Advertisement
Valer4ik

Untitled

Jan 10th, 2024
900
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // TODO: слишком переусложнил компонент изза меняющихся требований, не мешало бы розбить на отдельные компоненты
  2.  
  3. import React from 'react';
  4. import styled from 'styled-components';
  5. import { Form } from 'react-final-form';
  6.  
  7. import { useTranslation } from 'next-i18next';
  8. import { Typography } from '../Typography';
  9. import { FormField, FormFieldTypeEnum } from '../FormField';
  10. import { Button } from '../Button';
  11. import { FormFields } from './types';
  12. import { useValidationSchema } from '../../hooks/useValidationSchema';
  13. import { getValidationSchema } from './validation';
  14. import CardIcon from '../../icons/legacy/card-number.svg';
  15. import { IInputProps } from '../Input/types';
  16. import { getIsMoscowRegion } from '../../api/tariffs/helpers';
  17. import { WriteRemoteCheckboxField } from '../WriteRemoteCheckboxField';
  18. import { IRegion } from '../../api/region';
  19.  
  20. interface IDefaultFields {
  21.     [FormFields.phone]: string;
  22.     [FormFields.email]: string;
  23. }
  24.  
  25. export type IConfirmOrderModalFormValues<
  26.     WithCard = false,
  27.     WithDepositAmount = false,
  28.     WithWriteRemote = false,
  29. > = IDefaultFields &
  30.     (WithCard extends true
  31.         ? {
  32.               [FormFields.cardNumber]: string;
  33.           }
  34.         : {}) &
  35.     (WithDepositAmount extends true
  36.         ? {
  37.               [FormFields.depositAmount]: string;
  38.           }
  39.         : {}) &
  40.     (WithWriteRemote extends true
  41.         ? {
  42.               [FormFields.writeRemote]: boolean | undefined;
  43.           }
  44.         : {});
  45.  
  46. type ICommonProps<
  47.     WithCard extends boolean = false,
  48.     WithDepositAmount extends boolean = false,
  49.     WithWriteRemote extends boolean = false,
  50. > = {
  51.     onSubmit: (values: IConfirmOrderModalFormValues<WithCard, WithDepositAmount, WithWriteRemote>) => void;
  52.     withCardNumber?: boolean;
  53.     withDepositAmount?: boolean;
  54.     depositAmountRules?: {
  55.         min: number;
  56.         max: number;
  57.         description: string;
  58.     };
  59.     isLoading?: boolean;
  60. };
  61.  
  62. type IConfirmPersonalOrderProps<
  63.     WithCard extends boolean = false,
  64.     WithDepositAmount extends boolean = false,
  65.     WithWriteRemote extends boolean = false,
  66. > = WithWriteRemote extends true
  67.     ? { region: IRegion } & ICommonProps<WithCard, WithDepositAmount, WithWriteRemote>
  68.     : { region?: undefined } & ICommonProps<WithCard, WithDepositAmount, WithWriteRemote>;
  69.  
  70. export const ConfirmPersonalOrder = <
  71.     WithCard extends boolean = false,
  72.     WithDepositAmount extends boolean = false,
  73.     WithWriteRemote extends boolean = false,
  74. >({
  75.     region,
  76.     onSubmit,
  77.     isLoading = false,
  78.     depositAmountRules,
  79.     withDepositAmount = false,
  80.     withCardNumber = false,
  81. }: IConfirmPersonalOrderProps<WithCard, WithDepositAmount, WithWriteRemote>) => {
  82.     const { t } = useTranslation();
  83.     const validation = useValidationSchema(
  84.         getValidationSchema({ withCardNumber, withDepositAmount, depositAmountRules }),
  85.     );
  86.  
  87.     return (
  88.         <Wrapper>
  89.             <Caption>{t('Укажите контактные данные для оформления заказа и оплаты билета')}</Caption>
  90.             <Form<IConfirmOrderModalFormValues<WithCard, WithDepositAmount, WithWriteRemote>>
  91.                 // @ts-ignore
  92.                 onSubmit={onSubmit}
  93.                 validate={validation}
  94.             >
  95.                 {({ handleSubmit, valid }) => (
  96.                     <FormInner onSubmit={handleSubmit}>
  97.                         <FormInputs>
  98.                             {withCardNumber && (
  99.                                 <FormField
  100.                                     key="card-input"
  101.                                     name={FormFields.cardNumber}
  102.                                     label={t('Номер карты Тройка')}
  103.                                     icon={<CardIcon />}
  104.                                     placeholder="0000 000 000"
  105.                                     mask="9999 999 999"
  106.                                 />
  107.                             )}
  108.                             {withDepositAmount && (
  109.                                 <div>
  110.                                     <FormField<IInputProps>
  111.                                         name={FormFields.depositAmount}
  112.                                         label={t('Сумма')}
  113.                                         placeholder="0.00 ₽"
  114.                                         step="0.01"
  115.                                         type="number"
  116.                                     />
  117.                                     {depositAmountRules?.description && (
  118.                                         <FieldCaption>{depositAmountRules.description}</FieldCaption>
  119.                                     )}
  120.                                 </div>
  121.                             )}
  122.                             <FormField
  123.                                 fieldType={FormFieldTypeEnum.phone}
  124.                                 name={FormFields.phone}
  125.                                 label={t('Номер телефона')}
  126.                                 placeholder="+7 ___ ___ __ __"
  127.                             />
  128.                             <FormField
  129.                                 name={FormFields.email}
  130.                                 label={t('E-mail')}
  131.                                 placeholder={t('Укажите e-mail')}
  132.                                 type="email"
  133.                             />
  134.                             {region && getIsMoscowRegion(region) && (
  135.                                 <WriteRemoteCheckboxField name={FormFields.writeRemote} />
  136.                             )}
  137.                         </FormInputs>
  138.                         <SmallText>
  139.                             {t('Оплачивая заказ, вы соглашаетесь с')}{' '}
  140.                             <a href="/user-agreement" target="_blank">
  141.                                 {t('условиями сервиса')}
  142.                             </a>{' '}
  143.                             {t('и')}{' '}
  144.                             <a href="/user-agreement" target="_blank">
  145.                                 {t('политикой обработки персональных данных')}
  146.                             </a>
  147.                             {t('. После оплаты заказа, не забудьте записать билет на вашу Тройку.')}
  148.                         </SmallText>
  149.                         <SubmitButton disabled={!valid || isLoading} htmlType="submit">
  150.                             {t('Перейти к оплате')}
  151.                         </SubmitButton>
  152.                     </FormInner>
  153.                 )}
  154.             </Form>
  155.         </Wrapper>
  156.     );
  157. };
  158.  
  159. const Wrapper = styled.div`
  160.     display: flex;
  161.     flex-direction: column;
  162.     flex: 1;
  163. `;
  164.  
  165. const Caption = styled(Typography).attrs({ variant: 'regular16' })`
  166.     color: ${({ theme }) => theme.colors.black()};
  167.     margin-bottom: 24px;
  168. `;
  169.  
  170. const SmallText = styled(Typography).attrs({ variant: 'regular12' })`
  171.     color: ${({ theme }) => theme.colors.black()};
  172.     margin-top: 24px;
  173.     margin-bottom: 10px;
  174.  
  175.     a {
  176.         text-decoration: underline;
  177.     }
  178. `;
  179.  
  180. const FormInner = styled.form`
  181.     display: flex;
  182.     flex-direction: column;
  183.     flex: 1;
  184. `;
  185.  
  186. const FormInputs = styled.div`
  187.     display: grid;
  188.     grid-auto-flow: row;
  189.     grid-gap: 24px;
  190. `;
  191.  
  192. const SubmitButton = styled(Button)`
  193.     margin: 36px auto 0;
  194.  
  195.     @media ${({ theme }) => theme.breakpoints.sm} {
  196.         width: 100%;
  197.         margin-top: auto;
  198.     }
  199. `;
  200.  
  201. const FieldCaption = styled(Typography).attrs({ variant: 'regular12', color: 'gray' })`
  202.     margin-top: 8px;
  203.     margin-left: 4px;
  204. `;
  205.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement