) => {\n event.preventDefault();\n\n const otp = getOTPValue();\n let nextActiveInput = activeInput;\n\n // Get pastedData in an array of max size (num of inputs - current position)\n const pastedData = event.clipboardData\n .getData('text/plain')\n .slice(0, numInputs - activeInput)\n .split('');\n\n // Prevent pasting if the clipboard data contains non-numeric values for number inputs\n if (isInputNum && pastedData.some((value) => isNaN(Number(value)))) {\n return;\n }\n\n // Paste data from focused input onwards\n for (let pos = 0; pos < numInputs; ++pos) {\n if (pos >= activeInput && pastedData.length > 0) {\n otp[pos] = pastedData.shift() ?? '';\n nextActiveInput++;\n }\n }\n\n focusInput(nextActiveInput);\n handleOTPChange(otp);\n };\n\n return (\n \n {Array.from({ length: numInputs }, (_, index) => index).map((index) => (\n \n {renderInput(\n {\n value: getOTPValue()[index] ?? '',\n placeholder: getPlaceholderValue()?.[index] ?? undefined,\n ref: (element) => (inputRefs.current[index] = element),\n onChange: handleChange,\n onFocus: (event) => handleFocus(event)(index),\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n onPaste: handlePaste,\n autoComplete: 'off',\n 'aria-label': `Please enter OTP character ${index + 1}`,\n style: Object.assign(\n !skipDefaultStyles ? ({ width: '1em', textAlign: 'center' } as const) : {},\n isStyleObject(inputStyle) ? inputStyle : {}\n ),\n className: typeof inputStyle === 'string' ? inputStyle : undefined,\n type: inputType,\n inputMode: isInputNum ? 'numeric' : 'text',\n onInput: handleInputChange,\n },\n index\n )}\n {index < numInputs - 1 && (typeof renderSeparator === 'function' ? renderSeparator(index) : renderSeparator)}\n \n ))}\n
\n );\n};\n\nexport type { OTPInputProps, InputProps, AllowedInputTypes };\nexport default OTPInput;\n","import { css, media, styled, typography } from '@pulse-web-ui/theme';\n\nexport const OtpContainer = styled.div`\n margin-bottom: 56px;\n ${media.desktop} {\n margin-bottom: 8px;\n }\n\n .otp-input {\n input {\n transition: border-color 0.2s ease-in-out;\n }\n }\n`;\n\ninterface InputProps {\n error?: boolean;\n}\n\nexport const StyledOtpInput = styled.input`\n ${typography.regular18}\n width: 48px !important;\n height: 56px;\n margin-right: 8px;\n box-sizing: border-box;\n border-radius: calc(${({ theme }) => theme.common.radius} * 3);\n background-color: ${({ theme }) => theme.colors.neutral[10]};\n color: ${({ theme }) => theme.colors.text.primary};\n outline: none;\n\n ${({ theme, error }) =>\n !!error\n ? css`\n border: 1px solid ${theme.colors?.accent.error.normal};\n background-color: ${theme.colors?.accent.error.faded};\n color: ${theme.colors?.accent.error.normal};\n\n &:hover {\n border: 1px solid ${theme.colors?.accent.error.normal};\n }\n `\n : css`\n border: 1px solid ${({ theme }) => theme.colors.neutral[10]};\n\n &:hover {\n border: 1px solid ${({ theme }) => theme.colors.neutral[30]};\n }\n `};\n`;\n","import { createRef, forwardRef, memo, useEffect, useRef } from 'react';\nimport OtpInput from 'react-otp-input';\n\nimport { HelperText } from '@pulse-web-ui/helper-text';\n\nimport { CenteredWrapper, GridColumnContainer } from '@src/components';\n\nimport { Resend } from './components';\nimport { OtpContainer, StyledOtpInput } from './otp.styles';\nimport { OtpProps } from './otp.types';\n\nexport const Otp = memo(\n forwardRef(\n (\n {\n expiryTimestamp,\n onResend,\n status,\n onAbleResendOtp,\n limit = 6,\n onChange,\n extraMessage,\n disabled,\n alignment,\n isExpiryTimestampText,\n gridStep,\n style,\n code,\n },\n ref\n ) => {\n const inputRefs = useRef([]);\n inputRefs.current = new Array(limit).map(\n (_, i) => inputRefs.current[i] ?? createRef()\n );\n const hasError = status?.status === 'error';\n const isAfterErrorState = code?.length === limit && hasError;\n\n useEffect(() => {\n if (hasError && !!inputRefs.current?.length) {\n inputRefs.current.forEach((input, index) => {\n if (index === 0) {\n input.focus();\n } else {\n input.blur();\n }\n });\n }\n }, [hasError]);\n\n const otpChangeHandler = (val: string) => {\n if (!isAfterErrorState) {\n onChange(val);\n }\n };\n\n /* eslint-disable indent */\n const handleKeyDown =\n (onKeyDown: React.KeyboardEventHandler) =>\n (e: React.KeyboardEvent) => {\n const inputValue = (e.target as HTMLInputElement).value;\n const isNumberKeyPressed = !!Number(e.key) || e.key === '0';\n const sameValue = inputValue === e.key;\n\n if (isAfterErrorState && isNumberKeyPressed) {\n if (sameValue) {\n onChange(e.key);\n } else {\n onChange('');\n }\n }\n onKeyDown(e);\n };\n /* eslint-enable */\n\n return (\n \n \n \n \n \n }\n renderInput={({ ref, ...props }, index) => (\n {\n if (instance) {\n inputRefs.current[index] = instance;\n }\n ref(instance);\n }}\n disabled={disabled}\n error={hasError}\n {...props}\n onKeyDown={handleKeyDown(props.onKeyDown)}\n type=\"text\"\n />\n )}\n />\n \n
\n \n\n {extraMessage && {extraMessage}}\n {expiryTimestamp && (\n \n \n \n )}\n \n \n );\n }\n )\n);\n","import { media, mixins, styled, typography } from '@pulse-web-ui/theme';\n\nexport const TotalSumWrapper = styled.div<{ isError: boolean }>`\n border: ${({ isError, theme }) =>\n isError\n ? `2px solid ${theme.colors.accent.error.normal}`\n : `2px solid ${theme.colors.surface.background}`};\n border-radius: ${({ theme }) => theme.common.radius12};\n padding: 16px 24px 12px;\n box-sizing: border-box;\n width: 100%;\n background: ${({ isError, theme }) =>\n isError\n ? theme.colors.accent.error.faded\n : theme.colors.surface.background};\n\n ${mixins.flex({ horizontal: false })}\n ${media.desktop} {\n min-height: 114px;\n padding: 16px 24px;\n min-height: 114px;\n }\n`;\n\nexport const TotalSumValue = styled.div`\n ${typography.medium24}\n color: ${({ theme }) => theme.colors.text.primary};\n white-space: nowrap;\n`;\n\nexport const TotalSumTitle = styled.div`\n ${typography.regular16}\n line-height: 24px;\n color: ${({ theme }) => theme.colors.text.primary};\n white-space: nowrap;\n`;\n\nexport const TotalSumSubtitle = styled.div<{ isError: boolean }>`\n ${typography.regular16}\n line-height: 24px;\n color: ${({ isError, theme }) =>\n isError ? theme.colors.text.error : theme.colors.text.secondary};\n letter-spacing: 0.02em;\n`;\n","import { FC } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { UnicodeEnum } from '@src/constants';\n\nimport {\n TotalSumSubtitle,\n TotalSumTitle,\n TotalSumValue,\n TotalSumWrapper,\n} from './total-sum.styles';\nimport { TotalSumProps } from './total-sum.types';\n\nexport const TotalSum: FC = ({\n totalSum,\n isError,\n subtitleText,\n title,\n}) => {\n const { t } = useTranslation();\n\n return (\n \n \n {title || `${t('COMMON:labels.coverAmount')}:`}\n \n \n {totalSum} {UnicodeEnum.RUB}\n \n {subtitleText}\n \n );\n};\n","/* eslint-disable indent */\nimport { media, mixins, styled, typography } from '@pulse-web-ui/theme';\n\nimport type { SumPerPeriodWrapperProps } from './ifl-sum-per-period.types';\n\nexport const SumPerPeriodWrapper = styled.div`\n ${mixins.flex({ horizontal: false, justifyContent: 'flex-start' })}\n color: ${({ theme }) => theme.colors.text.primary};\n padding: 16px 24px 12px;\n border-radius: ${({ theme }) => theme.common.radius12};\n opacity: ${(props) => (props.disabled ? 0.3 : 1)};\n background: ${({ theme }) => theme.colors.surface.background};\n min-height: 81px;\n box-sizing: border-box;\n width: 100%;\n justify-content: flex-start;\n\n ${media.desktop} {\n min-height: 114px;\n height: 100%;\n }\n`;\n\nexport const SumPerPeriodValue = styled.div`\n ${typography.medium24}\n white-space: nowrap;\n margin-bottom: 2px;\n`;\n\nexport const SumPerPeriodTitle = styled.div`\n ${typography.regular16}\n margin-bottom: 2px;\n`;\n\nexport const StyledSpinnerWrapper = styled.div`\n margin-top: 6px;\n`;\n\nexport const SumPerPeriodErrorMessage = styled.div`\n ${typography.regular14}\n letter-spacing: 0.02em;\n color: ${({ theme }) => theme.colors.text.error};\n padding-top: 16px;\n\n ${media.desktop} {\n padding-top: 13px;\n }\n`;\n\nexport const SumPerPeriodDescWrapper = styled.div`\n ${typography.regular16}\n line-height: 24px;\n color: ${({ theme }) => theme.colors.text.secondary};\n`;\n\nexport const SumPerPeriodPromoWrapper = styled.div`\n margin-bottom: 2px;\n`;\n\nexport const SumPerPeriodBaseValue = styled.span`\n ${typography.regular16}\n line-height: 24px;\n text-decoration: line-through;\n color: ${({ theme }) => theme.colors.text.secondary};\n margin-left: 8px;\n`;\n\nexport const SumPerPeriodPromoValue = styled.span`\n ${typography.medium24}\n`;\n\nexport const SumPerPeriodPromoDesc = styled.span`\n ${typography.medium24}\n color: ${({ theme }) => theme.colors.text.primary};\n`;\n","import type { FC } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Spinner } from '@pulse-web-ui/spinner';\n\nimport { UnicodeEnum } from '@src/constants';\nimport { currencyRuLocaleWithoutFraction } from '@src/utils';\n\nimport {\n StyledSpinnerWrapper,\n SumPerPeriodBaseValue,\n SumPerPeriodDescWrapper,\n SumPerPeriodPromoDesc,\n SumPerPeriodPromoValue,\n SumPerPeriodPromoWrapper,\n SumPerPeriodTitle,\n SumPerPeriodValue,\n SumPerPeriodWrapper,\n} from './ifl-sum-per-period.styles';\nimport type { SumPerPeriodProps } from './ifl-sum-per-period.types';\n\nexport const SumPerPeriod: FC = ({\n isLoading,\n disabled,\n sumPerPeriod,\n sumPromoPerPeriod,\n sumPerPeriodDesc,\n title,\n description,\n isError,\n}) => {\n const { t } = useTranslation();\n\n return (\n \n \n {title || t('COMMON:labels.insuranceCostLabel')}\n \n {isLoading || !sumPerPeriod ? (\n \n \n \n ) : sumPromoPerPeriod ? (\n <>\n \n \n {`${currencyRuLocaleWithoutFraction(sumPromoPerPeriod)} ${\n UnicodeEnum.RUB\n }`}\n \n {sumPerPeriodDesc && (\n {sumPerPeriodDesc}\n )}\n \n {currencyRuLocaleWithoutFraction(sumPerPeriod)} {UnicodeEnum.RUB}\n \n \n {description && (\n {description}\n )}\n >\n ) : (\n <>\n \n {`${currencyRuLocaleWithoutFraction(sumPerPeriod)} ${\n UnicodeEnum.RUB\n } ${sumPerPeriodDesc ?? ''}`}\n \n {description && (\n {description}\n )}\n >\n )}\n \n );\n};\n","/* eslint-disable indent */\nimport { useTranslation } from 'react-i18next';\n\nimport { SumPerPeriodErrorMessage } from './ifl-sum-per-period.styles';\nimport { SumPerPeriodErrorProps } from './ifl-sum-per-period.types';\n\nexport const SumPerPeriodError = ({\n errorResponse,\n currentSumErr,\n}: SumPerPeriodErrorProps) => {\n const { t } = useTranslation();\n const errorCode = errorResponse?.response?.data?.code;\n\n if (\n errorCode === 'VALIDATION_ERROR' ||\n errorCode === 'TECHNICAL_ERROR' ||\n errorCode === 'BUSINESS_ERROR'\n ) {\n let msg =\n errorCode === 'BUSINESS_ERROR'\n ? t('COMMON:errors.costMoreReduceYourCoverage')\n : t('COMMON:errors.impossibleCalculate');\n\n switch (currentSumErr) {\n case 'less':\n msg = t('COMMON:errors.coverageLessMin');\n break;\n case 'gt':\n msg = t('COMMON:errors.coverageAboveLimit');\n break;\n }\n return {msg};\n }\n\n return null;\n};\n","import { Button } from '@pulse-web-ui/button';\nimport { media, mixins, styled, typography } from '@pulse-web-ui/theme';\n\nexport const SupportBlockContent = styled.div`\n box-sizing: border-box;\n padding-top: 40px;\n\n ${media.desktop} {\n padding-top: 32px;\n }\n`;\n\nexport const SupportBlockTitle = styled.h3`\n ${typography.medium18};\n line-height: 26px;\n margin-bottom: 24px;\n`;\n\nexport const SupportButtonsWrapper = styled.div`\n ${mixins.flex({\n gap: 12,\n horizontal: false,\n })}\n\n ${media.desktop} {\n ${mixins.flex({ gap: 12 })}\n }\n`;\n\nexport const SupportButton = styled(Button)`\n height: 48px;\n padding: 8px 32px;\n`;\n","import { useTranslation } from 'react-i18next';\n\nimport { PhoneClassic } from '@pulse-web-ui/icons';\nimport { useTheme } from '@pulse-web-ui/theme';\nimport type { BaseThemeType } from '@pulse-web-ui/theme';\n\nimport {\n SupportBlockContent,\n SupportBlockTitle,\n SupportButton,\n SupportButtonsWrapper,\n} from './new-support.styles';\n\nexport const NewSupportBlock = () => {\n const { t } = useTranslation();\n const theme = useTheme() as BaseThemeType;\n\n return (\n \n {t('AUTH:headers.contactSupport')}\n \n }\n onClick={() => (window.location.href = 'tel:+78003021554')}\n >\n {t('COMMON:labels.freeCall')}\n \n \n \n );\n};\n","import { styled, typography } from '@pulse-web-ui/theme';\n\nexport const InsurancePriceCardContainer = styled.div`\n width: 100%;\n box-sizing: border-box;\n // TODO: RGS_ONLINE_THEME. Добавить border для партнеров. border: 2px solid theme.colors.surface.brand;\n padding: 16px 24px;\n color: ${({ theme }) => theme.colors.text.primary};\n border-radius: ${({ theme }) => theme.common.radius12};\n // TODO: RGS_ONLINE_THEME. Убрать background для партнеров.\n background-color: ${({ theme }) => theme.colors.surface.background};\n`;\n\nexport const InsurancePriceCardTitle = styled.div`\n ${typography.regular16};\n margin-bottom: 2px;\n`;\n\nexport const InsurancePriceCardPremiumAndDelta = styled.div`\n ${typography.medium20};\n`;\n","import { Spinner } from '@pulse-web-ui/spinner';\n\nimport { FRACTION_TWO, UnicodeEnum } from '@src/constants';\nimport { currencyRuLocaleWithoutFraction } from '@src/utils';\n\nimport {\n InsurancePriceCardContainer,\n InsurancePriceCardPremiumAndDelta,\n InsurancePriceCardTitle,\n} from './insurance-price-card.styles';\n\ninterface Props {\n title: string;\n isLoading: boolean;\n premiumAndDelta?: string;\n}\n\nexport const InsurancePriceCard = ({\n premiumAndDelta,\n title,\n isLoading,\n}: Props) => (\n \n {title}\n {!!premiumAndDelta && !isLoading ? (\n \n {currencyRuLocaleWithoutFraction(\n parseFloat(premiumAndDelta),\n FRACTION_TWO\n )}{' '}\n {UnicodeEnum.RUB}\n \n ) : (\n \n )}\n \n);\n","import { Input } from '@pulse-web-ui/input';\nimport { styled } from '@pulse-web-ui/theme';\n\nexport const PromoCodeInput = styled(Input)`\n & + label {\n top: ${({ value }) => (value?.length ? '7px' : '17px')};\n }\n`;\n","/* eslint-disable indent */\nimport { yupResolver } from '@hookform/resolvers/yup';\nimport { useContext, useEffect, useState } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\n\nimport { HelperText } from '@pulse-web-ui/helper-text';\n\nimport { PromoSubmitButton } from '@src/common-components/button';\nimport {\n PromoTextInputWrapper,\n PromoWrapper,\n} from '@src/common-components/container';\nimport { PromoCodeInput } from '@src/features/promo-code/prom-code.styles';\nimport { useHandlePressKey } from '@src/hooks';\nimport { formInsurancePeriodSchema } from '@src/schemas';\nimport { Store, UserActionTypes, WizardActionTypes } from '@src/store';\nimport { FormPromoProps, KeyCode } from '@src/types';\nimport { addTestAttribute, getPercentageDiff } from '@src/utils';\n\ninterface Props {\n promoCode?: string;\n isSuccessfulPromo?: boolean;\n premiumAndDelta?: string;\n premiumAndDeltaPromo?: string;\n isLoading?: boolean;\n isPricesLoading: boolean;\n onChange?: (promoCode?: string) => void;\n onSubmit: (promoCode?: string) => void;\n discountHintKey?: string;\n className?: string;\n}\n\nexport const PromoCode = ({\n promoCode,\n isSuccessfulPromo,\n premiumAndDelta,\n premiumAndDeltaPromo,\n isLoading,\n isPricesLoading,\n onChange,\n onSubmit,\n discountHintKey,\n className,\n}: Props) => {\n const {\n dispatch,\n state: {\n stateUser: { promoCodeFailedMessage },\n stateAuthFlow: { authStep },\n },\n } = useContext(Store);\n const { t } = useTranslation(['COMMON']);\n const [submitPromoDisabled, setSubmitPromoDisabled] = useState(false);\n const [isInputActive, setIsInputActive] = useState(false);\n const checkSubmitState = (val: string) => {\n setSubmitPromoDisabled(val === promoCode);\n };\n\n const {\n control,\n formState: { errors },\n handleSubmit,\n setError,\n clearErrors,\n watch,\n getValues,\n } = useForm({\n resolver: yupResolver(formInsurancePeriodSchema),\n shouldFocusError: true,\n mode: 'all',\n defaultValues: { promoCode },\n });\n\n useEffect(() => {\n const { promoCode: promoCodeValue } = getValues();\n if (promoCodeValue?.length === 0 && !isSuccessfulPromo) {\n dispatch({\n type: UserActionTypes.SetPromoCodeFailedMessage,\n payload: undefined,\n });\n onSubmit(undefined);\n }\n }, [watch('promoCode')]);\n\n useEffect(() => {\n const subscription = watch((value) => {\n if (onChange) {\n onChange(value.promoCode ? value.promoCode : '');\n }\n });\n\n return () => subscription.unsubscribe();\n }, [watch]);\n\n const submitPromoCode = handleSubmit((data) => {\n dispatch({\n type: UserActionTypes.SetPromoCodeFailedMessage,\n payload: undefined,\n });\n onSubmit(!!data.promoCode?.length ? data.promoCode : undefined);\n });\n\n const handleKeyPressEnter = () => {\n if (isInputActive) {\n submitPromoCode();\n } else if (authStep) {\n return;\n } else {\n dispatch({\n type: WizardActionTypes.UpdateWantNextStep,\n payload: true,\n });\n }\n };\n useHandlePressKey(KeyCode.ENTER, handleKeyPressEnter, [isInputActive]);\n\n const getLabel = () => {\n const { promoCode: statePromoCode } = getValues();\n\n return isSuccessfulPromo && promoCode === statePromoCode\n ? t('COMMON:success.applied')\n : t('COMMON:success.apply');\n };\n\n useEffect(() => {\n setSubmitPromoDisabled(!!isSuccessfulPromo && promoCode !== '');\n }, [isSuccessfulPromo, promoCode]);\n\n useEffect(() => {\n if (!isPricesLoading && isSuccessfulPromo === false && !!promoCode) {\n setError('promoCode', {\n type: 'string',\n message: t('COMMON:errors.promoCodeNotValid') || '',\n });\n dispatch({\n type: UserActionTypes.SetPromoCodeFailedMessage,\n payload: t('COMMON:errors.promoCodeNotValid') || '',\n });\n }\n if (!isPricesLoading && isSuccessfulPromo && !!promoCode) {\n clearErrors('promoCode');\n }\n }, [isPricesLoading, isSuccessfulPromo, promoCode]);\n\n useEffect(() => {\n if (!promoCode?.length) {\n clearErrors('promoCode');\n }\n }, [promoCode]);\n\n return (\n \n \n (\n \n {\n checkSubmitState(val);\n onChange(val);\n }}\n onFocus={() => setIsInputActive(true)}\n onBlur={() => setIsInputActive(false)}\n error={\n !!errors.promoCode ||\n (!!promoCodeFailedMessage && !isSuccessfulPromo)\n }\n disabled={isLoading}\n {...addTestAttribute('promocode.input')}\n />\n \n )}\n />\n \n \n \n );\n};\n","import { styled } from '@pulse-web-ui/theme';\n\nexport const ToggleButton = styled.span`\n display: inline-block;\n margin-top: 16px;\n`;\n","/* eslint-disable indent */\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Button } from '@pulse-web-ui/button';\n\nimport { AdaptiveListWrapper } from '@src/components';\nimport { numWord } from '@src/utils';\n\nimport { ToggleButton } from './risks-accordion.styles';\n\nconst MAX_COUNT = 2;\n\ninterface Props {\n children: JSX.Element[];\n}\n\nexport const RisksAccordion = ({ children }: Props) => {\n const { t } = useTranslation(['RISKS_ACCORDION']);\n const remainder = children.length - MAX_COUNT;\n const declensions = [\n t('COMMON:declensions.risk'),\n t('COMMON:declensions.risk-2'),\n t('COMMON:declensions.risk-3'),\n ];\n const [isOpen, setIsOpen] = useState(false);\n\n return (\n <>\n \n {isOpen ? children : children.slice(0, MAX_COUNT)}\n \n {children.length > MAX_COUNT && (\n \n \n \n )}\n >\n );\n};\n","import { mixins, styled } from '@pulse-web-ui/theme';\n\nexport const SettingsWrapper = styled.div`\n ${mixins.flex({ justifyContent: 'space-between', alignItems: 'center' })}\n`;\n","import {\n SubscriptionCard,\n SubscriptionCardGroup,\n} from '@pulse-web-ui/subscription-card';\nimport { media, styled } from '@pulse-web-ui/theme';\n\nexport const StyledSubscriptionCard = styled(SubscriptionCard)`\n ${media.desktop} {\n width: calc(100% / 3 - 16px / 3);\n height: 152px;\n }\n`;\n\nexport const StyledSubscriptionCardGroup = styled(SubscriptionCardGroup)`\n margin-bottom: 32px;\n gap: 8px;\n`;\n","import React, { VFC, memo } from 'react';\n\nimport { NewRadio, NewRadioGroup } from '@pulse-web-ui/new-radio-group';\n\nimport { PaymentPeriodsListWrapper, Skeleton } from '@src/components';\nimport { FeatureFlags } from '@src/constants';\nimport { useFeatureFlags } from '@src/hooks';\nimport { Price, SelectedDuration } from '@src/types';\n\nimport {\n StyledSubscriptionCard,\n StyledSubscriptionCardGroup,\n} from './payment-period-list.styles';\n\ninterface Props {\n onChange: (value: SelectedDuration) => void;\n selectedDuration: SelectedDuration | null;\n prices: Price[];\n getLabel: (\n price: Price,\n isFeatureSubscriptionType: boolean\n ) => JSX.Element | string | undefined;\n getDescription: (\n price: Price,\n isFeatureSubscriptionType: boolean\n ) => JSX.Element | string | undefined;\n getSubtitle: (price: Price) => JSX.Element | string | undefined;\n featureFlag: FeatureFlags;\n isOnlyOnePeriodAllowed?: boolean;\n}\n\nexport const PaymentPeriodList: VFC = memo(\n ({\n onChange,\n selectedDuration,\n prices,\n getLabel,\n getDescription,\n getSubtitle,\n featureFlag,\n isOnlyOnePeriodAllowed,\n }) => {\n const {\n res: [isFeatureSubscriptionType],\n isFeatureFlagsLoading,\n } = useFeatureFlags([featureFlag]);\n\n if (isFeatureFlagsLoading) {\n return ;\n }\n\n return isFeatureSubscriptionType ? (\n \n {prices.map((item) => (\n \n ))}\n \n ) : (\n \n \n {prices.map((item) => (\n \n ))}\n \n \n );\n }\n);\n","import React, { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { FormLabel } from '@src/components';\nimport { FeatureFlags } from '@src/constants';\nimport { useFeatureFlags } from '@src/hooks';\n\ninterface Props {\n featureFlag: FeatureFlags;\n marginBottom?: number;\n isOnlyOnePeriodAllowed?: boolean;\n}\n\nexport const PaymentPeriodsTitle = ({\n featureFlag,\n marginBottom,\n isOnlyOnePeriodAllowed,\n}: Props) => {\n const { t } = useTranslation();\n const {\n res: [isFeatureSubscriptionType],\n isFeatureFlagsLoading,\n } = useFeatureFlags([featureFlag]);\n\n if (isFeatureFlagsLoading) {\n return null;\n }\n\n return (\n \n {isFeatureSubscriptionType && !isOnlyOnePeriodAllowed\n ? t('COMMON:headers.chooseSubscriptionType')\n : t('COMMON:headers.paymentOfPeriod')}\n \n );\n};\n","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport { FeatureFlags } from '@src/constants';\nimport { useFeatureFlags } from '@src/hooks';\nimport { getDaysDuration } from '@src/utils';\n\ninterface Props {\n featureFlag: FeatureFlags;\n minDate: Date;\n maxDate: Date;\n}\n\nexport const PaymentPeriodHint = ({ featureFlag, minDate, maxDate }: Props) => {\n const { t } = useTranslation();\n const {\n res: [isFeatureSubscriptionType],\n isFeatureFlagsLoading,\n } = useFeatureFlags([featureFlag]);\n\n if (isFeatureFlagsLoading) {\n return null;\n }\n\n return (\n <>\n {isFeatureSubscriptionType && (\n \n {t('COMMON:hints.chooseAnyDateFromTheNextDays')}\n \n )}\n >\n );\n};\n","import { VFC, useMemo } from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport { FeatureFlags } from '@src/constants';\nimport { useFeatureFlags } from '@src/hooks';\nimport type { Price } from '@src/types';\nimport { getDiscount } from '@src/utils';\n\ntype Props = {\n prices: Price[];\n featureFlag: FeatureFlags;\n};\n\nexport const PromoCodeDiscount: VFC = ({ prices, featureFlag }) => {\n const { t } = useTranslation();\n const {\n res: [isFeatureDiscount],\n } = useFeatureFlags([featureFlag]);\n\n const discountPrice = prices.find((price) => price?.premiumAndDeltaPromo);\n\n const promoDiscount = useMemo(\n () =>\n discountPrice &&\n discountPrice.premiumAndDeltaPromo &&\n getDiscount(\n discountPrice.premiumAndDelta,\n discountPrice.premiumAndDeltaPromo\n ),\n [prices]\n );\n\n if (!discountPrice) return null;\n\n return (\n \n {isFeatureDiscount\n ? t('COMMON:hints.discountForFirstPeriodFeature')\n : t('COMMON:hints.discountForFirstPeriod')}\n \n );\n};\n","import { Button } from '@pulse-web-ui/button';\nimport { media, mixins, styled, typography } from '@pulse-web-ui/theme';\n\nexport const SupportBlockContent = styled.div`\n box-sizing: border-box;\n padding-top: 40px;\n\n ${media.desktop} {\n padding-top: 32px;\n }\n`;\n\nexport const SupportBlockTitle = styled.h3`\n ${typography.medium20};\n margin-bottom: 8px;\n\n ${media.desktop} {\n ${typography.medium24};\n }\n`;\n\nexport const SupportBlockSubTitle = styled.div`\n ${typography.regular16};\n line-height: 24px;\n color: ${(props) => props.theme.colors.text.secondary};\n margin-bottom: 24px;\n\n ${media.desktop} {\n ${typography.regular18};\n line-height: 26px;\n }\n`;\n\nexport const SupportButtonsWrapper = styled.div`\n ${mixins.flex({\n gap: 8,\n horizontal: false,\n })}\n\n ${media.desktop} {\n ${mixins.flex({ gap: 16 })}\n }\n`;\n\nexport const SupportButton = styled(Button)`\n height: 48px;\n padding: 11px 30px;\n`;\n","import { useTranslation } from 'react-i18next';\n\nimport { Telegram2, Vk2 } from '@pulse-web-ui/icons';\nimport { useTheme } from '@pulse-web-ui/theme';\nimport type { BaseThemeType } from '@pulse-web-ui/theme';\n\nimport {\n SupportBlockContent,\n SupportBlockSubTitle,\n SupportBlockTitle,\n SupportButton,\n SupportButtonsWrapper,\n} from './rgs-support.styles';\n\nexport const RGSSupportBlock = () => {\n const { t } = useTranslation();\n const theme = useTheme() as BaseThemeType;\n\n return (\n \n \n {t('BEST_TO_PAY:headers.socialNetworks')}\n \n \n {t('BEST_TO_PAY:hints.lifeHacks')}\n \n \n \n }\n onClick={() => window.open('https://t.me/sk_rgs_online', '_blank')}\n >\n {t('COMMON:labels.telegram')}\n \n }\n onClick={() => window.open('https://vk.com/rgs.online', '_blank')}\n >\n {t('COMMON:labels.vk')}\n \n \n \n );\n};\n","import { media, styled, typography } from '@pulse-web-ui/theme';\n\nexport const InsurancePriceCardContainer = styled.div`\n width: 100%;\n box-sizing: border-box;\n padding: 16px 24px;\n color: ${({ theme }) => theme.colors.text.primary};\n border-radius: ${({ theme }) => theme.common.radius12};\n background-color: ${({ theme }) => theme.colors.surface.background};\n`;\n\nexport const InsurancePriceCardTitle = styled.div`\n ${typography.regular16};\n line-height: 24px;\n margin-bottom: 2px;\n`;\n\nexport const OldCost = styled.span`\n ${typography.regular16}\n line-height: 24px;\n text-decoration: line-through;\n color: ${({ theme }) => theme.colors.text.secondary};\n margin-left: 8px;\n`;\n\nexport const Cost = styled.span`\n ${typography.medium20}\n\n ${media.desktop} {\n ${typography.medium24};\n }\n`;\n\nexport const CostPerPerson = styled.div`\n ${typography.regular16}\n color: ${({ theme }) => theme.colors.text.secondary};\n line-height: 24px;\n margin-top: 2px;\n`;\n","import { useTranslation } from 'react-i18next';\n\nimport { Spinner } from '@pulse-web-ui/spinner';\n\nimport { FRACTION_TWO, UnicodeEnum } from '@src/constants';\nimport { currencyRuLocaleWithoutFraction } from '@src/utils';\n\nimport {\n Cost,\n CostPerPerson,\n InsurancePriceCardContainer,\n InsurancePriceCardTitle,\n OldCost,\n} from './insurance-mite-price-card.styles';\n\ninterface Props {\n title: string;\n isLoading: boolean;\n premiumAndDelta?: number;\n premiumAndDeltaPromo?: number;\n costPerPerson?: string;\n}\n\nexport const InsuranceMitePriceCard = ({\n premiumAndDelta,\n premiumAndDeltaPromo,\n title,\n isLoading,\n costPerPerson,\n}: Props) => {\n const { t } = useTranslation();\n\n return (\n \n {title}\n {!premiumAndDelta || isLoading ? (\n \n ) : (\n <>\n {premiumAndDeltaPromo ? (\n <>\n \n {`${currencyRuLocaleWithoutFraction(\n premiumAndDeltaPromo,\n FRACTION_TWO\n )} ${UnicodeEnum.RUB}`}\n \n \n {currencyRuLocaleWithoutFraction(premiumAndDelta, FRACTION_TWO)}{' '}\n {UnicodeEnum.RUB}\n \n >\n ) : (\n \n {currencyRuLocaleWithoutFraction(premiumAndDelta, FRACTION_TWO)}{' '}\n {UnicodeEnum.RUB}\n \n )}\n {costPerPerson && (\n \n {t('MITE_FORM:labels.costPerPerson', {\n cost: currencyRuLocaleWithoutFraction(\n parseFloat(costPerPerson),\n FRACTION_TWO\n ),\n })}\n \n )}\n >\n )}\n \n );\n};\n","/* eslint-disable indent */\nimport { media, mixins, styled, typography } from '@pulse-web-ui/theme';\n\nimport { CustomButtonProps } from '@src/components/form-elements/form-elements.types';\n\nexport const StyledVisibleContainer = styled.div`\n display: flex;\n align-items: center;\n`;\n\nexport const StyledDeleteButton = styled.div`\n ${typography.regular18}\n color: ${({ theme }) => theme.colors.text.error};\n margin-right: 12px;\n cursor: pointer;\n`;\n\nexport const InsurancePersonFormHead = styled.div`\n ${mixins.flex({\n alignItems: 'center',\n justifyContent: 'space-between',\n wrap: false,\n gap: 12,\n })}\n min-height: 28px;\n margin-bottom: 16px;\n`;\n\nexport const InsurancePersonGroup = styled.div`\n width: 100%;\n`;\n\nexport const InsurancePersonFormContainer = styled.div`\n ${mixins.flex({\n horizontal: false,\n wrap: false,\n horizontalAlignment: 'flex-start',\n gap: 32,\n })}\n &:not(:last-child) {\n margin-bottom: 32px;\n }\n`;\n\nexport const InsurancePersonFormTitleBox = styled.div`\n ${mixins.flex({\n alignItems: 'center',\n wrap: false,\n gap: 8,\n })}\n`;\n\nexport const InsurancePersonFormTitle = styled.div`\n ${typography.medium18}\n color: ${({ theme }) => theme.colors.text.primary};\n`;\n\nexport const InsurancePersonFormSubTitle = styled.div`\n ${typography.regular14}\n color: ${({ theme }) => theme.colors.text.secondary};\n padding-top: 2px;\n`;\n\nexport const InsurancePersonFormNumber = styled.div<{\n choosedPolicy?: string;\n}>`\n ${typography.regular16}\n ${mixins.flex({\n alignItems: 'center',\n justifyContent: 'center',\n })}\n color: ${({ theme }) => theme.colors['on-accent'].primary};\n width: 24px;\n height: 24px;\n background: ${({ theme }) => theme.colors.surface.brand};\n border-radius: 50%;\n`;\n\nexport const InsurancePersonFormButton = styled.button`\n ${typography.regular14}\n background: ${({ active, theme }) =>\n active ? theme.colors.accent.action.clarified : 'none'};\n padding: 3px 7px;\n cursor: pointer;\n user-select: none;\n outline: none;\n border: 1px solid\n ${({ active, theme }) =>\n active ? theme.colors.accent.action.clarified : theme.colors.neutral[30]};\n border-radius: ${({ theme }) => theme.common.radius32};\n color: ${({ theme }) => theme.colors.text.primary};\n line-height: 20px;\n white-space: nowrap;\n`;\n\nexport const StyledButton = styled.div``;\n\nexport const InsurancePersonFormLabel = styled.div`\n ${typography.medium18}\n\n ${media.desktop} {\n ${typography.medium20}\n }\n`;\n","/* eslint-disable indent */\nimport { getAgeCategory } from '@src/utils/age-ratios-format';\n\nexport const getInsurancePersonTitle = (ageMin: number) => {\n const ageCategory = getAgeCategory();\n\n if (ageMin === 1) {\n return ageCategory.children;\n }\n\n return ageCategory.adults;\n};\n","/* eslint-disable indent */\nimport i18n from '@src/i18n/config';\n\nexport const getInsurancePersonSubTitle = (ageMin: number) => {\n const ageCategorySubTitle = {\n children: `1 – 17 ${i18n.t('COMMON:hints.years')}`,\n adults: `18 – 69 ${i18n.t('COMMON:hints.years')}`,\n elderly: `70 ${i18n.t('COMMON:hints.yearsAndOlder')}`,\n };\n\n switch (ageMin) {\n case 1:\n return ageCategorySubTitle.children;\n case 18:\n return ageCategorySubTitle.adults;\n case 70:\n return ageCategorySubTitle.elderly;\n default:\n break;\n }\n};\n","/* eslint-disable @typescript-eslint/no-empty-function */\n\n/* eslint-disable indent */\nimport { useCallback, useContext, useState } from 'react';\nimport { Controller, useFormContext } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\n\nimport { Button } from '@pulse-web-ui/button';\nimport { DaDataFio, DaDataSuggestion } from '@pulse-web-ui/dadata';\nimport { Datepicker } from '@pulse-web-ui/datepicker';\nimport { HelperText } from '@pulse-web-ui/helper-text';\nimport { Plus } from '@pulse-web-ui/icons';\nimport { useTheme } from '@pulse-web-ui/theme';\n\nimport { FilterParts, StyledDadataFioSuggestions } from '@src/components';\nimport { AdaptiveColumns, CalendarContainer } from '@src/components/container';\nimport { useHandlePressKey } from '@src/hooks';\nimport { useNsDetailsInsured } from '@src/pages/ns-form/hooks';\nimport { Store, WizardActionTypes } from '@src/store';\nimport { InsurancePersonsForm, KeyCode } from '@src/types';\nimport { addTestAttribute, calculateAge } from '@src/utils';\n\nimport {\n InsurancePersonFormButton,\n InsurancePersonFormContainer,\n InsurancePersonFormHead,\n InsurancePersonFormLabel,\n InsurancePersonFormNumber,\n InsurancePersonFormSubTitle,\n InsurancePersonFormTitle,\n InsurancePersonFormTitleBox,\n InsurancePersonGroup,\n StyledButton,\n StyledDeleteButton,\n StyledVisibleContainer,\n} from './insurance-person-form.styles';\nimport { InsurancePersonFormProps } from './insurance-person-form.types';\nimport {\n getDatepickerPeriod,\n getInsurancePersonSubTitle,\n getInsurancePersonTitle,\n isVisibleIsMeButton,\n} from './utils';\n\nexport const InsurancePersonForm = ({\n personsIndex,\n selectedIndex,\n isLastPerson,\n ageMin,\n handleSelectionMe,\n pressEnterNextStep,\n effectiveSince,\n lockedFields,\n fields,\n showFormTitle,\n showAddButton,\n showDeleteButton,\n handleAddField,\n handleDeleteField = () => {},\n formLabel,\n}: InsurancePersonFormProps) => {\n const { dispatch } = useContext(Store);\n const { t } = useTranslation();\n const [isFocusedMiddleName, setIsFocusedMiddleName] = useState(false);\n const theme: any = useTheme();\n\n const getDadataValue = (value: string | undefined) =>\n ({ value: value || '' } as DaDataSuggestion);\n\n const {\n formState: { errors },\n control,\n getValues,\n setValue,\n } = useFormContext();\n const personErrors = errors.persons?.[personsIndex];\n\n const { profileDataForForm } = useNsDetailsInsured();\n\n const isMe = getValues(`persons.${personsIndex}.isMe`);\n const userAge = profileDataForForm?.birthDate\n ? calculateAge(new Date(profileDataForForm.birthDate))\n : null;\n const isMeVisible = !ageMin\n ? true\n : userAge\n ? isVisibleIsMeButton(ageMin, userAge)\n : ageMin !== 1;\n\n const showButton =\n (isMeVisible && selectedIndex === -1) || selectedIndex === personsIndex;\n\n const AddButton = useCallback(() => {\n const lastElement = fields?.length - 1;\n\n if (lastElement === personsIndex) {\n return (\n \n }\n onClick={handleAddField}\n {...addTestAttribute(\n `insurancePerson.${personsIndex}.button.addMore`\n )}\n >\n {t('COMMON:buttons.addMore')}\n