diff --git a/src/app/router/AppRouter/ui/AppRouter.tsx b/src/app/router/AppRouter/ui/AppRouter.tsx index 41458535..8bd5090b 100644 --- a/src/app/router/AppRouter/ui/AppRouter.tsx +++ b/src/app/router/AppRouter/ui/AppRouter.tsx @@ -6,6 +6,7 @@ import CartPage from '@/pages/CartPage/CartPage' import { CategoryPage } from '@/pages/CategoryPage/CategoryPage' import ComparePage from '@/pages/ComparePage/ComparePage' import ContactsPage from '@/pages/ContactsPage/ContactsPage' +import CreateAccountPage from '@/pages/CreateAccountPage/CreateAccountPage' import DeliveryPage from '@/pages/DeliveryPage/DeliveryPage' import ErrorPage from '@/pages/ErrorPage/ErrorPage' import { FavoritesPage } from '@/pages/FavoritesPage/FavoritesPage' @@ -118,6 +119,10 @@ export const AppRouter = createBrowserRouter([ { path: Routes.CONTACTS, element: + }, + { + path: Routes.REGISTRATION, + element: } /* { path: Routes.CERTIFICATE, diff --git a/src/pages/CreateAccountPage/CreateAccountPage.module.scss b/src/pages/CreateAccountPage/CreateAccountPage.module.scss new file mode 100644 index 00000000..4e8d74f4 --- /dev/null +++ b/src/pages/CreateAccountPage/CreateAccountPage.module.scss @@ -0,0 +1,40 @@ +@use '@/shared/styles/utils/mixins' as media; + +.container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 65px 0; +} + +.wrapper { + display: flex; + align-items: center; + justify-content:space-between; + width: 45%; + margin-bottom: 20px; + @include media.respond-to('large') { + width: 80%; + } + @include media.respond-to('middle') { + width: 94%; + } +} + +.auth { + display: flex; + align-items: center; + justify-content: center; + column-gap: 10px; +} + +.button { + padding: 4px 14px; +} + +.paragraph { + @include media.respond-to('middle') { + display: none; + } +} \ No newline at end of file diff --git a/src/pages/CreateAccountPage/CreateAccountPage.tsx b/src/pages/CreateAccountPage/CreateAccountPage.tsx new file mode 100644 index 00000000..a2e397d0 --- /dev/null +++ b/src/pages/CreateAccountPage/CreateAccountPage.tsx @@ -0,0 +1,41 @@ +import { useNavigate } from 'react-router' + +import { Routes } from '@/shared/config/routerConfig/routes' +import { Button, ButtonDesign, ButtonSize, ButtonTheme } from '@/shared/ui/Button/Button' +import Heading from '@/shared/ui/Heading/Heading' +import Paragraph from '@/shared/ui/Paragraph/Paragraph' +import CreateAccountForm from '@/widgets/CreateAccount/ui/CreateAccountForm' + +import styles from './CreateAccountPage.module.scss' + +/** + * Страница регистрации + */ + +const CreateAccountPage = () => { + const navigate = useNavigate() + const handleRedirect = () => { + navigate(`${Routes.LOGIN}`) + } + return ( +
+
+ Регистрация +
+ У вас уже есть аккаунт? + +
+
+ +
+ ) +} +export default CreateAccountPage diff --git a/src/shared/config/routerConfig/routes.ts b/src/shared/config/routerConfig/routes.ts index 21928c16..e52f482d 100644 --- a/src/shared/config/routerConfig/routes.ts +++ b/src/shared/config/routerConfig/routes.ts @@ -21,5 +21,6 @@ export enum Routes { TERMS = '/terms', VOUCHERS = '/vouchers', PRODUCT = '/product', - HELP = '/help' + HELP = '/help', + REGISTRATION = '/registration' } diff --git a/src/widgets/CreateAccount/model/types.ts b/src/widgets/CreateAccount/model/types.ts new file mode 100644 index 00000000..b5c92151 --- /dev/null +++ b/src/widgets/CreateAccount/model/types.ts @@ -0,0 +1,15 @@ +export interface ICreateAccountForm { + name: string + surname: string + email: string + tel: string + country: string + region: string + index: string + model: string + city: string + password: string + passwordConfirmation: string + subscription: string + agreement: boolean +} diff --git a/src/widgets/CreateAccount/model/validation.ts b/src/widgets/CreateAccount/model/validation.ts new file mode 100644 index 00000000..5c7ff967 --- /dev/null +++ b/src/widgets/CreateAccount/model/validation.ts @@ -0,0 +1,29 @@ +import * as Yup from 'yup' + +export const validationSchema = Yup.object().shape({ + name: Yup.string() + .required('Введите имя') + .min(2, 'Минимальная длина имени 6 символов') + .max(64, 'Максимальная длина имени 64 символа'), + surname: Yup.string() + .required('Введите фамилию') + .min(1, 'Минимальная длина фамилии 1 символ') + .max(64, 'Максимальная длина фамилии 64 символа'), + email: Yup.string() + .required('Введите электронную почту') + .email('Укажите корректный адрес электронной почты'), + tel: Yup.string() + .required('Введите номер телефона') + .matches(/^\+7\d{10}$/, 'Номер телефона должен быть в формате +7XXXXXXXXXX (X - цифра)'), + country: Yup.string(), + region: Yup.string(), + index: Yup.number() + .min(6, 'Количество символов должно быть 6') + .max(6, 'Количество символов должно быть 6') + .typeError('Индекс указывается только цифрами'), + city: Yup.string(), + password: Yup.string().required('Введите пароль'), + passwordConfirmation: Yup.string() + .required('Введите подтверждение пароля') + .oneOf([Yup.ref('password')], 'Пароли должны совпадать') +}) diff --git a/src/widgets/CreateAccount/ui/CreateAccountForm.module.scss b/src/widgets/CreateAccount/ui/CreateAccountForm.module.scss new file mode 100644 index 00000000..30bdcaff --- /dev/null +++ b/src/widgets/CreateAccount/ui/CreateAccountForm.module.scss @@ -0,0 +1,129 @@ +@use '@/shared/styles/utils/variables' as var; +@use '@/shared/styles/utils/mixins' as media; + +.form { + display: flex; + flex-direction: column; + justify-content: center; + width: 45%; + border-radius: 10px; + background-color: var.$white; + margin: 0 0 20px; + padding: 25px 30px 20px; + + @include media.respond-to('large') { + width: 80%; + } + @include media.respond-to('middle') { + width: 94%; + } + + &__paragraph { + margin: 0 0 10px; + padding: 0; + } + + &__title { + margin-bottom: 20px; + + + &_second { + margin-top: 20px; + } + } + + &__label { + margin: 0 0 20px; + padding: 0; + + &_notRequired[data-no-star]::before { + content: ''; + } + + &_agreement { + margin-bottom: 0; + line-height: 20px; + } + + } + + &__label::before { + content: '*'; + color: var.$promo-color; + margin-right: 3px; + + &_notRequired[data-no-star]::before { + content: ''; + } + } + + &__list { + display: flex; + column-gap: 30px; + } + + &__input { + background-color: var.$body-bg; + border: 2px solid var.$border-color; + border-radius: 10px; + margin: 5px 0 0; + padding: 10px 16px; + + &_extra { + width: 100%; + } + } + + &__input:focus { + border: 2px solid var.$theme-primary-color; + transition: 0.7s; + } + + &__error { + position: absolute; + top: 72px; + left: 17px; + font-size: 12px; + font-weight: 100; + color: var.$promo-color; + } + + &__radio { + width: 20px; + margin-top: 5px; + } + + &__checkbox { + margin: 0; + } + + &__buttons { + display: flex; + gap: 20px; + } + + &__agreement { + display: flex; + align-items: flex-start; + column-gap: 10px; + border-top: 1px solid var.$border-color; + padding: 20px 0; + margin-bottom: 15px; + margin-top: 20px; + } + + &__span { + display: inline; + padding: 0; + border: 0; + color: var.$link-color; + font-size: 14px; + + + &:hover { + color: var.$link-color; + transition: opacity 0.25s, color 0.25s; + opacity: 0.7; + } + } +} \ No newline at end of file diff --git a/src/widgets/CreateAccount/ui/CreateAccountForm.stories.tsx b/src/widgets/CreateAccount/ui/CreateAccountForm.stories.tsx new file mode 100644 index 00000000..6acb3607 --- /dev/null +++ b/src/widgets/CreateAccount/ui/CreateAccountForm.stories.tsx @@ -0,0 +1,17 @@ +import { Meta, StoryObj } from '@storybook/react' + +import CreateAccountForm from './CreateAccountForm' + +const meta = { + title: 'widgets/CreateAccountForm', + component: CreateAccountForm, + parameters: { + layout: 'centered' + }, + tags: ['autodocs'] +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Default: Story = {} diff --git a/src/widgets/CreateAccount/ui/CreateAccountForm.tsx b/src/widgets/CreateAccount/ui/CreateAccountForm.tsx new file mode 100644 index 00000000..1cd948c3 --- /dev/null +++ b/src/widgets/CreateAccount/ui/CreateAccountForm.tsx @@ -0,0 +1,270 @@ +import classNames from 'classnames' +import { ErrorMessage, Field, Form, Formik } from 'formik' + +import { Button, ButtonDesign, ButtonSize, ButtonTheme } from '@/shared/ui/Button/Button' +import Checkbox from '@/shared/ui/Checkbox/Checkbox' +import Heading, { HeadingType } from '@/shared/ui/Heading/Heading' +import { Input } from '@/shared/ui/Input/Input' +import Label from '@/shared/ui/Label/Label' + +import { ICreateAccountForm } from '../model/types' +import { validationSchema } from '../model/validation' + +import styles from './CreateAccountForm.module.scss' + +const initialValues: ICreateAccountForm = { + name: '', + surname: '', + email: '', + tel: '', + country: '', + region: '', + index: '', + model: '', + city: '', + password: '', + passwordConfirmation: '', + subscription: String('Нет'), + agreement: false +} + +const subscription = [ + { label: 'Да', value: 'Да' }, + { label: 'Нет', value: 'Нет' } +] + +const countries = ['---Выберите---', 'Белоруссия (Беларусь)', 'Российская Федерация'] +/** + * Страница регистрации + */ + +const CreateAccountForm = () => { + const handleRedirect = () => { + //TODO + } + const openModal = () => { + //TODO + } + return ( + { + setSubmitting(false) + resetForm() + }}> + {({ isSubmitting }) => ( +
+ + Основные данные + + + + + + + + + + + + Ваш пароль + + + + + Рассылка новостей + + + +
+ + +
+ + +
+ )} +
+ ) +} +export default CreateAccountForm diff --git a/src/widgets/FormReturn/ui/FormReturn.module.scss b/src/widgets/FormReturn/ui/FormReturn.module.scss index 33ef8edb..8eb31bbd 100644 --- a/src/widgets/FormReturn/ui/FormReturn.module.scss +++ b/src/widgets/FormReturn/ui/FormReturn.module.scss @@ -16,7 +16,7 @@ } &__title { - margin-bottom: 20px; + margin-bottom: 20px; &_second { margin-top: 20px;