(\n function Switcher(props, ref) {\n const {\n labels = {},\n\n disableThumb,\n } = useSwitcher()\n\n const leftLabel = labels[LabelPosition.LEFT]\n const rightLabel = labels[LabelPosition.RIGHT]\n\n return (\n \n \n {leftLabel ? : null}\n {!disableThumb ? : null}\n {rightLabel ? : null}\n
\n )\n }\n))\n\nexport type SwitcherProps = Props & SwitchProviderProps\n\nexport type { HandleChange as ChangeHandler } from '../context/definitions'\n\nexport const buttonClasses = {\n root: scssVariables.root,\n flag: scssVariables.flag,\n label: scssVariables.label,\n thumb: scssVariables.thumb,\n track: scssVariables.track,\n} as const", "import * as React from 'react'\n\nimport hashsum from 'hash-sum'\n\nimport { RippleOptions } from 'ui/_hooks/use-ripple'\n\nimport {\n HandleChange,\n\n LabelPosition,\n} from './definitions'\n\nexport interface SwitcherProviderProps {\n name: string\n\n form?: string\n\n labels?: [right?: string, left?: string] | readonly [right?: string, left?: string]\n\n checked: boolean\n onChange: HandleChange\n\n disableThumb?: boolean\n\n disableRipple?: boolean\n rippleOptions?: RippleOptions\n}\n\ninterface Children {\n children: React.ReactNode\n}\n\ninterface SwitcherContext extends Omit {\n flagId: string\n\n labels: {\n [LabelPosition.LEFT]?: string\n [LabelPosition.RIGHT]?: string\n }\n\n onChange: React.ChangeEventHandler\n}\n\nconst context = React.createContext({} as SwitcherContext)\nconst { Provider } = context\n\nexport const useSwitcher = () => React.useContext(context)\n\nconst SwitcherProvider: React.FC = ({\n children,\n\n ...props\n}) => {\n const flagId = React.useId()\n\n const _n = React.useRef(props.name)\n\n _n.current = props.name\n\n const context = React.useMemo(() => ({\n flagId,\n\n name: props.name,\n\n form: props.form,\n\n labels: {\n [LabelPosition.LEFT]: props.labels[LabelPosition.LEFT],\n [LabelPosition.RIGHT]: props.labels[LabelPosition.RIGHT],\n },\n\n checked: props.checked,\n onChange: e => props.onChange?.(e, e.target.checked, _n.current),\n\n disableThumb: props.disableThumb,\n\n disableRipple: props.disableRipple,\n rippleOptions: props.rippleOptions,\n }), [\n flagId,\n props.name,\n props.form,\n props.labels[LabelPosition.LEFT],\n props.labels[LabelPosition.RIGHT],\n props.checked,\n props.onChange,\n props.disableThumb,\n props.disableRipple,\n hashsum(props.rippleOptions),\n ])\n\n return (\n \n {children}\n \n )\n}\n\nexport default SwitcherProvider", "import * as React from 'react'\n\nimport SwitcherProvider, { SwitcherProviderProps as ProviderProps } from '.'\n\nconst withSwitcher = (\n Component: React.ComponentType>\n) => React.forwardRef(({\n name,\n\n form,\n\n labels,\n\n checked,\n onChange,\n\n disableThumb,\n\n disableRipple,\n rippleOptions,\n\n ...props\n}, ref) => (\n \n \n \n))\n\nexport type { ProviderProps as SwitchProviderProps }\n\nexport default withSwitcher", "import * as React from 'react'\nimport clsx from 'clsx'\n\nimport { useSwitcher } from '../context'\n\nimport scssVariables from '../variables.module.scss'\n\ntype BaseInputProps = React.DetailedHTMLProps, HTMLInputElement>\n\nexport interface FlagProps extends Omit { }\n\nexport default React.forwardRef(\n function Flag({\n className,\n\n ...props\n }, ref) {\n const {\n flagId,\n\n name,\n\n form,\n\n checked,\n\n onChange: handleChange,\n } = useSwitcher()\n\n return (\n \n )\n }\n)", "import 'css-chunk:src/variables.module.scss';export default {\n \"domain\": \"mono-ui_switcher\",\n \"same-width\": \"same-width\",\n \"root\": \"mono-ui_switcher\",\n \"flag\": \"mono-ui_switcher__flag\",\n \"label\": \"mono-ui_switcher__label\",\n \"thumb\": \"mono-ui_switcher__thumb\",\n \"track\": \"mono-ui_switcher__track\"\n};", "import * as React from 'react'\nimport clsx from 'clsx'\n\nimport { useSwitcher } from '../context'\n\nimport scssVariables from '../variables.module.scss'\n\ntype BaseLabelProps = React.DetailedHTMLProps, HTMLLabelElement>\n\nexport interface LabelProps extends Omit {\n children?: string\n}\n\nexport default React.forwardRef(\n function Label({\n className,\n\n children,\n\n ...props\n }, ref) {\n const { flagId } = useSwitcher()\n\n if (!children) {\n return null\n }\n\n return (\n \n )\n }\n)", "import * as React from 'react'\nimport clsx from 'clsx'\n\nimport useRipple from 'ui/_hooks/use-ripple'\n\nimport { useSwitcher } from '../context'\n\nimport scssVariables from '../variables.module.scss'\n\ntype BaseLabelProps = React.DetailedHTMLProps, HTMLLabelElement>\n\nexport interface ThumbProps extends Omit { }\n\nexport default React.forwardRef(\n function Thumb({\n className,\n\n ...props\n }, ref) {\n const {\n flagId,\n\n disableThumb,\n\n disableRipple,\n rippleOptions,\n } = useSwitcher()\n\n const [rippleClass] = useRipple({\n disableRipple: disableRipple || disableThumb,\n ...rippleOptions\n })\n\n return (\n \n )\n }\n)", "import * as React from 'react'\n\nimport ripple from 'ripple-effects'\nimport hashsum from 'hash-sum'\n\nexport type RippleOptions = Parameters[1]\n\ntype UseRippleOptions = RippleOptions & {\n disableRipple?: boolean\n}\n\ntype RippleDestroy = () => boolean\nconst NOOP_DESTROY: RippleDestroy = () => false\n\nconst useRipple = ({ disableRipple, ...rippleOptions }: UseRippleOptions) => {\n const id = React.useId()\n const rippleClass = React.useMemo(() => [id.replace(/:/g, ''), 'ripple'].join('-'), [id])\n\n const destroy = React.useRef(NOOP_DESTROY)\n\n React.useEffect(() => {\n if (!disableRipple) {\n const { destroy: rippleDestroy } = ripple(`.${rippleClass}`, {\n background: 'rgba(200, 200, 200, 0.75)',\n ...rippleOptions\n })\n\n destroy.current = () => {\n rippleDestroy()\n\n return true\n }\n\n return () => {\n rippleDestroy()\n }\n }\n }, [disableRipple, hashsum(rippleOptions)])\n\n return [rippleClass, destroy.current] as const\n}\n\nexport default useRipple", "import * as React from 'react'\n\nimport { Entity } from '@qwerty.software/ui-order-form/src/contexts/form-context'\n\nimport Decorator, { DecoratorProps } from './../../_decorator'\n\nimport { getConfigs } from 'global-entities/configs/utils/get'\n\nimport { UIOrderForm } from './form'\n\nimport StoreManager from '@qwerty.software/store-manager'\nimport { ORDER_SLICE_NAME } from '@qwerty.software/ui-order-form/src/store/slices/order/constants'\nimport { getQuerySearchFromOrderValues } from '@qwerty.software/ui-order-form/src/hooks/use-copy-order-to-clipboard'\nimport { InnerConfigs } from '@qwerty.software/ui-order-form/src/templates/_decorator/configs-context'\n\nexport interface UIOrderFormProps extends Omit {\n discount?: InnerConfigs['discount']\n}\n\nexport default React.memo(({\n configs = {},\n\n dictionary,\n\n discount,\n\n ...props\n}) => {\n const { orderPagePath, shouldRedirectToParentSite, parentSiteUrl, calculatorQueryFlow } = getConfigs()\n\n const handleSubmit = React.useCallback((e: React.FormEvent) => {\n e.preventDefault()\n\n const url = new URL(window.location.href)\n const searchParams = new URLSearchParams(url.search)\n let searchParamsFromOrderValues: URLSearchParams | null = null\n\n if (calculatorQueryFlow) {\n const orderValues = StoreManager.getInstance().store.getState()?.[ORDER_SLICE_NAME]\n\n if (orderValues) {\n searchParamsFromOrderValues = getQuerySearchFromOrderValues(orderValues, true)\n }\n }\n\n if (discount?.code) {\n searchParams.set('discount', discount.code)\n }\n\n const combinedParams = new URLSearchParams({\n ...Object.fromEntries(searchParams),\n ...Object.fromEntries(searchParamsFromOrderValues || [])\n }).toString()\n\n if (shouldRedirectToParentSite && parentSiteUrl) {\n window.location.href = `${window.location.protocol}//${parentSiteUrl}/${orderPagePath}${combinedParams.length ? '?' + combinedParams : ''}${url.hash}`\n return\n }\n\n window.location.href = `/${orderPagePath}${combinedParams.length ? '?' + combinedParams : ''}${url.hash}`\n }, [orderPagePath, shouldRedirectToParentSite, parentSiteUrl, calculatorQueryFlow])\n\n return (\n \n \n \n )\n})\n", "import * as React from 'react'\nimport { v4 as uuid } from 'uuid'\n\nimport _merge from 'lodash/merge'\n\nimport { NAME } from '@qwerty.software/ui-order-form/src/constants'\n\nimport { Entity } from './definitions'\n\nimport type { loadingEntities } from '@qwerty.software/ui-order-form/src/templates/dashboard/constants'\n\nimport type { IRawFile, RawOrder } from '@qwerty.software/ui-order-form/src/templates/dashboard/types'\n\nexport { Entity } from './definitions'\n\nexport interface IFormContext extends Omit, HTMLFormElement>, 'children'> {\n entity: Entity\n formRef?: React.MutableRefObject\n\n rawOrder?: RawOrder // dashboard only\n hasAdditionalPayment?: boolean // dashboard only\n rawFiles?: IRawFile[] // dashboard only\n loadingEntity?: loadingEntities // dashboard only\n\n formDifference?: {\n ConnectPriceData?: React.FunctionComponent\n sidebar?: React.FunctionComponent\n summary?: {\n changablePriceItems?: boolean\n PriceItemUnitsList?: React.FunctionComponent\n },\n formBottomBlock?: React.FunctionComponent\n tooltip?: {\n triggers?: Array<'hover' | 'click'>\n },\n checkBoxIcons?: {\n checked: React.FunctionComponent\n unchecked: React.FunctionComponent\n },\n additionalFeatures?: {\n AdditionalFeatureSpecial: React.FunctionComponent\n useShortTitle?: boolean\n },\n WriterCategoryButton?: React.FunctionComponent\n upsalesSpecificOrder?: Array\n calculator?: {\n Footer?: React.FunctionComponent\n }\n MaterialsIcon?: React.FunctionComponent\n MaterialsRemoveIcon?: React.FunctionComponent\n withNumberInputSvgButton?: boolean\n\n priceCalculator?: any\n enabledSoftwares?: number[]\n }\n}\n\nexport const INITIAL_CONFIGS: Omit = {\n id: uuid(),\n name: NAME,\n method: 'GET',\n action: window.location.href,\n hidden: true,\n}\n\nexport const FormContext = React.createContext(INITIAL_CONFIGS as IFormContext)\n\nexport const FormProvider = React.memo<{\n entity: Entity\n formProps: Partial>\n formDifference?: IFormContext['formDifference']\n\n rawOrder?: RawOrder // dashboard only\n hasAdditionalPayment?: boolean // dashboard only\n rawFiles?: IRawFile[] // dashboard only\n loadingEntity?: loadingEntities // dashboard only\n\n children: React.ReactNode\n}>(({\n entity,\n formProps,\n\n formDifference,\n\n rawOrder,\n hasAdditionalPayment,\n loadingEntity,\n rawFiles,\n\n children,\n}) => {\n const formRef = React.useRef(null)\n\n const attrs = _merge({\n ...INITIAL_CONFIGS,\n }, formProps)\n\n return (\n \n \n {children}\n \n )\n})\n\nexport const useFormContext = () => React.useContext(FormContext)\n", "import * as React from 'react'\nimport type { DeepPartial } from '@reduxjs/toolkit'\nimport { BrowserRouter } from 'react-router-dom'\nimport defaultCalculator from '@qwerty.software/calc-of-price/adapters/microservices'\n\nimport { ConfigsProvider, InnerConfigs } from './configs-context'\nimport { DictionaryProvider, IDictionaryContext } from '@qwerty.software/ui-order-form/src/contexts/dictionary-context'\nimport { FormProvider, IFormContext } from '@qwerty.software/ui-order-form/src/contexts/form-context'\n\nimport { withDiscount } from 'global-entities/discount/with-discount'\nimport { withFileUploader } from 'global-entities/files-uploader/with-files-uploader'\n\nimport useSlices from '@qwerty.software/store-manager/hooks/use-slices'\n\nimport ConfigureNotify from 'utils/notify/configure-notify'\n\nimport StoreGate from 'common/store-gate'\n\nimport * as order from '@qwerty.software/ui-order-form/src/store/slices/order'\nimport * as user from '@qwerty.software/ui-order-form/src/store/slices/user'\nimport * as priceData from '@qwerty.software/ui-order-form/src/store/slices/price-data'\n\nimport usePriceData from '@qwerty.software/ui-order-form/src/store/slices/price-data/usePriceData'\nimport useUserData from 'global-entities/user-data/hook'\nimport { useMarkOrderPageAsVisited } from 'hooks/use-mark-order-page-as-visited'\n\nimport GeoTag from 'global-entities/geo-tag'\nimport { CURRENCY_SLICE_PERSIST_CONFIG, currencySlice } from '@qwerty.software/currency-switcher/src/store/slice'\nimport { ORDER_NAMESPACE } from '@qwerty.software/ui-order-form/src/constants'\nimport { useClearAfterTime } from 'hooks/use-clear-after-time'\nimport { FORCE_HIDE_TURNITIN_UPSALE } from 'constants/configs'\n\nexport interface ProvidersProps {\n dictionary?: DeepPartial\n\n // TODO: @required\n configs?: DeepPartial\n // TODO: @required\n entity?: IFormContext['entity']\n formProps?: Partial>\n formDifference?: IFormContext['formDifference']\n}\n\nexport interface DecoratorProps extends ProvidersProps {\n withPriceData?: boolean\n withUserData?: boolean\n\n children?: React.ReactNode\n}\n\nconst ConnectPriceData = React.memo(() => {\n usePriceData({ calculator: defaultCalculator })\n\n return null\n})\n\nconst ConnectUserData = React.memo(() => {\n useUserData()\n\n return null\n})\n\n// we need to clear the order form 24 hours after the last change\nconst ClearDataViaExpire = React.memo(() => {\n useClearAfterTime()\n\n return null\n})\n\nconst MarkOrderPageAsVisited = React.memo(() => {\n useMarkOrderPageAsVisited()\n\n return null\n})\n\nconst Decorator = React.memo(({\n dictionary = {},\n configs = {},\n\n entity = null,\n formProps = {},\n\n // is important to be empty object because we don't need all form differences in each form\n // pass difference only for current difference needed form\n formDifference = {},\n\n children,\n}) => {\n\n // this is here because we need to hide turnitin for all projects without manually adding it to each one\n // just comment this when you need to show turnitin\n React.useEffect(() => {\n window.MICROSERVICES_CONFIGS = {\n ...window.MICROSERVICES_CONFIGS,\n [FORCE_HIDE_TURNITIN_UPSALE]: true,\n }\n }, [])\n\n useSlices([\n [order.orderSlice, order.COMMON_PERSIST_CONFIG],\n [currencySlice, CURRENCY_SLICE_PERSIST_CONFIG],\n [priceData.priceDataSlice],\n [user.userSlice],\n ])\n\n const ConnectPriceDataComponent = formDifference?.ConnectPriceData ? formDifference.ConnectPriceData : ConnectPriceData\n\n return (\n // Comment here because it makes additional render and order bot works wrong\n \n \n \n \n \n \n \n \n \n \n \n {children}\n \n \n \n \n \n // \n )\n})\n\nconst WithDiscountComponent = withDiscount({\n namespace: ORDER_NAMESPACE,\n Component: Decorator,\n options: { searchParam: ['discount', 'discountCode'] }\n})\nconst WithFileUploaderComponent = withFileUploader(ORDER_NAMESPACE, WithDiscountComponent)\n\nexport default WithFileUploaderComponent\n", "import * as React from 'react'\nimport type { DeepPartial } from '@reduxjs/toolkit'\n\nimport type { Configs } from 'common/configs/types'\n\nimport _merge from 'lodash/merge'\n\nexport interface InnerConfigs {\n cashback?: number\n discount?: {\n code: string\n percent?: number\n }\n\n disablePageWordsSwitcher?: boolean\n\n estimatedPriceBefore?: React.ReactNode\n\n summaryAfter?: React.ReactNode\n\n extender?: {\n show: boolean\n withLabel: boolean\n }\n}\n\nexport type { Configs } from 'common/configs/types'\n\nexport interface IConfigsContext extends InnerConfigs, Configs { }\n\nexport const INITIAL_CONFIGS: IConfigsContext = {\n disablePageWordsSwitcher: false,\n\n extender: {\n show: false,\n withLabel: false,\n }\n}\n\nconst ConfigsContext = React.createContext(INITIAL_CONFIGS)\n\nexport const ConfigsProvider = React.memo<{\n configs: DeepPartial\n children: React.ReactNode\n}>(({ configs = {}, children }) => (\n \n {children}\n \n))\n\nexport const useConfigsContext = () => React.useContext(ConfigsContext)\n", "import * as React from 'react'\nimport Template from 'utils/dictionary/t'\n\nimport _merge from 'lodash/merge'\nimport _get from 'lodash/get'\nimport { DeepPartial } from '@reduxjs/toolkit'\n\nimport INITIAL_DICTIONARY, {\n Diction,\n DictionaryContext as IDictionaryContext,\n PlaceholderMap,\n} from './dictionary'\n\nexport interface DictionaryProviderProps {\n dictionary: DeepPartial\n\n children: React.ReactNode\n}\n\ntype dArgs> = T extends keyof PlaceholderMap\n ? [path: T, data: PlaceholderMap[T] | null]\n : [path: T]\n\nconst DictionaryContext = React.createContext(INITIAL_DICTIONARY)\n\nexport const DictionaryProvider = React.memo(({\n dictionary = {},\n\n children,\n}) => (\n \n {children}\n \n))\n\nexport const useDictionary = () => {\n const dictionary = React.useContext(DictionaryContext)\n\n return React.useCallback(>(...args: dArgs) => {\n const [path, data] = args\n\n const diction: Diction = _get(dictionary, path)\n const reactKey = `key: ${diction}`\n\n if (data === null) {\n return typeof diction === 'string'\n }\n\n if (diction === false) {\n return null\n }\n\n if (!diction) {\n return ''\n }\n\n if (!data) {\n return diction\n }\n\n return new Template(reactKey).fill(diction, data)\n }, [dictionary])\n}\n\nexport default DictionaryContext\n\nexport { default as INITIAL_DICTIONARY } from './dictionary'\n\nexport type {\n Diction,\n DictionaryContext as IDictionaryContext,\n PlaceholderMap,\n} from './dictionary'", "import * as React from 'react'\n\nimport _every from 'lodash/every'\nimport _isString from 'lodash/isString'\n\ninterface ITranslateOptions {\n before?: string\n after?: string\n}\n\nclass Template {\n private BEFORE!: string\n private AFTER!: string\n\n constructor(private reactKey: string, {\n before = '[:',\n after = ']',\n }: ITranslateOptions = {}) {\n this.BEFORE = this.escape(before)\n this.AFTER = this.escape(after)\n }\n\n protected escape(str: string): string {\n return str.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&') // escape for RegExp\n }\n\n protected match(str: string) {\n return str.match(this.getPattern('g'))\n }\n\n private getPattern(flags: string): RegExp {\n return new RegExp(`(${this.BEFORE}(?.+?)${this.AFTER})`, flags)\n }\n\n public getToken(placeholder: string): string | null {\n const { groups = {} } = placeholder.match(this.getPattern('')) || {}\n\n return groups.placeholder ?? null\n }\n\n public fill(template: string, data?: Record): React.ReactNode[] | string {\n const placeholders = this.match(template)\n\n if (!placeholders) {\n return [template]\n }\n\n const res = placeholders.reduce((accumulator, placeholder) => {\n const placeholderToken = this.getToken(placeholder)\n\n if (!placeholderToken || !data || typeof data[placeholderToken] === 'undefined') {\n return accumulator\n }\n\n return accumulator.reduce((parts: React.ReactNode[], substr) => {\n if (typeof substr !== 'string') {\n parts.push(substr)\n\n return parts\n }\n\n const _parts: React.ReactNode[] = substr.split(placeholder)\n\n if (_parts.length > 1) {\n for (let i = _parts.length; i-- > 1;) {\n\n _parts.splice(i, 0, data[placeholderToken] ?? null)\n }\n }\n\n parts.push(..._parts)\n\n return parts\n }, [] as React.ReactNode[])\n }, [template] as React.ReactNode[]) as React.ReactNode[]\n\n if (_every(res, _isString)) {\n return res.join('')\n }\n\n return res.map((element, index) => (\n \n {element}\n \n ))\n }\n}\n\nexport default Template", "import { UpsaleIds } from '@qwerty.software/ui-order-form/src/store/constants'\n\nexport type Diction = string | false\n\nconst INITIAL_DICTIONARY: DictionaryContext = {\n title: 'Calculate the price',\n price: {\n caption: 'Total price:',\n bottomCaption: 'Current price:',\n amount: '[:currency][:price]',\n amountRightCurrency: '[:price][:currency]',\n\n summary: {\n complexAssignment: 'Complex Assignment',\n speakerNotes: 'Speaker Notes',\n writerCategory: {\n bestAvailable: 'Best available',\n proWriter: 'PRO writer',\n topWriter: 'TOP writer',\n preferredWriter: 'Preferred writer',\n },\n additionalFeature: {\n plagiarismReport: 'Plagiarism report',\n progressiveDelivery: 'Progressive delivery',\n summary: 'Summary',\n draft: 'Draft',\n abstractPage: 'Abstract',\n grammarlyReport: 'Grammarly Report',\n },\n softCopies: 'Soft Copies',\n software: 'Software',\n },\n },\n titles: {\n dashboard: {\n fieldsMain: 'Paper information',\n fieldsAdditional: 'Extra features',\n },\n inquiry: 'Get a Quote for Your Task',\n stepless: 'Write your order details here:',\n materials: {\n dragMessage: 'Upload files',\n },\n discount: {\n currencyDiscount: 'Bonus [:currency][:amount]',\n secondPageDiscount: '50% off every 2nd page',\n thirdPageDiscount: '50% off every 3rd page',\n },\n singleViewSteps: {\n details: 'Details',\n personalInformation: 'Personal information',\n },\n writerCategory: {\n bestAvailable: 'Regular',\n proWriter: 'Pro',\n topWriter: 'Top',\n preferredWriter: 'Preferred',\n }\n },\n subtitles: {\n inquiry: 'We will get back to you in 5 minutes or less',\n },\n labels: {\n extender: 'Switch to:',\n paperType: 'Type of paper',\n subject: 'Subject',\n topic: 'Topic',\n paperDetails: 'Paper details',\n paperRequirements: 'Paper requirements',\n materials: 'Materials',\n paperFormat: 'Paper format',\n academicLevel: 'Academic level',\n workType: 'Type of work',\n deadline: 'Deadline',\n quantity: 'Quantity',\n pagesWordsSwitcher: {\n pages: 'Pages',\n words: 'Words',\n },\n spacing: 'Spacing',\n slides: 'Number of slides',\n speakerNotes: 'Speaker notes',\n sources: 'Sources',\n softCopies: 'Soft copies',\n writerCategory: 'Choose your writer',\n preferredWriter: 'Writer from order ID[:description]',\n additionalFeatures: 'Additional features',\n software: 'Software',\n discount: 'Discount',\n\n auth: {\n email: 'Email [:required]',\n phone: 'Phone number [:required]',\n password: 'Password [:required]',\n\n tabs: {\n orderForm: {\n signin: 'I have an account',\n signup: 'I am new here',\n social: 'Social Account',\n },\n },\n },\n\n summary: {\n freeFeature: 'Free features',\n\n amendments: 'Amendments',\n bibliography: 'Bibliography',\n outline: 'Outline',\n titlePage: 'Title page',\n formatting: 'Formatting',\n chosenPackage: 'Chosen package',\n },\n },\n descriptions: {\n materials: {\n dragMessage: 'or drag your files here',\n },\n preferredWriter: '(for returning customers only)',\n },\n tooltips: {\n writerCategory: {\n bestAvailable: false,\n proWriter: false,\n topWriter: false,\n preferredWriter: false,\n },\n extender: 'Choose an Extended version if you have a lot of details for your paper, or switch to a Quick form for brief instructions',\n paperType: 'Please select the most appropriate type of paper needed. If the type of paper you need is not on the list, leave the default choice \"Essay\" and specify what you need in the \"Paper details\" field.',\n subject: 'Please select the most appropriate field of studies or the name of the class you have an assignment for. If the subject you need is not on the list, choose \"Other\" and specify what you need in the \"Paper details\" field.',\n topic: 'Please enter the specific title or topic for your paper, if you have one.',\n paperDetails: 'Please leave a detailed explanation of your requirements to make sure the writer is on the right track and decrease chances of revision in your order.',\n materials: 'You may upload useful materials to the writer now or after finishing this form.',\n paperFormat: 'Please specify the format of the paper if needed. Otherwise leave it as is.',\n academicLevel: 'Please select an appropriate academic level that corresponds to your level of writing.',\n workType: 'Please choose the service you are looking for. \"Writing from scratch\" means that you will get a custom written paper. \"Editing/proofreading\" means you will upload your own paper that the writer will revise. \"Problem solving\" suits assignments in Math or Economics, etc. Paraphrasing means re-writing the paper in other words with the same meaning and structure. \"Multiple choice questions\" means choosing one or several answers from offered options.',\n deadline: 'How soon do you want to receive your order? Please consider that it takes about 1 hour to complete 1 page of high quality text.',\n quantity: {\n pages: 'Please choose how many pages you need. 1 double spaced page is approximately 275 words, 1 single spaced page is approximately 550 words. Title and bibliography pages are included for free.',\n words: 'Please choose how many words you need. 275 words with double spacing or 550 words with single spacing is approximately 1 page. Title and bibliography are included for free.',\n problems: 'Please choose how many problems you want to solve.',\n },\n spacing: '1 double spaced page is approximately 275 words, 1 1.5 spaced page is approximately 400 words, 1 single spaced page is approximately 550 words.',\n slides: 'Impress your professors with a high-quality presentation. Choose how many slides it should have. Add speaker notes to present to the audience',\n speakerNotes: 'Additional notes written to accompany slides for the presenter to use during the presentation',\n disabledSpeakerNotes: 'Please choose the number of slides first, and then you will be able to select speaker notes',\n sources: 'The number of sources to be used in the paper. Bibliography page is included for free. Receive printable PDF/DOC sources cited in the paper as \"Soft copies\" for $4 per source.',\n softCopies: 'Digital versions of sources used by the writer that you can receive in electronic format',\n disabledSoftCopies: 'Please choose the number of sources first, and then you will be able to select softcopies',\n additionalFeatures: {\n appliedFetatureTooltipText: 'This feature is already applied to your order',\n disabled: {\n aiCheckReport: {\n default: 'AI writing detection tool is unavailable for less than 400 words or more than 15000',\n },\n resume101Org: {\n default: 'Follow-up/\"Thank You\" Letter is a part of the chosen Package',\n },\n multiplyChoiseQuestions: {\n default: 'This feature is not available for the Multiple choice questions work type',\n },\n },\n },\n preferredWriter: {\n noData: 'Please cancel the current order ID first to be able to enter a new one',\n },\n software: 'Specialized software work included (additional fees apply).',\n discount: 'Placed orders with us before? Check with support agent for a loyalty discount.',\n disabledSoftware: 'If you want to choose some software type you should enable field via checkbox',\n reset: 'For your convenience and security, we keep order form inputs if you navigate to another page accidentally, and automatically clear everything in 24 hours. This way you are protected from having to enter all the information again if anything goes wrong, and your privacy is still 100% secure.',\n },\n placeholders: {\n topic: 'Writer\u2019s choice',\n paperDetails: 'If you have any specific requirements, please add them here',\n preferredWriter: 'Order # ...',\n discount: 'Enter discount code',\n },\n hint: {\n materials: 'Maximum file size is 25 MB',\n deadline: 'Ready by [:time] [:date]',\n quantity: 'Approximately [:amount] [:quantity]',\n paperDetails: 'Please tell us a little more about your task [:minDetailsLenght] - [:maxDetailsLenght] characters)',\n paperRequirements: 'Max file size 25 MB (doc, docx, pdf, rtf, excel)',\n preferredWriter: {\n main: 'Copypaste order ID from Dashboard',\n login: {\n unauthorized: 'Please[:login]first',\n authorized: 'Please enter order ID or choose another writer category',\n noWriters: 'There are no orders with writers on your account.',\n noWritersFromSubmit: 'There are no orders with writers on your account. Please choose another writer category',\n unauthorizedFromSubmit: 'Please[:login]first and enter order ID or choose another writer category'\n },\n policy: 'You accept [:policy]',\n bestAvailable: 'Success!',\n pro: 'your preferred writer has a PRO category',\n top: 'your preferred writer has a TOP category',\n },\n\n auth: {\n email: 'We promise not to spam you',\n phone: 'We wont share phone number with third parties',\n //by creating account with us you agree to our Terms and Conditions, Money Back Guarantee, Privacy Policy and to be contacted regarding your orders\n socialAgreements: 'by creating account with us you agree to our [:terms-and-conditions], [:money-back-guarantee], [:privacy-policy] and to be contacted regarding your orders'\n },\n\n summary: {\n complexAssignment: 'Additional fee charged for completing an order that requires special knowledge and more advanced research skills',\n preferredWriter: 'Please note: your preferred writer has a [:title] category, you will pay [:percent]% more',\n software: 'Specialized software work included (additional fees apply).',\n },\n },\n marks: {\n additionalFeatures: {\n popular: 'Popular',\n },\n summary: {\n free: 'free',\n }\n },\n cashback: {\n oldPriceCaption: 'Standart price',\n oldPrice: '[:currency][:price]',\n priceCaption: '[:cashback]% CASHBACK',\n price: '[:currency][:price]',\n },\n buttons: {\n stepper: {\n step1: 'Paper information',\n step2: 'Price calculation',\n step3: 'Extra features',\n },\n calculator: {\n submit: 'Continue',\n },\n inquiry: {\n submit: 'Get help now',\n },\n preferredWriter: {\n cancel: 'Cancel',\n submit: 'Apply',\n },\n orderForm: {\n reset: 'Clear the order form',\n submit: 'Submit [:price] [:loader]',\n step1: {\n previous: 'Previous',\n next: 'Next',\n },\n step2: {\n previous: 'Previous',\n next: 'Next',\n },\n step3: {\n previous: 'Previous',\n next: 'Next',\n },\n },\n materials: \"Upload files\",\n dashboard: {\n favoriteWriterAddText: false,\n favoriteWriterRemoveText: false\n }\n },\n links: {\n login: 'login',\n auth: {\n forgotPassword: 'Forgot password ?',\n changeAccount: 'Change account',\n },\n preferredWriter: {\n login: 'login',\n policy: 'Preferred writer policy',\n },\n termsAndConditions: 'Terms and Conditions',\n moneyBackGuarantee: 'Money Back Guarantee',\n privacyPolicy: 'Privacy Policy',\n\n discounts: 'Find a valid discound code here',\n\n contacts: {\n whatsup: {\n formatted: false,\n link: false,\n },\n }\n },\n notifications: {\n discount: {\n cancel: 'Your discount is canceled. You have changed the conditions of use.',\n },\n },\n resetModal: 'Are you sure you want to clear the order form?',\n auth: {\n loggedTextFirstLine: 'You are logged in as [:email]',\n loggedTextSecondLine: 'Not you? [:link]',\n },\n moment: {\n deadline: {\n time: 'hh:mmA',\n date: 'MMMM DD, YYYY',\n },\n },\n}\n\nexport type PlaceholderMap = {\n 'titles.discount.currencyDiscount': Record<'currency' | 'amount', React.ReactNode>\n 'labels.preferredWriter': Record<'description', React.ReactNode>\n 'labels.auth.email': Record<'required', React.ReactNode>\n 'labels.auth.phone': Record<'required', React.ReactNode>\n 'labels.auth.password': Record<'required', React.ReactNode>\n 'hint.deadline': Record<'time' | 'date', React.ReactNode>\n 'hint.quantity': Record<'amount' | 'quantity', React.ReactNode>\n 'hint.paperDetails': Record<'minDetailsLenght' | 'maxDetailsLenght', React.ReactNode>\n 'hint.preferredWriter.login.unauthorized': Record<'login', React.ReactNode>\n 'hint.preferredWriter.login.unauthorizedFromSubmit': Record<'login', React.ReactNode>\n 'hint.preferredWriter.policy': Record<'policy', React.ReactNode>\n 'hint.auth.socialAgreements': Record<'terms-and-conditions' | 'money-back-guarantee' | 'privacy-policy', React.ReactNode>\n 'hint.summary.preferredWriter': Record<'title' | 'percent', React.ReactNode>\n 'cashback.priceCaption': Record<'cashback', React.ReactNode>\n 'cashback.oldPrice': Record<'price' | 'currency', React.ReactNode>\n 'cashback.price': Record<'price' | 'currency', React.ReactNode>\n 'price.amount': Record<'price' | 'currency', React.ReactNode>\n 'price.amountRightCurrency': Record<'price' | 'currency', React.ReactNode>\n 'buttons.orderForm.submit': Record<'price' | 'loader', React.ReactNode>\n 'auth.loggedTextFirstLine': Record<'email', React.ReactNode>\n 'auth.loggedTextSecondLine': Record<'link', React.ReactNode>\n}\n\nexport default INITIAL_DICTIONARY\n\nexport interface DictionaryContext {\n title: Diction\n price: {\n caption: Diction\n bottomCaption: Diction\n amount: Diction\n amountRightCurrency: Diction\n\n summary: {\n complexAssignment: Diction\n speakerNotes: Diction\n writerCategory: {\n bestAvailable: Diction\n proWriter: Diction\n topWriter: Diction\n preferredWriter: Diction\n }\n additionalFeature: {\n plagiarismReport: Diction\n progressiveDelivery: Diction\n summary: Diction\n draft: Diction\n abstractPage: Diction\n grammarlyReport: Diction\n }\n softCopies: Diction\n software: Diction\n }\n },\n cashback: {\n oldPriceCaption: Diction\n priceCaption: Diction\n oldPrice: Diction\n price: Diction\n }\n titles: {\n dashboard: {\n fieldsMain: Diction\n fieldsAdditional: Diction\n }\n inquiry: Diction\n stepless: Diction\n materials: {\n dragMessage: Diction\n }\n discount: {\n currencyDiscount: Diction\n secondPageDiscount: Diction\n thirdPageDiscount: Diction\n }\n singleViewSteps: {\n details: Diction\n personalInformation: Diction\n }\n writerCategory: {\n bestAvailable: Diction\n proWriter: Diction\n topWriter: Diction\n preferredWriter: Diction\n }\n }\n subtitles: {\n inquiry: Diction\n }\n labels: {\n extender: Diction\n paperType: Diction\n subject: Diction\n topic: Diction\n paperDetails: Diction\n paperRequirements: Diction\n materials: Diction\n paperFormat: Diction\n academicLevel: Diction\n workType: Diction\n deadline: Diction\n quantity: Diction\n pagesWordsSwitcher: {\n pages: Diction\n words: Diction\n }\n spacing: Diction\n slides: Diction\n speakerNotes: Diction\n sources: Diction\n softCopies: Diction\n writerCategory: Diction\n preferredWriter: Diction\n additionalFeatures: Diction\n software: Diction\n discount: Diction\n\n auth: {\n email: Diction\n phone: Diction\n password: Diction\n\n tabs: {\n orderForm: {\n signin: Diction\n signup: Diction\n social: Diction\n }\n }\n }\n\n summary: {\n freeFeature: Diction\n\n amendments: Diction\n bibliography: Diction\n outline: Diction\n titlePage: Diction\n formatting: Diction\n chosenPackage: Diction\n }\n }\n descriptions: {\n materials: {\n dragMessage: Diction\n }\n preferredWriter: Diction\n }\n tooltips: {\n extender: Diction\n paperType: Diction\n subject: Diction\n topic: Diction\n paperDetails: Diction\n materials: Diction\n paperFormat: Diction\n academicLevel: Diction\n workType: Diction\n writerCategory: {\n bestAvailable: Diction\n proWriter: Diction\n topWriter: Diction\n preferredWriter: Diction\n }\n deadline: Diction\n quantity: {\n pages: Diction\n words: Diction\n problems: Diction\n }\n spacing: Diction\n slides: Diction\n speakerNotes: Diction\n disabledSpeakerNotes: Diction\n sources: Diction\n softCopies: Diction\n disabledSoftCopies: Diction\n additionalFeatures: {\n appliedFetatureTooltipText: Diction\n disabled: {\n aiCheckReport: {\n [key in UpsaleIds]?: Diction\n } & { default: Diction }\n resume101Org: {\n [key in UpsaleIds]?: Diction\n } & { default: Diction }\n multiplyChoiseQuestions: {\n [key in UpsaleIds]?: Diction\n } & { default: Diction }\n }\n }\n preferredWriter: {\n noData: Diction\n }\n software: Diction\n discount: Diction\n disabledSoftware: Diction\n reset: Diction\n }\n placeholders: {\n topic: Diction\n paperDetails: Diction\n preferredWriter: Diction\n discount: Diction\n }\n hint: {\n materials: Diction\n deadline: Diction\n quantity: Diction\n paperDetails: Diction\n paperRequirements: Diction\n preferredWriter: {\n main: Diction\n login: {\n unauthorized: Diction\n authorized: Diction\n noWriters: Diction\n noWritersFromSubmit: Diction\n unauthorizedFromSubmit: Diction\n }\n policy: Diction\n bestAvailable: Diction\n pro: Diction\n top: Diction\n }\n\n auth: {\n email: Diction\n phone: Diction\n socialAgreements: Diction\n }\n\n summary: {\n complexAssignment: Diction\n preferredWriter: Diction\n software: Diction\n }\n }\n marks: {\n additionalFeatures: {\n popular: Diction\n }\n summary: {\n free: Diction\n }\n }\n buttons: {\n stepper: {\n step1: Diction\n step2: Diction\n step3: Diction\n }\n calculator: {\n submit: Diction\n }\n inquiry: {\n submit: Diction\n }\n preferredWriter: {\n cancel: Diction\n submit: Diction\n }\n orderForm: {\n reset: Diction\n submit: Diction\n step1: {\n previous: Diction\n next: Diction\n }\n step2: {\n previous: Diction\n next: Diction\n }\n step3: {\n previous: Diction\n next: Diction\n }\n }\n materials: Diction\n dashboard: {\n favoriteWriterAddText: Diction\n favoriteWriterRemoveText: Diction\n }\n }\n links: {\n login: Diction\n auth: {\n forgotPassword: Diction\n changeAccount: Diction\n }\n preferredWriter: {\n login: Diction\n policy: Diction\n }\n termsAndConditions: Diction\n moneyBackGuarantee: Diction\n privacyPolicy: Diction\n\n discounts: Diction\n\n contacts: {\n whatsup: {\n formatted: Diction\n link: Diction\n }\n }\n }\n notifications: {\n discount: {\n cancel: Diction\n }\n }\n resetModal: Diction\n auth: {\n loggedTextFirstLine: Diction\n loggedTextSecondLine: Diction\n }\n moment: {\n deadline: {\n time: Diction\n date: Diction\n }\n },\n}\n", "import * as React from 'react'\n\nimport StoreManager from '@qwerty.software/store-manager'\nimport StoreManagerInitializer from '@qwerty.software/store-manager/initializer'\n\nimport singleton from 'helpers/singleton'\n\nimport checkSearchParam, { normalizeSearchParam } from './side-effects/search-param'\n\nimport Discount from './selectors'\nimport { applyDiscount } from './definitions'\n\nconst NamespaceContext = React.createContext(null)\n\nconst storeInitializer = StoreManagerInitializer.getInstance()\n\nexport interface Options {\n /**\n * string or string array for redeclare search param\n * true for enable with default search param name\n */\n searchParam?: string | string[] | true\n useCheckRoute?: boolean\n disableAutoApply?: boolean\n disableApplyViaSearch?: boolean\n}\n\nexport const useNamespace = () => {\n const context = React.useContext(NamespaceContext)\n\n if (context === null) {\n throw new Error('\"useNamespace\" of \"discount\" must be used within a \"NamespaceProvider\"')\n }\n\n return context\n}\n\nconst onceSet = singleton('916c7bce-669b-4a7a-92d0-a4508c55775b', () => new Set())\n\ninterface WithDiscountProps {\n Component: React.ComponentType,\n namespace: string\n options?: Options\n}\n\nexport const withDiscount = ({\n Component,\n namespace,\n options,\n}: WithDiscountProps) => {\n const searchParam = normalizeSearchParam(options?.searchParam)\n\n const decorated = React.forwardRef((props, ref) => (\n \n \n \n ))\n\n if (onceSet.has(namespace)) {\n return decorated\n }\n onceSet.add(namespace)\n\n if (!options?.disableAutoApply) {\n storeInitializer.addEventListener('init', () => {\n const { store } = StoreManager.getInstance()\n\n const { sended } = Discount(namespace).DISCOUNT(store.getState())\n\n if (sended) {\n store.dispatch(applyDiscount(namespace, { disableNotify: true, useCheckRoute: options?.useCheckRoute }))\n }\n }, {\n once: true,\n })\n }\n\n if (!searchParam) {\n return decorated\n }\n\n storeInitializer.addEventListener('init', () => {\n const { store } = StoreManager.getInstance()\n\n store.dispatch(checkSearchParam({ namespace, searchParam }))\n }, {\n once: true,\n })\n\n return decorated\n}", "/**\n * An observer that can be used to monitor the initialization state of the storage manager\n */\ninterface IInitializer extends EventTarget {\n isInitialized(): boolean\n}\n\ninterface IInitEvent extends Event {\n /**\n * Flag which signal about synthetic call for callbacks or real clear init event\n */\n isFresh: boolean\n}\n\nabstract class Initializer extends EventTarget implements IInitializer {\n static FreshInitEvent = class extends Event implements IInitEvent {\n public isFresh: boolean = true\n\n constructor(eventInitDict?: EventInit) {\n super('init', eventInitDict)\n }\n }\n\n static InitEvent = class extends Event implements IInitEvent {\n public isFresh: boolean = false\n\n constructor(eventInitDict?: EventInit) {\n super('init', eventInitDict)\n }\n }\n\n private _isInitialized: boolean = false\n\n public isInitialized = (): boolean => {\n return this._isInitialized\n }\n\n /**\n * Overriding addEventListener for \"init\" event:\n * dispatching all callbacks immediately if assigned new listener after it initialized\n */\n public addEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void {\n if (this._isInitialized && type === 'init') {\n const cb = typeof callback === 'function' ? callback : callback.handleEvent\n\n cb(new Initializer.InitEvent())\n }\n\n super.addEventListener(type, callback, options)\n }\n\n protected initialized = () => {\n if (this._isInitialized) {\n return\n }\n\n this._isInitialized = true\n\n this.dispatchEvent(new Initializer.FreshInitEvent())\n\n console.log('Store initialized')\n }\n}\n\nexport default Initializer", "import InitializerObserver from './absrtact-initializer'\n\nimport { ConfigsMapType } from 'global-entities/configs/utils/init'\nimport { BootstrapData } from 'global-entities/bootstrap-data/utils/init'\n\nimport type { StoreManagerClass } from '.'\n\nclass Initializer extends InitializerObserver {\n private constructor() { super() }\n\n static getInstance() {\n window.__storeManagerInitializer = window.__storeManagerInitializer || new Initializer()\n\n return window.__storeManagerInitializer\n }\n\n static async init(StoreManager: StoreManagerClass, configs: ConfigsMapType, bootstrapData: BootstrapData.ICore) {\n const instance = Initializer.getInstance()\n\n return new Promise((resolve) => {\n instance.addEventListener('init', handleInited)\n\n instance.init(StoreManager, configs, bootstrapData)\n\n function handleInited(e) {\n instance.removeEventListener('init', handleInited)\n\n resolve(true)\n }\n })\n }\n\n private init(StoreManager: StoreManagerClass, configs: ConfigsMapType, bootstrapData: BootstrapData.ICore) {\n if (this.isInitialized()) {\n console.warn('Store already initialized')\n\n return\n }\n\n require('global-entities/configs/utils/init')\n .initConfigs(configs)\n\n require('global-entities/bootstrap-data/utils/init')\n .initBootstrapData(bootstrapData)\n\n StoreManager.init(this.initialized)\n }\n}\n\nexport const storeManagerInitializer = Initializer.getInstance()\n\nexport { KEY as CONFIGS_KEY } from 'global-entities/configs/utils/init'\nexport { KEY as BOOTSTRAP_DATA_KEY } from 'global-entities/bootstrap-data/utils/init'\n\nexport default Initializer\n\ndeclare global {\n interface Window {\n __storeManagerInitializer?: Initializer\n }\n}", "import { createAction } from '@reduxjs/toolkit'\n\nimport { slice as discountSlice } from 'global-entities/discount/slice'\n\nimport { applyDiscount } from 'global-entities/discount/definitions'\n\nimport { discountListener } from '.'\n\nimport { CHECK_SEARCH_PARAM } from '../definitions'\n\nconst DEFAULT_SEARCH_PARAM = 'discount'\n\nexport const checkSearchParamAction = createAction<{\n namespace: string,\n searchParam: string[]\n}>(CHECK_SEARCH_PARAM)\n\ndiscountListener.startListening({\n actionCreator: checkSearchParamAction,\n\n effect(action, api) {\n const { namespace, searchParam } = action.payload\n\n const url = new URL(window.location.href)\n\n // search between all searchParam names\n const searchParamName = searchParam\n .find(param => Boolean(url.searchParams.get(param)))\n\n if (!searchParamName) {\n return\n }\n\n const code = url.searchParams.get(searchParamName) as string\n\n setTimeout((url, key) => {\n url.searchParams.delete(key)\n\n window.history.replaceState({}, document.title, url.toString())\n }, 0, url, searchParamName)\n\n api.dispatch(discountSlice.actions.setCode({ namespace, code }))\n api.dispatch(applyDiscount(namespace))\n },\n})\n\nexport function normalizeSearchParam(searchParam: string | string[] | boolean = true): string[] | null {\n switch (searchParam) {\n case false:\n return null\n\n case true:\n searchParam = DEFAULT_SEARCH_PARAM\n break\n\n default: break\n }\n\n return !Array.isArray(searchParam)\n ? [searchParam]\n : searchParam\n}\n\nexport default checkSearchParamAction", "import * as React from 'react'\n\nimport './side-effects/notifications'\n\nconst NamespaceContext = React.createContext(null)\n\nexport const useNamespace = () => {\n const context = React.useContext(NamespaceContext)\n\n if (context === null) {\n throw new Error('\"useNamespace\" of \"files-uploader\" must be used within a \"NamespaceProvider\"')\n }\n\n return context\n}\n\nexport const withFileUploader = (\n namespace: string,\n Component: React.ComponentType,\n) => React.forwardRef((props, ref) => (\n \n \n \n))", "import type { ValidationError } from '../validators/_error-interface'\n\nimport { slice as filesUploaderSlice } from 'global-entities/files-uploader/slice'\n\nimport { createFileSelector } from 'global-entities/files-uploader/selectors'\n\nimport { filesUploaderListener } from '.'\n\n/**\n * Check validation errors on adding file and notify user about them\n */\nfilesUploaderListener.startListening({\n actionCreator: filesUploaderSlice.actions.addFile,\n effect: (action, api) => {\n\n for (const file of [].concat(action.payload.files)) {\n const FILE = createFileSelector(action.payload.namespace, file.hash)\n const { validation } = FILE(api.getState())\n\n Object.values(validation).forEach((error: null | ValidationError) => {\n if (!error?.notify) {\n return\n }\n\n error.notify()\n })\n }\n }\n})", "import { createListenerMiddleware } from '@reduxjs/toolkit'\n\nimport singleton from 'helpers/singleton'\n\nconst SINGLETON_ID = '6a903a95-d1a1-46fc-9222-9b5adcbb4ae9'\n\nexport const filesUploaderListener = singleton(SINGLETON_ID, () => createListenerMiddleware())", "import * as React from 'react'\nimport StoreManager from '@qwerty.software/store-manager'\nimport { Slice } from '@reduxjs/toolkit'\nimport { PersistConfig } from 'redux-persist'\n\nconst storeManager = StoreManager.getInstance()\n\nconst useSlices = (\n slices: (Slice | [slice: Slice, persistConfig?: PersistConfig])[],\n deps: React.DependencyList = []\n) => {\n // useState invoked in component constuction moment, so it berofe any useEffects of this component\n const [, setSlices] = React.useState(() => {\n storeManager.addSlices(slices)\n\n return slices\n })\n\n React.useEffect(() => {\n setSlices(prevSlices => {\n // storeManager.removeSlices(prevSlices.map((slice) => (Array.isArray(slice) ? slice[0] : slice)))\n storeManager.addSlices(slices)\n\n return slices\n })\n }, deps)\n}\n\nexport default useSlices\n", "import * as React from 'react'\nimport { SnackbarProvider } from 'notistack'\nimport './styles.scss'\n\nconst ConfigureNotify = () => (\n \n)\n\nexport default ConfigureNotify\n", "import * as React from 'react'\nimport { Provider } from 'react-redux'\nimport { PersistGate } from 'redux-persist/integration/react'\n\nimport { REHYDRATE } from 'redux-persist/lib/constants'\n\nimport setDesignTypeToStorage from 'utils/set-design-type-to-storage'\n\nimport useStoreManager from 'hooks/use-store-manager'\n\ninterface StoreGateProps {\n children: React.ReactNode\n}\n\nconst StoreGate = React.memo(({ children }) => {\n const storeManager = useStoreManager()\n\n React.useEffect((): void => {\n if (storeManager) {\n // @ts-ignore\n storeManager.persistor.dispatch({ type: REHYDRATE })\n\n setDesignTypeToStorage()\n }\n }, [storeManager])\n\n if (!storeManager) {\n return null\n }\n\n const { store, persistor } = storeManager\n\n return (\n \n \n {children}\n \n \n )\n})\n\nexport default StoreGate\n", "import storage from 'utils/storage'\n\nimport getFromConfigs from 'helpers/configs/get-from-configs'\n\nimport { IS_NEW_SPEEDYPAPER_DESIGN, PROJECT_ID } from 'constants/configs'\nimport { DESIGN_TYPE } from 'constants/storage'\nimport { SPEEDYPAPER_ID } from 'constants/project-ids'\n\nexport default () => {\n const isSpeedyPaperId = (getFromConfigs(PROJECT_ID) === SPEEDYPAPER_ID)\n\n if (!storage.get(DESIGN_TYPE) && isSpeedyPaperId) {\n if (getFromConfigs(IS_NEW_SPEEDYPAPER_DESIGN)) {\n storage.set(DESIGN_TYPE, 'new')\n\n return\n }\n\n storage.set(DESIGN_TYPE, 'old')\n }\n}\n", "import * as React from 'react'\n\nimport StoreManagerInitializer from '@qwerty.software/store-manager/initializer'\nimport StoreManager from '@qwerty.software/store-manager'\n\nconst storeManagerInitializer = StoreManagerInitializer.getInstance()\n\nconst useStoreManager = () => {\n const [storeManager, setStoreManager] = React.useState(() => {\n if (storeManagerInitializer.isInitialized()) {\n return StoreManager.getInstance()\n }\n\n return null\n })\n\n const handleInit = React.useCallback(() => {\n setStoreManager(StoreManager.getInstance())\n }, [])\n\n React.useEffect(() => {\n if (!storeManager) {\n storeManagerInitializer.addEventListener('init', handleInit)\n\n return () => {\n storeManagerInitializer.removeEventListener('init', handleInit)\n }\n }\n }, [storeManager])\n\n return storeManager\n}\n\nexport default useStoreManager", "import { createSlice, PayloadAction } from '@reduxjs/toolkit'\nimport { persistReducer } from 'redux-persist'\nimport localforage from 'localforage'\n\nimport _omit from 'lodash/omit'\n\nimport {\n NAME,\n INITIAL_STATE,\n\n AuthFieldNames,\n} from './constants'\nimport { UserState, UserValues } from './types'\n\nconst BLACKLIST = [\n AuthFieldNames.PASSWORD,\n]\n\ntype ValidatedFields = AuthFieldNames.CLIENT_AGREEMENTS\n | AuthFieldNames.EMAIL\n | AuthFieldNames.PASSWORD\n | AuthFieldNames.PHONE\n\nconst slice = createSlice({\n name: `slice://${NAME}/`,\n initialState: INITIAL_STATE,\n reducers: {\n change(state, action: PayloadAction<{ key: K, value: UserValues[K] }>) {\n state[action.payload.key] = action.payload.value\n },\n validationOn(state, action: PayloadAction) {\n let { payload } = action\n\n if (payload && typeof payload === 'string') {\n payload = [payload]\n }\n\n if (!Array.isArray(payload)) {\n payload = Object.values(_omit(AuthFieldNames, ['AUTH_TYPE'])) as K[]\n }\n\n payload.forEach(key => (\n state[key] = { ...state[key], validationEnabled: true }\n ))\n },\n validationOff(state, action: PayloadAction) {\n let { payload } = action\n\n if (payload && typeof payload === 'string') {\n payload = [payload]\n }\n\n if (!Array.isArray(payload)) {\n payload = Object.values(_omit(AuthFieldNames, ['AUTH_TYPE'])) as K[]\n }\n\n payload.forEach(key => (\n state[key] = { ...state[key], validationEnabled: false }\n ))\n },\n reset(state) {\n Object.keys(state).forEach(key => {\n state[key] = INITIAL_STATE[key]\n })\n }\n },\n})\n\nslice.reducer = persistReducer({\n keyPrefix: '',\n key: slice.name,\n // TODO: Disable serialization.\n // serialize: false,\n storage: localforage.createInstance({\n name: '[MSH] Storage',\n storeName: NAME,\n driver: [\n // localforage.INDEXEDDB,\n localforage.LOCALSTORAGE,\n ]\n }),\n blacklist: BLACKLIST,\n}, slice.reducer)\n\n// @ts-ignore\nexport const HYDRATED = (state: State) => state[slice.name]?._persist?.rehydrated\n\nexport const userSlice = slice\n\ninterface State {\n //@ts-ignore\n [userSlice.name]: UserState\n}\n\nexport const value = (name: Name) => (state: State): UserValues[Name] => state[userSlice.name][name]\nexport const USER = (state: State): UserValues => state[userSlice.name]\n", "import getFromConfigs from 'helpers/configs/get-from-configs'\n\nimport { ORDER_DATA_DEFAULTS, PROJECT_DOMAIN } from 'constants/configs'\nimport { SIGNUP } from 'constants/auth'\n\nimport { KEY } from 'global-entities/geo-tag/constants'\nimport { UserValues, UserState } from './types'\n\nexport const DEFAULT_COUNTRY_CODE = 'US'\n\nexport enum Type {\n TEXT = 'text',\n PASSWORD = 'password',\n}\n\nexport enum AuthFieldNames {\n AUTH_TYPE = 'authType',\n EMAIL = 'email',\n PHONE = 'phone',\n PASSWORD = 'password',\n CLIENT_AGREEMENTS = 'clientAgreements',\n}\n\nconst domain = getFromConfigs(PROJECT_DOMAIN)\nexport const NAME = `auth.form/${domain}` as const\n\nconst orderDataDefaults = getFromConfigs(ORDER_DATA_DEFAULTS)\n\nconst getCountryCode = (fallbackCountryCode: string = DEFAULT_COUNTRY_CODE) => {\n try {\n return JSON.parse(sessionStorage.getItem(KEY))?.countryCode || fallbackCountryCode\n } catch (error) {\n return fallbackCountryCode\n }\n}\n\nexport const INITIAL_VALUES: UserValues = {\n [AuthFieldNames.AUTH_TYPE]: (orderDataDefaults && orderDataDefaults.authType) || SIGNUP.authType,\n [AuthFieldNames.EMAIL]: {\n value: '',\n validationEnabled: false,\n },\n [AuthFieldNames.PHONE]: {\n value: {\n number: '',\n countryCode: getCountryCode(),\n mask: '',\n },\n validationEnabled: false,\n },\n [AuthFieldNames.PASSWORD]: {\n type: Type.PASSWORD,\n value: '',\n validationEnabled: false,\n },\n [AuthFieldNames.CLIENT_AGREEMENTS]: {\n value: [],\n validationEnabled: false,\n },\n}\n\nexport const INITIAL_STATE: UserState = {\n ...INITIAL_VALUES,\n}\n", "import { useSelector } from 'react-redux'\n\nimport useAction from 'hooks/useAction'\nimport useDiscount from 'global-entities/discount/hooks/use-discount'\n\nimport { CURRENCY } from '@qwerty.software/currency-switcher/src/store/slice'\nimport { ORDER } from '../order'\n\nimport { priceDataSlice } from '.'\nimport { useCalculate } from './use-calculate'\n\nimport type { RawOrder } from '@qwerty.software/ui-order-form/src/templates/dashboard/types'\n\ninterface IUsePriceDataOptions {\n calculator: any\n showAltPrices?: boolean\n\n rawOrder?: RawOrder // for dashboard\n}\n\n// TODO: Replace to RTK side-effects\nconst usePriceData = (options: IUsePriceDataOptions) => {\n const order = useSelector(ORDER)\n const currency = useSelector(CURRENCY)\n const discount = useDiscount()\n\n const setPriceData = useAction(priceDataSlice.actions.change)\n\n useCalculate({\n calculator: options.calculator,\n\n showAltPrices: options.showAltPrices,\n\n rawOrder: options.rawOrder,\n orderValues: order,\n discount,\n currency,\n\n setPriceData,\n })\n}\n\nexport default usePriceData\n", "import * as React from 'react'\nimport { useDispatch } from 'react-redux'\n\nconst useAction = (action: Function, deps: React.DependencyList = []) => {\n const dispatch = useDispatch()\n\n return React.useCallback((...rest: any[]) => dispatch(action(...rest)), deps)\n}\n\nexport default useAction\n", "import * as React from 'react'\nimport { useSelector, useDispatch } from 'react-redux'\n\nimport { slice as discountSlice } from 'global-entities/discount/slice'\n\nimport { useNamespace } from '../with-discount'\nimport { usePriceActivation } from './use-price-activation'\n\nimport Discount from '../selectors'\n\nimport { applyDiscount } from 'global-entities/discount/definitions'\n\ninterface Options {\n useCheckRoute?: boolean\n}\n\nfunction useDiscount(namespace: string = '', { useCheckRoute = false }: Options = {}) {\n const dispatch = useDispatch()\n const _namespace = useNamespace()\n\n if (!namespace) {\n namespace = _namespace\n }\n\n const api = React.useMemo(() => Discount(namespace), [namespace])\n\n let discount = useSelector(api.DISCOUNT)\n const _asyncField = React.useMemo(() => api.adapters.asyncField(discount), [discount])\n\n React.useEffect(() => {\n if (discount === api.NOOP_DISCOUNT) {\n dispatch(discountSlice.actions.setCode({ namespace, code: '' }))\n }\n }, [discount, api])\n\n const handleCodeChange = React.useCallback>(e => {\n const code = e.target.value\n\n dispatch(discountSlice.actions.setCode({ namespace, code }))\n }, [namespace])\n\n const send = React.useCallback(() => {\n dispatch(applyDiscount(namespace, { useCheckRoute }))\n }, [namespace])\n\n const cancel = React.useCallback(() => {\n dispatch(discountSlice.actions.cancelDiscount({ namespace }))\n }, [namespace])\n\n const reset = React.useCallback(() => {\n dispatch(discountSlice.actions.resetDiscount({ namespace }))\n }, [namespace])\n\n type Result = typeof discount & {\n handleCodeChange: typeof handleCodeChange,\n\n send: typeof send,\n cancel: typeof cancel,\n reset: typeof reset,\n\n api: typeof api,\n namespace: typeof namespace,\n\n // temporary\n _asyncField: typeof _asyncField,\n }\n\n const discountApi = React.useMemo(() => ({\n ...discount !== null ? discount : api.NOOP_DISCOUNT,\n handleCodeChange,\n\n send,\n cancel,\n reset,\n\n api,\n namespace,\n\n _asyncField,\n }), [\n namespace,\n discount,\n ])\n\n usePriceActivation({ discountApi })\n\n return discountApi\n}\n\nexport default useDiscount", "import * as React from 'react'\n\nimport { useDispatch, useSelector } from 'react-redux'\nimport { PRICE_DATA_USD } from '@qwerty.software/ui-order-form/src/store/slices/price-data'\n\nimport { slice as discountSlice } from 'global-entities/discount/slice'\nimport { PreloadState } from 'global-entities/discount/definitions'\nimport notify from 'utils/notify'\nimport { CURRENCY } from '@qwerty.software/currency-switcher/src/store/slice'\nimport { replacePriceViaCurrency } from '@qwerty.software/currency-switcher/src/utils/replace-price-via-currency'\n\nexport const usePriceActivation = ({ discountApi }) => {\n const dispatch = useDispatch()\n const { priceFullWithoutDiscount } = useSelector(PRICE_DATA_USD)\n const currency = useSelector(CURRENCY)\n\n const updateDiscount = (discount) => dispatch(discountSlice.actions.updateDiscount({ namespace: discountApi.namespace, discount }))\n const { data } = discountApi._asyncField\n\n React.useEffect(() => {\n if (data?.discount?.type?.price_activation && typeof priceFullWithoutDiscount === 'number') {\n if (priceFullWithoutDiscount < data.discount.type.price_activation) {\n const modifiedText = replacePriceViaCurrency({ currency, textWithPrice: `Sorry, the code is valid for order over $${data.discount.type.price_activation}. Add pages or additional services on $${(data.discount.type.price_activation - priceFullWithoutDiscount).toFixed(2)} to activate the code` })\n\n updateDiscount({\n preload: {\n state: PreloadState.REJECTED,\n error: modifiedText,\n },\n applied: false\n })\n\n discountApi.applied && notify.warning('Your discount is canceled. You have changed the conditions of use.')\n }\n\n if (priceFullWithoutDiscount >= data.discount.type.price_activation && !discountApi.applied) {\n discountApi.send()\n }\n }\n }, [data, priceFullWithoutDiscount, discountApi.applied, currency])\n}", "import { useCallback, useEffect, useMemo } from 'react'\n\nimport { getBootstrapData } from 'global-entities/bootstrap-data/utils/get'\n\nimport { ContextPDAdapter } from './ContextPDAdapter'\nimport { extractFreeFeaturesFromRawOrder } from './extract-free-features-from-raw-order'\n\nimport { DEFAULT_CURRENCY, ICurrency } from '@qwerty.software/currency-switcher/src/store/constants'\n\nimport type { OrderValues } from '../order/types'\nimport type { IPriceData } from './types'\nimport type { RawOrder } from '@qwerty.software/ui-order-form/src/templates/dashboard/types'\nimport type { DiscountMeta } from 'global-entities/discount/definitions'\nimport type { Values } from \"global-entities/price-data/hooks/useCalculator\"\n\nexport interface ISetterArgs {\n priceData: IPriceData\n adaptedOrderValues: Values\n priceDataBase: IPriceData\n}\n\ninterface IUseCalculatePriceOptions {\n calculator: any\n\n showAltPrices: boolean\n\n rawOrder: RawOrder\n orderValues: OrderValues\n discount: Partial\n currency: ICurrency\n\n setPriceData: ({ priceData, adaptedOrderValues, priceDataBase }: ISetterArgs) => void\n\n overrideValues?: Partial\n}\n\nexport const useCalculate = ({\n calculator,\n\n showAltPrices,\n\n rawOrder,\n orderValues,\n discount,\n currency,\n\n setPriceData,\n\n overrideValues\n}: IUseCalculatePriceOptions) => {\n const { priceCalculatorAdapted = undefined, prices_alt } = getBootstrapData()\n\n const withFreeFeaturesValues = useMemo(() => extractFreeFeaturesFromRawOrder({\n rawOrder,\n orderValues: {...orderValues, ...(overrideValues || {})}\n }), [\n orderValues,\n overrideValues?.academicLevel,\n JSON.stringify(overrideValues?.additionalFeatures),\n overrideValues?.deadline,\n overrideValues?.pagesWordsSwitcher,\n overrideValues?.paperDetails,\n overrideValues?.paperFormat,\n overrideValues?.paperType,\n overrideValues?.preferredOrder?.sended,\n overrideValues?.preferredOrder?.value,\n overrideValues?.quantity,\n overrideValues?.quantityKey,\n overrideValues?.slides,\n overrideValues?.softCopies,\n overrideValues?.software?.checked,\n overrideValues?.software?.value,\n overrideValues?.sources,\n overrideValues?.spacing,\n overrideValues?.speakerNotes,\n overrideValues?.subject,\n overrideValues?.topic,\n overrideValues?.words,\n overrideValues?.workType,\n overrideValues?.writerCategory,\n ])\n\n const writer = rawOrder?.active_writer?.mtl ? rawOrder.active_writer : null\n\n const adaptedOrderValues = useMemo(() => {\n const adapted = ContextPDAdapter({...orderValues, ...(overrideValues || {})}, currency, discount)\n\n return { ...adapted, ...withFreeFeaturesValues, writer }\n }, [orderValues, currency, discount, withFreeFeaturesValues, writer])\n\n const handleSetPriceData = useCallback(({ priceData, adaptedOrderValues, priceDataBase }) => {\n setPriceData({ priceData, adaptedOrderValues, priceDataBase })\n }, [setPriceData])\n\n useEffect(() => {\n if (priceCalculatorAdapted && !!calculator) {\n const prices = showAltPrices\n ? prices_alt\n : priceCalculatorAdapted.bdPrices\n\n const priceData = calculator(\n {\n fieldValues: adaptedOrderValues,\n bd: { ...priceCalculatorAdapted, bdPrices: prices},\n currency: currency.symbol,\n },\n {\n currency: currency.name,\n rate: currency.rate\n }\n )\n\n const priceDataBase = currency.name !== DEFAULT_CURRENCY.name\n ? calculator(\n {\n fieldValues: adaptedOrderValues,\n bd: { ...priceCalculatorAdapted, bdPrices: prices},\n currency: currency.symbol,\n },\n {\n currency: DEFAULT_CURRENCY.name,\n rate: DEFAULT_CURRENCY.rate\n }\n )\n : priceData\n\n handleSetPriceData({ priceData, adaptedOrderValues, priceDataBase })\n }\n }, [\n calculator,\n showAltPrices,\n currency?.name,\n currency?.rate,\n prices_alt,\n priceCalculatorAdapted,\n adaptedOrderValues.pages,\n adaptedOrderValues.words,\n adaptedOrderValues.slides,\n adaptedOrderValues.speakerNotes,\n adaptedOrderValues.problems,\n adaptedOrderValues.questions,\n adaptedOrderValues.deadline,\n adaptedOrderValues.spacing,\n adaptedOrderValues.workType,\n adaptedOrderValues.paperType,\n adaptedOrderValues.academicLevel,\n adaptedOrderValues.writerCategory,\n adaptedOrderValues.sources,\n adaptedOrderValues.softcopies,\n adaptedOrderValues.subject,\n adaptedOrderValues.software,\n\n adaptedOrderValues.additionalFeatures,\n adaptedOrderValues.discountData,\n // @ts-ignore\n adaptedOrderValues.preferredOrderData?.writerCategory?.chosenID,\n // @ts-ignore\n adaptedOrderValues.preferredOrderData?.writerCategory?.free,\n\n setPriceData,\n ])\n}\n", "import { RawOrder } from \"@qwerty.software/ui-order-form/src/templates/dashboard/types\"\nimport { FieldNames } from \"@qwerty.software/ui-order-form/src/store/constants\"\nimport { OrderValues } from \"../order/types\"\n\ninterface IExtractorProps {\n rawOrder: RawOrder\n orderValues: OrderValues\n}\n\ntype TResultKeys = FieldNames.WRITER_CATEGORY | FieldNames.ADDITIONAL_FEATURES | FieldNames.SPEAKER_NOTES\n\ntype TExtractor = (props: IExtractorProps) => Partial>\n\nexport const extractFreeFeaturesFromRawOrder: TExtractor = ({ rawOrder, orderValues }) => {\n if (!rawOrder) return {}\n\n const writerCategoryValue = {\n chosenID: orderValues.writerCategory,\n free: rawOrder.writer_category.free && rawOrder.writer_category.chosen_id === orderValues.writerCategory\n }\n\n const additionalFeaturesValue = orderValues.additionalFeatures.map((id => ({\n id,\n chosen: orderValues.additionalFeatures.includes(id),\n free: rawOrder.additional_features.some((feature) => feature.id === id && feature.free)\n })))\n\n const speakerNotesValue = rawOrder.speaker_notes.enabled && rawOrder.speaker_notes.free ? false : orderValues.speakerNotes\n\n return {\n [FieldNames.WRITER_CATEGORY]: writerCategoryValue,\n [FieldNames.ADDITIONAL_FEATURES]: additionalFeaturesValue,\n [FieldNames.SPEAKER_NOTES]: speakerNotesValue\n }\n}\n", "import * as React from 'react'\nimport { useSelector } from 'react-redux'\nimport useAction from 'hooks/useAction'\n\nimport checkAction from 'global-entities/user-data/actions/check'\n\nimport { getIsAuthorized, getIsChecked } from 'global-entities/user-data/selectors'\n\nconst useUserData = () => {\n const udIsAuthorized = useSelector(getIsAuthorized)\n const isChecked = useSelector(getIsChecked)\n\n const check = useAction(checkAction)\n\n React.useEffect(() => {\n if (!isChecked) {\n check()\n }\n }, [isChecked])\n\n return {\n check,\n udIsAuthorized,\n }\n}\n\nexport default useUserData\n", "import _size from 'lodash/size'\nimport _get from 'lodash/get'\nimport _toUpper from 'lodash/toUpper'\n\nimport StoreManager from '@qwerty.software/store-manager'\nimport { abTestsSlice } from '@qwerty.software/ab-test/src/component/store'\n\n/* adapters local */\nimport userDataAdapter from 'global-entities/user-data/adapter'\n\n/* utils general */\nimport { reqHPromise as reqH } from 'utils/http-client/request-handler'\nimport notify from 'utils/notify'\nimport storage from 'utils/storage'\nimport customEvent from 'utils/custom-event'\nimport queryString from 'utils/query-string'\nimport actionTracker from 'utils/action-tracker'\n\nimport { getFromURL } from 'utils/from-url'\nimport { setRedesignReferrer } from 'utils/from-url/redesign-referrer'\nimport { getTempQuery } from 'utils/from-url/temp-query'\nimport { getVisitor, setVisitor, setIsNewVisitor } from 'utils/visitor'\nimport { getRT } from 'utils/rt'\nimport { getFirstCheck, setFirstCheck } from 'utils/first-check-request'\nimport trackMainPage from 'utils/visited-pages/track-main-page'\nimport { setVisitedPage } from 'utils/visited-pages'\n\nimport { getFingerprint } from './fingerprint'\n\n/* helpers general */\nimport getFromConfigs from 'helpers/configs/get-from-configs'\n\n/* helpers global-entities */\nimport toggleAuthButtons from 'global-entities/user-data/helpers/toggle-auth-buttons'\n\n// import { SET_ALT_PRICES_FLAG } from 'global-entities/price-data/alt-prices/constants'\n\n/* redux-constants local */\nimport {\n USER_CHECK,\n REMOTE_SUCCESS,\n} from 'global-entities/user-data/constants'\n\n/* constants general */\nimport {\n AUTHORISATION_STATUSES,\n CHECK,\n CHECK_TRIGGERED,\n} from 'constants/auth'\nimport { TEMP_QS_KEY, REFERRER } from 'constants/storage'\nimport { USER_CHECKED } from 'constants/custom-events'\nimport { SHOULD_DISABLE_USER_CHECK_REQUEST } from 'constants/configs'\n\nconst DISABLE_CHECK_REQUEST = getFromConfigs(SHOULD_DISABLE_USER_CHECK_REQUEST)\n\nconst getParams = () => {\n window[CHECK_TRIGGERED] = true\n\n const params = {\n ...(queryString.getParams() || {}),\n ...getTempQuery(),\n from_url: getFromURL(),\n }\n\n const rt = getRT()\n if (rt) {\n params.rt = rt\n }\n\n return params\n}\n\nwindow.checkAuthData = window.checkAuthData || new Promise(resolve => {\n const fingerprint = getFingerprint()\n\n if (DISABLE_CHECK_REQUEST) {\n // eslint-disable-next-line no-console\n console.log('Check request disabled via configs.')\n return\n }\n\n (async (params) => {\n const res = await reqH({\n method: 'GET',\n url: CHECK.route,\n params: {\n ...params,\n first_check_request: getFirstCheck(),\n k: Math.random(),\n f: fingerprint,\n caller: window?.location?.pathname,\n },\n skipGlobalSpinner: true,\n })\n\n if (_size(res.errors) > 0) {\n notify.error(res.errors[0])\n return res\n }\n\n StoreManager.getInstance().store.dispatch(abTestsSlice.actions.hydrate(res.data.user))\n\n setVisitor(res.data.user.visitor_id)\n setIsNewVisitor(res.data.user.is_new_visitor)\n\n const userData = userDataAdapter(res.data.user)\n\n trackMainPage(userData)\n\n setFirstCheck()\n\n setRedesignReferrer()\n\n resolve(res)\n })(getParams())\n})\n\nexport default () => async (dispatch) => {\n if (getFromConfigs(SHOULD_DISABLE_USER_CHECK_REQUEST)) {\n return\n }\n\n try {\n const res = await window.checkAuthData\n\n if (_size(res.errors) > 0) {\n notify.error(res.errors[0])\n return res\n }\n\n const userData = userDataAdapter(res.data.user)\n\n dispatch({\n type: USER_CHECK + REMOTE_SUCCESS,\n payload: userData,\n })\n\n // let altPrice = null\n\n // switch (`${res.data.user.incPrices}`.toUpperCase()) {\n // case 'GROUP_A':\n // altPrice = false\n // break\n // case 'GROUP_B':\n // altPrice = true\n // break\n // default:\n // break\n // }\n\n // dispatch({\n // type: SET_ALT_PRICES_FLAG,\n // payload: altPrice,\n // })\n\n // TODO remove it from here, fix jinp LR-2808\n window._jinp_visitor_id = userData.visitorID\n window._jinp_referrer_id = userData.referrerID\n\n actionTracker.track({\n data: {\n user_status: 'unknown',\n visitor_id: userData.visitorID,\n referrer_id: userData.referrerID,\n },\n })\n\n toggleAuthButtons(userData.isAuthorized ? AUTHORISATION_STATUSES.authorized : AUTHORISATION_STATUSES.unauthorized)\n\n setVisitedPage()\n\n customEvent.trigger(USER_CHECKED, { isAuthorized: userData.isAuthorized })\n\n storage.remove(TEMP_QS_KEY, { isOuterKey: true })\n storage.remove(REFERRER, { isOuterKey: true })\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Check request failure]', error.message)\n return error\n }\n}\n", "/* constants general */\nimport { AUTHORISATION_STATUSES } from 'constants/auth'\n\nconst convert = (originalPropertyName, adaptedPropertyName, originalData, adaptedData) => {\n if (typeof originalData[originalPropertyName] !== 'undefined') {\n adaptedData[adaptedPropertyName] = originalData[originalPropertyName]\n }\n\n return adaptedData\n}\n\nexport default (originalData) => {\n if (!originalData) {\n return\n }\n\n const adaptedData = {}\n\n const propertiesForAdaptation = [\n { originalPropertyName: 'id', adaptedPropertyName: 'userID' },\n { originalPropertyName: 'visitor_id', adaptedPropertyName: 'visitorID' },\n { originalPropertyName: 'visitor', adaptedPropertyName: 'visitor' },\n { originalPropertyName: 'referrer_id', adaptedPropertyName: 'referrerID' },\n { originalPropertyName: 'referrer_type_id', adaptedPropertyName: 'referrerTypeID' },\n { originalPropertyName: 'link_id', adaptedPropertyName: 'linkID' },\n { originalPropertyName: 'email', adaptedPropertyName: 'email' },\n { originalPropertyName: 'phone', adaptedPropertyName: 'phone' },\n { originalPropertyName: 'first_name', adaptedPropertyName: 'firstName' },\n { originalPropertyName: 'last_name', adaptedPropertyName: 'lastName' },\n { originalPropertyName: 'subscribed', adaptedPropertyName: 'subscribed' },\n { originalPropertyName: 'paid_orders_count', adaptedPropertyName: 'paidOrdersCount' },\n { originalPropertyName: 'user_tags', adaptedPropertyName: 'tags' },\n { originalPropertyName: 'retentionDiscount', adaptedPropertyName: 'retentionDiscount' },\n { originalPropertyName: 'is_referral', adaptedPropertyName: 'isReferral' },\n { originalPropertyName: 'cashback', adaptedPropertyName: 'cashback' },\n { originalPropertyName: 'cashbackBalance', adaptedPropertyName: 'cashbackBalance' },\n { originalPropertyName: 'all_orders_count', adaptedPropertyName: 'allOrdersCount' },\n { originalPropertyName: 'loyalty_data', adaptedPropertyName: 'loyaltyData' },\n { originalPropertyName: 'profileType', adaptedPropertyName: 'profileType' },\n { originalPropertyName: 'typeOfWorkABTest', adaptedPropertyName: 'typeOfWorkABTest' },\n { originalPropertyName: 'lengthOrderForm', adaptedPropertyName: 'lengthOrderForm' },\n { originalPropertyName: 'notificationProWriter', adaptedPropertyName: 'notificationProWriter' },\n { originalPropertyName: 'chatbotOrderFormAlternative', adaptedPropertyName: 'chatbotOrderFormAlternative' },\n { originalPropertyName: 'showIphoneBanner', adaptedPropertyName: 'showIphoneBanner' },\n { originalPropertyName: 'currency_id', adaptedPropertyName: 'currencyId' },\n { originalPropertyName: 'last_paid_order_data', adaptedPropertyName: 'lastPaidOrderData' },\n { originalPropertyName: 'top_upsales', adaptedPropertyName: 'topUpsales' },\n { originalPropertyName: 'incPrices', adaptedPropertyName: 'incPrices' },\n ]\n\n propertiesForAdaptation.forEach((item) => {\n convert(item.originalPropertyName, item.adaptedPropertyName, originalData.user ? originalData.user : originalData, adaptedData)\n })\n\n adaptedData.authorizationStatus = AUTHORISATION_STATUSES.unauthorized\n adaptedData.isAuthorized = false\n\n if (adaptedData.userID) {\n adaptedData.authorizationStatus = AUTHORISATION_STATUSES.authorized\n adaptedData.isAuthorized = true\n }\n\n return adaptedData\n}\n", "import getFromConfigs from 'helpers/configs/get-from-configs'\nimport { TRACK_TOOL } from 'constants/configs'\n\nimport googleTrack from './google-track'\nimport interiorTrack from './interior-track'\n\nimport type { TrackerType, ITrackerParams } from './types'\n\nconst requiredArgument = (name: string) => {\n throw new Error(`${name} argument is required!`)\n}\n\nexport enum Tool {\n Google = 'google-track',\n Interior = 'interior-track',\n}\n\nconst trackAction: TrackerType = (params: ITrackerParams): void | false => {\n const tool: Tool = params.tool ? params.tool : getFromConfigs(TRACK_TOOL) || Tool.Interior\n\n switch (tool) {\n case (Tool.Google):\n return googleTrack(params)\n case (Tool.Interior):\n default:\n return interiorTrack(params)\n }\n}\n\nconst createSet = ({ name = requiredArgument('name') } = {}) => {\n let set = {}\n\n return {\n push: (params: Object) => {\n set = {\n ...set,\n ...params,\n }\n },\n track: (callback = () => { }) => trackAction({\n eventName: name,\n data: set,\n callback,\n }),\n }\n}\n\n// @ts-ignore\nwindow.microservicesActionTracker = {\n track: trackAction,\n createSet,\n}\n\nexport default {\n track: trackAction,\n createSet,\n}\n", "import type { TrackerType, ITrackerParams } from 'utils/action-tracker/types'\n\nconst checkTrackerEnabled = () => {\n if (typeof (window as any).dataLayer === 'undefined') {\n // eslint-disable-next-line no-console\n console.warn('No \"dataLayer\" variable found!')\n return false\n }\n\n return true\n}\n\nconst trackAction: TrackerType = ({\n eventName = '',\n data = {},\n callback = () => { },\n}: ITrackerParams = {}): void | false => {\n if (!checkTrackerEnabled()) {\n callback() // if tracker is blocked or disabled just call callback for best app safety\n return false\n }\n\n const params: {\n event?: string\n eventCallback: Function\n eventTimeout: number\n [key: string]: any\n } = { ...data, eventCallback: callback, eventTimeout: 500 }\n\n if (eventName) {\n params.event = eventName\n }\n\n if ((window as any)?.dataLayer && !!(window as any)?.dataLayer?.push) {\n (window as any).dataLayer.push(params)\n setTimeout(callback, 350)\n }\n}\n\nexport default trackAction\n", "import StoreManager from '@qwerty.software/store-manager'\n\nimport { INTERIOR_TRACK } from 'utils/action-tracker/interior-track/store/constants'\n\nimport type { TrackerType, ITrackerParams } from 'utils/action-tracker/types'\n\nimport type { Action } from 'utils/action-tracker/interior-track/store/sagas/track/types'\n\nconst trackAction = ({ eventName, callback, data }: {\n eventName: string\n callback: Function\n data: any\n}): Action => ({\n type: INTERIOR_TRACK,\n payload: { eventName, callback, data },\n})\n\nconst interiorTrack: TrackerType = ({\n eventName = '',\n callback = () => { },\n data\n \n}: ITrackerParams = {}) => {\n StoreManager.getInstance().store.dispatch(trackAction({\n eventName,\n callback,\n data\n }))\n}\n\nexport default interiorTrack\n", "import getFromConfigs from 'helpers/configs/get-from-configs'\n\nimport { ADDITIONAL_QUERY_PARAMS_TO_PARENT_SITE } from 'constants/configs'\n\nexport const getRT = () => {\n const additionalQueryParamsToParentSite = getFromConfigs(ADDITIONAL_QUERY_PARAMS_TO_PARENT_SITE)\n if (additionalQueryParamsToParentSite?.rt) {\n return additionalQueryParamsToParentSite.rt\n }\n}\n", "import storage from 'utils/storage'\n\nconst IS_NOT_THE_FIRST_CHECK_REQUEST = 'is-not-the-first-check-request'\n\nexport const getFirstCheck = () => !storage.get(IS_NOT_THE_FIRST_CHECK_REQUEST, { storageType: 'session' })\n\nexport const setFirstCheck = () => storage.set(IS_NOT_THE_FIRST_CHECK_REQUEST, true, { storageType: 'session' })\n", "import _size from 'lodash/size'\nimport _get from 'lodash/get'\n\nimport storage from 'utils/storage'\nimport actionTracker from 'utils/action-tracker'\n\nimport { getVisitedPages } from 'utils/visited-pages'\nimport getUserTraficFields from 'utils/action-tracker/getUserTraficFields'\n\nimport { DESIGN_TYPE } from 'constants/storage'\n\nconst trackMainPage = (userData: any) => {\n // setTimeout(() => {\n if (!_get(getVisitedPages(), `[${document.location.pathname}]`, false)) {\n actionTracker.track({\n eventName: 'main_page_open',\n data: {\n url_from: document.referrer.length ? document.referrer : 'first input',\n url_current: document.location.pathname,\n current_full_url: window.location,\n design_type: storage.get(DESIGN_TYPE),\n ...getUserTraficFields(userData),\n\n ...(userData.isAuthorized\n ? {\n user_id: userData.userID,\n paidOrdersCount: userData.paidOrdersCount,\n allOrdersCount: userData.allOrdersCount,\n }\n : {\n visitor_id: userData.visitorID,\n }\n ),\n },\n })\n }\n // }, 2000)\n}\n\nexport default trackMainPage\n", "import storage from 'utils/storage'\n\nexport const getVisitedPages = () => storage.get('visited_pages', { storageType: 'session' })\n\nexport const setVisitedPage = () => {\n storage.set('visited_pages', {\n ...getVisitedPages(),\n [document.location.pathname]: true,\n }, { storageType: 'session' })\n}\n", "const REVIEWS_RANGE = [38557, 141078, 139112, 89177, 139112, 9233, 30232, 38557]\nconst WHITE_DOORS_RANGE = [149486]\nconst PPC_RANGE = [15474, 141228]\nconst SEO_RANGE = [49692, 149487, 22459, 17474]\nconst SMM_RANGE = [49871, 242, 141405]\nconst DOORS_RANGE = [146402]\nconst ORGANIC_RANGE = [0, 52130]\nconst PUSH_RANGE = [146091]\n\nconst APP_RANGE = [87430, 89941]\n\nconst REFFERAL_RANGE = [4]\n\n// eslint-disable-next-line camelcase\nconst channelFindOut = ({ referrer_id, link_id, referrer_type_id }) => {\n switch (true) {\n case REVIEWS_RANGE.includes(referrer_id):\n return 'reviews'\n case WHITE_DOORS_RANGE.includes(referrer_id):\n return 'white_doors'\n case PPC_RANGE.includes(referrer_id):\n return 'ppc'\n case SEO_RANGE.includes(referrer_id):\n return 'seo'\n case SMM_RANGE.includes(referrer_id):\n return 'smm'\n case DOORS_RANGE.includes(referrer_id):\n return 'doors'\n case ORGANIC_RANGE.includes(referrer_id):\n return 'organic'\n case PUSH_RANGE.includes(referrer_id):\n return 'push'\n case APP_RANGE.includes(link_id):\n return 'app'\n case REFFERAL_RANGE.includes(referrer_type_id):\n return 'refferal'\n default:\n return 'webmasters'\n }\n}\n\nconst getUserTraficFields = (userData) => {\n // eslint-disable-next-line camelcase\n const link_id = userData?.visitor?.link_id || userData?.linkID || 0\n // eslint-disable-next-line camelcase\n const referrer_id = userData?.visitor?.referrer_id || userData?.referrerID || 0\n // eslint-disable-next-line camelcase\n const referrer_type_id = userData?.referrerTypeID || 0\n\n const fields = {\n link_id,\n referrer_id,\n referrer_type_id,\n }\n\n return {\n ...fields,\n channel: channelFindOut(fields),\n }\n}\n\nexport default getUserTraficFields\n", "import getBrowserFingerprint from 'sctk-new-get-browser-fingerprint'\n\nimport getFromConfigs from 'helpers/configs/get-from-configs'\nimport {\n PROJECT_DOMAIN,\n IS_ALIAS_DOMAIN,\n} from 'constants/configs'\nimport { toBinary } from './toBinary'\n\nexport const getFingerprint = () => {\n const fingerprint = getBrowserFingerprint({ enableWebgl: true })\n const isAliasDomain = getFromConfigs(IS_ALIAS_DOMAIN)\n const configsDomain = getFromConfigs(PROJECT_DOMAIN) || window.location.hostname\n\n const domain = isAliasDomain ? configsDomain : window.location.hostname\n\n return toBinary(`${fingerprint}${domain}`)\n}", "export const toBinary = (source: string): string => {\n const codeUnits = new Uint16Array(source.length)\n\n for (let i = 0; i < codeUnits.length; i++) {\n codeUnits[i] = source.charCodeAt(i)\n }\n\n return btoa(String.fromCharCode(...Array.from(new Uint8Array(codeUnits.buffer))))\n}", "/* constants general */\nimport {\n AUTHORISATION_STATUSES,\n DASHBOARD,\n SIGNOUT,\n} from 'constants/auth'\nimport {\n DATA_ATTR_OPEN_AUTH_MODAL,\n DATA_ATTR_EXISTING_USER_ACTION,\n} from 'constants/data-attrs'\n\nexport default (userAuthorizationStatus) => {\n let openAuthModalBtns = document.querySelectorAll(`[${DATA_ATTR_OPEN_AUTH_MODAL}=true]`)\n let dashboardBtns = document.querySelectorAll(`[${DATA_ATTR_EXISTING_USER_ACTION}=${DASHBOARD.action}]`)\n let signoutBtns = document.querySelectorAll(`[${DATA_ATTR_EXISTING_USER_ACTION}=${SIGNOUT.action}]`)\n\n openAuthModalBtns = [...openAuthModalBtns]\n dashboardBtns = [...dashboardBtns]\n signoutBtns = [...signoutBtns]\n\n switch (userAuthorizationStatus) {\n\n case AUTHORISATION_STATUSES.authorized:\n openAuthModalBtns.forEach((btn) => btn.classList.add('hidden'))\n\n dashboardBtns.forEach((btn) => btn.classList.remove('hidden'))\n\n signoutBtns.forEach((btn) => btn.classList.remove('hidden'))\n break\n\n case AUTHORISATION_STATUSES.unauthorized:\n openAuthModalBtns.forEach((btn) => btn.classList.remove('hidden'))\n\n dashboardBtns.forEach((btn) => btn.classList.add('hidden'))\n\n signoutBtns.forEach((btn) => btn.classList.add('hidden'))\n break\n\n default:\n break\n }\n\n}\n", "export const DATA_ATTR_OPEN_AUTH_MODAL = 'data-open-auth-modal'\n\nexport const DATA_ATTR_OPEN_AUTH_MODAL_NEW = 'data-open-auth-modal-new'\n\nexport const DATA_ATTR_AUTH_TYPE = 'data-auth-type'\n\nexport const DATA_ATTR_EXISTING_USER_ACTION = 'data-existing-user-action'\n\nexport const DATA_ATTR_REQUEST_CALL_MODAL = 'data-open-request-call-modal'\n\nexport const DATA_ATTR_CUSTOM_PATH_FOR_REDIRECT = 'data-custom-path-for-redirect'\n", "export const getUserData = (state) => state?.userData\n\nexport const getAuthorizationStatus = (state) => state?.userData?.authorizationStatus\nexport const getIsAuthorized = (state) => state?.userData?.isAuthorized\n\nexport const getUserID = (state) => state?.userData?.userID\nexport const getVisitorID = (state) => state?.userData?.visitorID\nexport const getReferrerID = (state) => state?.userData?.referrerID\n\nexport const getEmail = (state) => state?.userData?.email\nexport const getPhone = (state) => state?.userData?.phone\n\nexport const getFirstName = (state) => state?.userData?.firstName\nexport const getLastName = (state) => state?.userData?.lastName\nexport const getFullName = (state) => [getFirstName(state), getLastName(state)].join(' ').trim()\n\nexport const getPaidOrdersCount = (state) => state?.userData?.paidOrdersCount\n\nexport const getSubscribed = (state) => state?.userData?.subscribed\n\nexport const getTags = (state) => state?.userData?.tags\n\nexport const getRetentionDiscount = (state) => state?.userData?.retentionDiscount\n\nexport const getPusherRetentionDiscount = (state) => state?.retentionDiscount?.retentionDiscount\n\nexport const getIsABChatbot = (state) => Boolean(state?.userData?.chatbotOrderFormAlternative === 'GROUP_B')\n\nexport const getIsChecked = (state) => Boolean(state?.userData?.checked)\n\n", "import { useEffect } from \"react\"\nimport { useLocation } from \"react-router-dom\"\n\nimport { getIsChecked, getUserID } from 'global-entities/user-data/selectors'\nimport useVisitorID from 'global-entities/user-data/hooks/useVisitorID'\n\nimport { reqHPromise } from \"utils/http-client/request-handler\"\nimport { useSelector } from \"react-redux\"\n\nexport const useMarkOrderPageAsVisited = () => {\n const isChecked = useSelector(getIsChecked)\n const { pathname } = useLocation()\n const userId = useSelector(getUserID)\n const visitorId = useVisitorID()\n\n useEffect(() => {\n if (isChecked && visitorId) {\n reqHPromise({\n method: 'POST',\n url: 'add-visited-page',\n data: {\n name: pathname,\n user_id: userId,\n visitor_id: visitorId\n },\n })\n }\n }, [pathname, userId, visitorId, isChecked])\n}\n", "import { useSelector } from 'react-redux'\n\nimport storage from 'utils/storage'\n\ninterface IUserDataStore {\n userData: {\n visitorID?: number\n }\n}\n\nconst useVisitorID = () => {\n const visitorID = useSelector((state: IUserDataStore) => state.userData.visitorID)\n\n if (visitorID) {\n return visitorID\n }\n\n const Visitor = storage.get('Visitor')\n\n if (Visitor) {\n return Visitor\n }\n\n const userData = storage.get('user_data')\n\n if (userData?.visitorID) {\n return userData.visitorID\n }\n\n return undefined\n}\n\nexport default useVisitorID\n", "import * as React from 'react'\nimport _throttle from 'lodash/throttle'\n\nimport cookie from 'utils/cookie'\n\n// eslint-disable-next-line import/no-named-as-default\nimport tracer from 'global-entities/geo-tag/tracers'\n\nimport useGeoTag from 'global-entities/geo-tag/store/hooks/geoTag'\n\nconst DETAULT_COUNTRY_CODE = 'us'\n\nconst trace = _throttle(tracer, 5000)\n\n// TODO: Replace to RTK side-effect\nconst GeoTag = () => {\n const [{ IP, countryCode }, { setIP, setCountryCode }] = useGeoTag()\n\n React.useEffect(() => {\n (async () => {\n if (!IP || !countryCode) {\n\n try {\n const tag = await trace()\n\n if (tag) {\n setIP(tag.IP as string)\n setCountryCode(tag.countryCode as string || DETAULT_COUNTRY_CODE)\n cookie.set('_ip', tag.IP)\n } else {\n setCountryCode(DETAULT_COUNTRY_CODE) // TODO: hotfix - some users whithout countrycode\n }\n } catch (e) {\n setCountryCode(DETAULT_COUNTRY_CODE)\n\n // eslint-disable-next-line no-console\n console.warn('Setted default country code')\n }\n\n }\n })()\n }, [IP, countryCode])\n\n return null\n}\n\nexport default GeoTag\n", "const isEnabled = () => navigator.cookieEnabled\n\nconst get = (storageItemKey) => {\n if (!isEnabled()) {\n return\n }\n const matches = document.cookie.match(new RegExp(\n // eslint-disable-next-line\n '(?:^|; )' + storageItemKey.replace(/([\\.$?*|{}\\(\\)\\[\\]\\\\\\/\\+^])/g, '\\\\$1') + '=([^;]*)',\n ))\n\n return matches ? decodeURIComponent(matches[1]) : undefined\n}\n\nconst set = (storageItemKey, storageItemValue, { expiryDate } = {}) => {\n if (!isEnabled()) {\n return\n }\n if (expiryDate && expiryDate.toUTCString) {\n expiryDate = expiryDate.toUTCString()\n }\n\n storageItemValue = encodeURIComponent(storageItemValue)\n\n let updatedCookie = `${storageItemKey}=${storageItemValue}`\n if (expiryDate) {\n updatedCookie += `; expires=${expiryDate}`\n }\n\n document.cookie = updatedCookie\n}\n\nconst remove = (storageItemKey) => {\n if (!isEnabled()) {\n return\n }\n set(storageItemKey, '', { expiryDate: new Date() })\n}\n\nconst cookie = {\n isEnabled,\n\n get,\n set,\n remove,\n}\n\nexport default cookie\n\nwindow.MICROSERVICES_UTILS_AND_HELPERS = window.MICROSERVICES_UTILS_AND_HELPERS || {}\n!window.MICROSERVICES_UTILS_AND_HELPERS?.cookie && (window.MICROSERVICES_UTILS_AND_HELPERS.cookie = cookie)", "import axios from 'axios'\nimport _isEmpty from 'lodash/isEmpty'\n\nimport cloudflare from 'global-entities/geo-tag/tracers/cloudflare'\n// import ipinfo from 'global-entities/geo-tag/tracers/ipinfo'\n// import { KEY } from 'global-entities/geo-tag/constants'\n\nconst CancelToken = axios.CancelToken\n\nconst tracers = [\n cloudflare,\n // ipinfo,\n]\n\nexport const trace = async () => {\n // @ts-ignore\n if (!window._ms_geoTagResonseWaiting) {\n // @ts-ignore\n window._ms_geoTagResonseWaiting = true\n const source = CancelToken.source()\n const data = await Promise.race(tracers.map(tracer => tracer(source)))\n\n // @ts-ignore\n delete window._ms_geoTagResonseWaiting\n\n return data\n }\n}\n\nexport { cloudflareTracer } from 'global-entities/geo-tag/tracers/cloudflare'\n// export { ipInfoTracer } from 'global-entities/geo-tag/tracers/ipinfo'\n\nexport default trace\n", "import axios from 'axios'\n\nimport { ITracer } from 'global-entities/geo-tag/tracers/types'\nimport { GeoTagStoreType } from 'global-entities/geo-tag/store/types'\n\nconst KEYS: {\n ip: 'IP',\n loc: 'countryCode',\n} = {\n ip: 'IP',\n loc: 'countryCode',\n}\n\ntype KeyType = keyof GeoTagStoreType\ntype AccumulatorType = {\n [key in KeyType]: string\n}\n\nexport const cloudflareTracer: ITracer = async ({ token }): Promise => {\n const { data } = await axios.get('https://www.cloudflare.com/cdn-cgi/trace', {\n cancelToken: token,\n })\n\n return data.split('\\n').reduce((accumulator: AccumulatorType, keyValue: string) => {\n const [key, value] = keyValue.split('=')\n\n if (key in KEYS) {\n // @ts-ignore\n accumulator[KEYS[key]] = value\n }\n\n return accumulator\n }, {} as AccumulatorType)\n}\n\nexport default cloudflareTracer\n", "import * as React from 'react'\nimport { useDispatch, useSelector } from 'react-redux'\n\nimport {\n setCountryCode,\n setIP,\n} from 'global-entities/geo-tag/store/actions'\nimport {\n COUNTRY_CODE,\n IP,\n} from 'global-entities/geo-tag/store/selectors'\nimport type {\n GeoTagStoreType,\n CountryCodeType,\n IPType,\n} from 'global-entities/geo-tag/store/types'\n\nconst useGeoTag = (): [{\n countryCode: GeoTagStoreType['countryCode'],\n IP: GeoTagStoreType['IP'],\n}, {\n setCountryCode: (countryCode: CountryCodeType) => void,\n setIP: (IP: IPType) => void,\n}] => {\n const dispatch = useDispatch()\n\n return [{\n countryCode: useSelector(COUNTRY_CODE),\n IP: useSelector(IP),\n }, {\n setCountryCode: React.useCallback((countryCode: CountryCodeType): void => {\n // @ts-ignore\n dispatch(setCountryCode(countryCode))\n }, []),\n setIP: React.useCallback((IP: IPType): void => {\n // @ts-ignore\n dispatch(setIP(IP))\n }, []),\n }]\n}\n\nexport default useGeoTag\n", "import { Dispatch } from 'redux'\n\nimport {\n SET_CONTRY_CODE,\n CountryCodeType,\n\n SET_IP,\n IPType,\n} from 'global-entities/geo-tag/store/types'\n\nexport interface ISetCountryCodeAction {\n type: typeof SET_CONTRY_CODE\n payload: CountryCodeType\n}\nexport const setCountryCode = (countryCode: CountryCodeType) => (dispatch: Dispatch) => {\n dispatch({ type: SET_CONTRY_CODE, payload: countryCode })\n}\n\nexport interface ISetIPAction {\n type: typeof SET_IP\n payload: IPType\n}\nexport const setIP = (IP: IPType) => (dispatch: Dispatch) => {\n dispatch({ type: SET_IP, payload: IP })\n}\n\n/* eslint-disable @typescript-eslint/indent */\nexport type GeoTagActions = ISetCountryCodeAction |\n ISetIPAction\n/* eslint-enable @typescript-eslint/indent */\n", "import { KEY } from 'global-entities/geo-tag/constants'\n\nimport type { IGeoTagStore } from 'global-entities/geo-tag/store/types'\n\nexport const COUNTRY_CODE = (state: IGeoTagStore): IGeoTagStore['geo-tag']['countryCode'] => state[KEY].countryCode\n\nexport const IP = (state: IGeoTagStore): IGeoTagStore['geo-tag']['IP'] => state[KEY].IP\n\nexport const GEO_TAG = (state: IGeoTagStore): IGeoTagStore['geo-tag'] => state[KEY]\n", "import { useEffect, useState } from \"react\";\nimport { useDispatch, useSelector } from \"react-redux\";\n\nimport { reset } from '@qwerty.software/ui-order-form/src/changed-data-reminder/store/actions'\nimport { ORDER_LAST_CHANGED_AT, HYDRATED } from \"@qwerty.software/ui-order-form/src/store/slices/order\";\n\nexport const useClearAfterTime = () => {\n const dispatch = useDispatch()\n\n const [cleaned, setCleaned] = useState(false)\n const orderLastChangeAt = useSelector(ORDER_LAST_CHANGED_AT)\n const storePersisted = useSelector(HYDRATED)\n\n useEffect(() => {\n if (storePersisted) {\n const currentTime = Date.now()\n\n // we need to clear the order form 24 hours after the last change\n if (currentTime - orderLastChangeAt > 24 * 60 * 60 * 1000) {\n dispatch(reset({}) as any)\n setCleaned(true)\n }\n }\n }, [storePersisted])\n\n return { orderStoreCleaned: cleaned }\n}\n", "import { createAsyncThunk } from '@reduxjs/toolkit'\n\nimport { slice as discountSlice } from 'global-entities/discount/slice'\nimport { slice as filesUploaderSlice } from 'global-entities/files-uploader/slice'\n\nimport { stepSlice } from '@qwerty.software/ui-order-form/src/store/slices/step/slice-creator'\nimport chatBotSlice from '@qwerty.software/chat-bot/src/store/slice'\nimport { orderSlice } from '@qwerty.software/ui-order-form/src/store/slices/order'\nimport { ORDER_NAMESPACE } from '@qwerty.software/ui-order-form/src/constants'\n\ninterface Namespaces {\n discountNamespace?: string\n filesUploaderNamespace?: string\n}\n\ninterface ResetArgs extends Namespaces { }\n\nexport const reset = createAsyncThunk('reset/order', (args, api) => {\n api.dispatch(discountSlice.actions.resetDiscount({ namespace: args?.discountNamespace || ORDER_NAMESPACE }))\n api.dispatch(filesUploaderSlice.actions.resetFiles({ namespace: args?.filesUploaderNamespace || ORDER_NAMESPACE }))\n\n api.dispatch(orderSlice.actions.reset({}))\n api.dispatch(chatBotSlice.actions.reset())\n api.dispatch(stepSlice.actions.reset())\n})", "import { createSlice, createSelector, PayloadAction } from '@reduxjs/toolkit'\nimport { persistReducer } from 'redux-persist'\nimport localforage from 'localforage'\n\nimport { STEP_SAGA } from '../../sagas/step/constants'\nimport { ForwardAction, GoAction, NextAction } from '../../sagas/step/types'\n\nimport { go } from './utils/go'\n\nimport { NAME } from './constants'\nimport type { StepState, Steps } from './types'\n\nexport const createStepSlice = (\n steps: Steps,\n {\n MIN_STEP_INDEX = 0,\n MAX_STEP_INDEX = steps.length - 1,\n INITIAL_INDEX = 0,\n }: {\n MIN_STEP_INDEX?: number,\n MAX_STEP_INDEX?: number,\n INITIAL_INDEX?: number,\n } = {}\n) => {\n const initialState = {\n activeStep: INITIAL_INDEX,\n isFirst: INITIAL_INDEX === MIN_STEP_INDEX,\n isLast: INITIAL_INDEX === MAX_STEP_INDEX,\n }\n const slice = createSlice({\n name: `slice://${NAME}/`,\n initialState,\n reducers: {\n set(state, action: PayloadAction) {\n go(action.payload, MIN_STEP_INDEX, MAX_STEP_INDEX).forEach(([key, value]) => {\n state[key] = value\n })\n },\n reset(state) {\n Object.keys(state).forEach(key => {\n state[key] = initialState[key]\n })\n }\n },\n })\n\n slice.reducer = persistReducer({\n keyPrefix: '',\n key: slice.name,\n // TODO: Disable serialization.\n // serialize: false,\n storage: localforage.createInstance({\n name: '[MSH] Storage',\n storeName: NAME,\n driver: [\n // localforage.INDEXEDDB,\n localforage.LOCALSTORAGE,\n ]\n }),\n }, slice.reducer) as unknown as typeof slice.reducer\n\n // @ts-ignore\n const HYDRATED = (state: State): void | boolean => state[slice.name]?._persist?.rehydrated\n\n const stepSlice = slice\n\n interface State {\n //@ts-ignore\n [stepSlice.name]: StepState\n }\n\n const ACTIVE_STEP = createSelector(getState, state => state?.activeStep)\n const TITLE = createSelector(getState, state => steps[state?.activeStep]?.title)\n const IS_FIRST = createSelector(getState, state => state?.isFirst)\n const IS_LAST = createSelector(getState, state => state?.isLast)\n\n const actions = {\n forward: (): ForwardAction => ({\n type: STEP_SAGA,\n payload: { direction: false },\n }),\n go: (step: number): GoAction => ({\n type: STEP_SAGA,\n payload: { step },\n }),\n next: (): NextAction => ({\n type: STEP_SAGA,\n payload: { direction: true },\n }),\n }\n\n return {\n STEPS: steps,\n stepSlice: slice,\n actions,\n selectors: {\n HYDRATED,\n ACTIVE_STEP,\n TITLE,\n IS_FIRST,\n IS_LAST,\n }\n }\n\n function getState(state) {\n return state[slice.name] as StepState\n }\n}\n\nexport type Selectors = ReturnType['selectors']\n", "import { SAGAS_SCHEMA } from 'constants/sagas'\nimport { NAME } from '../../slices/step/constants'\n\nexport const STEP_SAGA = `${SAGAS_SCHEMA}${NAME}/go` as const", "export const NAME = 'order-form/steps'\n", "export const number = (num: number, min: number = -Infinity, max: number = Infinity) => {\n if (num < min) {\n return min\n }\n\n if (num > max) {\n return max\n }\n\n return num\n}", "import { number } from '@qwerty.software/ui-order-form/src/utils/sanitizers/number'\n\nexport const go = (index, MIN_STEP_INDEX, MAX_STEP_INDEX) => {\n index = number(index, MIN_STEP_INDEX, MAX_STEP_INDEX)\n\n return Object.entries({\n activeStep: index,\n isFirst: index === MIN_STEP_INDEX,\n isLast: index === MAX_STEP_INDEX,\n })\n}\n", "import { createStepSlice } from '@qwerty.software/ui-order-form/src/store/slices/step'\nimport type { Steps } from '@qwerty.software/ui-order-form/src/store/slices/step/types'\n\n// import { topicValidation } from './form-fields/topic/validator'\n\nexport enum Variant {\n ORDER = 'order',\n CALCULATOR = 'calculator',\n}\n\nexport enum Step {\n PAPER_INFORMATION,\n PRICE_CALCULATION,\n EXTRA_FEATURES,\n}\n\nconst steps: Steps = [\n {\n title: 'Paper information',\n // validation: [\n // topicValidation\n // ]\n },\n {\n title: 'Price calculation',\n },\n {\n title: 'Extra features',\n },\n]\n\nexport const slice = createStepSlice(steps)\nexport const { selectors } = slice\nexport const {\n stepSlice,\n actions: stepActions,\n selectors: {\n HYDRATED,\n ACTIVE_STEP,\n TITLE,\n IS_FIRST,\n IS_LAST,\n },\n STEPS,\n} = slice\n", "import { createSlice, PayloadAction } from '@reduxjs/toolkit'\n\nimport _omit from 'lodash/omit'\n\nimport hashsum from 'hash-sum'\n\nimport {\n BotState,\n\n SenderType as Sender,\n\n BotMessageTypesMap,\n UserMessageTypesMap,\n} from './definitions'\n\nimport scssVariables from '../variables.module.scss'\n\nconst INITIAL_STATE: BotState = {\n messages: [],\n input: null,\n wasChanged: [],\n}\n\nconst slice = createSlice({\n name: scssVariables.domain,\n initialState: INITIAL_STATE,\n reducers: {\n botPush: (\n state,\n action: PayloadAction & {\n id?: string\n beforeMessageId?: string\n afterMessageId?: string\n }>,\n ) => {\n const id = action.payload.id || hashsum(action.payload)\n\n const message = {\n id,\n sender: Sender.BOT,\n\n ..._omit(action.payload, ['id', 'sender', 'beforeMessageId', 'afterMessageId']),\n }\n\n if (action.payload.beforeMessageId) {\n const index = state.messages.findIndex(message => message.id === action.payload.beforeMessageId)\n\n if (index !== -1) {\n state.messages.splice(index, 0, message)\n\n return\n }\n }\n\n if (action.payload.afterMessageId) {\n const index = state.messages.findIndex(message => message.id === action.payload.afterMessageId)\n\n if (index !== -1) {\n state.messages.splice(index + 1, 0, message)\n\n return\n }\n }\n\n state.messages.push(message)\n },\n userPush: (\n state,\n action: PayloadAction & {\n id?: string\n beforeMessageId?: string\n afterMessageId?: string\n }>,\n ) => {\n const id = action.payload.id || hashsum(action.payload)\n\n const message = {\n id,\n sender: Sender.USER,\n\n ..._omit(action.payload, ['id', 'sender'])\n }\n\n if (action.payload.beforeMessageId) {\n const index = state.messages.findIndex(message => message.id === action.payload.beforeMessageId)\n\n if (index !== -1) {\n state.messages.splice(index, 0, message)\n\n return\n }\n }\n\n if (action.payload.afterMessageId) {\n const index = state.messages.findIndex(message => message.id === action.payload.afterMessageId)\n\n if (index !== -1) {\n state.messages.splice(index + 1, 0, message)\n\n return\n }\n }\n\n state.messages.push(message)\n },\n\n update: (state, action: PayloadAction) => {\n const index = state.messages.findIndex(message => message.id === action.payload.id)\n\n if (index === -1) {\n return\n }\n\n state.messages[index] = action.payload\n },\n\n setChanged: (state, action: PayloadAction) => {\n if (!state.wasChanged.includes(action.payload)) {\n state.wasChanged = [...state.wasChanged, action.payload]\n }\n },\n\n remove: (state, action: PayloadAction) => {\n state.messages = state.messages.filter(message => message.id !== action.payload)\n },\n\n input: (state, action: PayloadAction) => {\n state.input = action.payload\n },\n\n reset: (state) => {\n delete state.expiredAt\n\n state.messages = []\n state.input = null\n },\n\n expireAt: (state, action: PayloadAction) => {\n state.expiredAt = action.payload ? action.payload : Date.now() + 10 * 1000 // expires in 10 seconds\n },\n },\n})\n\nexport const CHANGED_SELECTOR = (state: BotState): BotState['wasChanged'] => state[slice.name]['wasChanged']\n\nexport default slice", "import { createAction } from '@reduxjs/toolkit'\n\nimport _kebabCase from 'lodash/kebabCase'\n\nimport { WriterCategoryIds, FieldNames } from '@qwerty.software/ui-order-form/src/store/constants'\nimport { PickedBdFields } from '@qwerty.software/ui-order-form/src/store/slices/order'\n\nimport { FileMeta, NAME as FILE_UPLOADER_NAME } from 'global-entities/files-uploader/definitions'\nimport { DiscountMeta, APPLY_DISCOUNT_KEY, NAME as DISCOUNT_NAME } from 'global-entities/discount/definitions'\n\nimport { SAGAS_SCHEMA } from 'constants/sagas'\nimport scssVariables from '../variables.module.scss'\n\nexport const DOMAIN = `${scssVariables.domain}.bot` as const\n\nexport interface BotState {\n messages: Array\n input: Input | null\n expiredAt?: number\n wasChanged?: string[]\n}\n\nexport const FINAL_SUBMIT = 'final-submit' as const\nexport type FINAL_SUBMIT = typeof FINAL_SUBMIT\n\nexport type Input = FieldNames.TOPIC\n | FieldNames.WORK_TYPE\n | FieldNames.QUANTITY\n | FieldNames.DEADLINE\n | FieldNames.PAPER_DETAILS\n | FieldNames.WRITER_CATEGORY\n | FieldNames.ADDITIONAL_FEATURES\n | DISCOUNT_NAME\n | FINAL_SUBMIT\n\nexport enum SenderType {\n BOT = 'BOT',\n USER = 'USER',\n}\n\nexport enum BotMessageType {\n ADDITIONAL_FEATURES = PickedBdFields.additionalFeatures,\n WRITER_CATEGORIES = PickedBdFields.writerCategories,\n TEXT = 'TEXT',\n TYPING = 'TYPING',\n}\n\nexport enum UserMessageType {\n TOPIC = FieldNames.TOPIC,\n WORK_TYPE = FieldNames.WORK_TYPE,\n QUANTITY = FieldNames.QUANTITY,\n DEADLINE = FieldNames.DEADLINE,\n PAPER_DETAILS = FieldNames.PAPER_DETAILS,\n MATERIALS = 'files-uploader', // FILE_UPLOADER_NAME\n WRITER_CATEGORY = FieldNames.WRITER_CATEGORY,\n ADDITIONAL_FEATURES = FieldNames.ADDITIONAL_FEATURES,\n DISCOUNT = 'discount', // DISCOUNT_NAME\n TEXT = 'TEXT',\n}\n\nexport type BotMessageTypesMap = {\n [BotMessageType.ADDITIONAL_FEATURES]: BotAdditionalFeaturesMessage\n [BotMessageType.WRITER_CATEGORIES]: BotWriterCategoriesMessage\n [BotMessageType.TEXT]: BotTextMessage\n [BotMessageType.TYPING]: BotTypingMessage\n}\n\nexport type UserMessageTypesMap = {\n [UserMessageType.TOPIC]: UserTopicMessage\n [UserMessageType.WORK_TYPE]: UserWorkTypeMessage\n [UserMessageType.QUANTITY]: UserQuantityMessage\n [UserMessageType.DEADLINE]: UserDeadlineMessage\n [UserMessageType.PAPER_DETAILS]: UserPaperDetailsMessage\n [UserMessageType.MATERIALS]: UserMaterialsMessage\n [UserMessageType.WRITER_CATEGORY]: UserWriterCategoryMessage\n [UserMessageType.ADDITIONAL_FEATURES]: UserAdditionalFeaturesMessage\n [UserMessageType.DISCOUNT]: UserDiscountMessage\n [UserMessageType.TEXT]: UserTextMessage\n}\n\nexport interface BaseMessage {\n id: string\n}\n\nexport interface BotMessage extends BaseMessage {\n sender: SenderType.BOT\n type: BotMessageType\n}\n\nexport interface UserMessage extends BaseMessage {\n sender: SenderType.USER\n type: UserMessageType\n}\n\nexport interface MessageMeta {\n id: ID | null\n isLast: boolean\n}\n\ntype ID = number | string\n\n//#region Bot messages\nexport interface BotAdditionalFeaturesMessage extends BotMessage {\n // As filter and sorter, if not isset - all features in bootstrap-data order will displayed\n features?: ID[]\n}\n\nexport interface BotWriterCategoriesMessage extends BotMessage {\n // As filter and sorter, if not isset - all categories in bootstrap-data order will displayed\n categories?: WriterCategoryIds[]\n}\n\nexport interface BotTextMessage extends BotMessage {\n text: string | Selector\n}\n\nexport interface BotTypingMessage extends BotMessage { }\n//#endregion Bot messages\n\nexport type Selector = (state: TState) => TValue\n\nexport type SelectorMap = {\n [FieldNames.TOPIC]: Selector