From cd43f07e5e901df61aaf790e769e8ba3bc19e642 Mon Sep 17 00:00:00 2001 From: Oleksandra Nedashkivska Date: Sun, 18 Aug 2024 15:07:06 +0300 Subject: [PATCH 01/20] OV-1: + password input --- frontend/package.json | 1 + .../auth/components/common/components.ts | 1 + .../common/password-input/password-input.tsx | 40 +++++++++++++++++++ .../bundles/common/components/components.ts | 6 +++ .../theme/styles/components.styles.ts | 10 +++++ package-lock.json | 13 ++++++ 6 files changed, 71 insertions(+) create mode 100644 frontend/src/bundles/auth/components/common/components.ts create mode 100644 frontend/src/bundles/auth/components/common/password-input/password-input.tsx diff --git a/frontend/package.json b/frontend/package.json index 881769413..41ff12932 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "vite": "5.4.0" }, "dependencies": { + "@chakra-ui/icons": "2.1.1", "@chakra-ui/react": "2.8.2", "@emotion/react": "11.13.0", "@emotion/styled": "11.13.0", diff --git a/frontend/src/bundles/auth/components/common/components.ts b/frontend/src/bundles/auth/components/common/components.ts new file mode 100644 index 000000000..b5b4684f7 --- /dev/null +++ b/frontend/src/bundles/auth/components/common/components.ts @@ -0,0 +1 @@ +export { PasswordInput } from './password-input/password-input.js'; diff --git a/frontend/src/bundles/auth/components/common/password-input/password-input.tsx b/frontend/src/bundles/auth/components/common/password-input/password-input.tsx new file mode 100644 index 000000000..a87a0e65b --- /dev/null +++ b/frontend/src/bundles/auth/components/common/password-input/password-input.tsx @@ -0,0 +1,40 @@ +import { + IconButton, + Input, + InputGroup, + InputRightElement, + ViewIcon, + ViewOffIcon, +} from '~/bundles/common/components/components.js'; +import { useCallback, useState } from '~/bundles/common/hooks/hooks.js'; + +const PasswordInput: React.FC = () => { + const [showPassword, setShowPassword] = useState(false); + + const handlePasswordIconClick = useCallback((): void => { + setShowPassword((previousShowPassword) => !previousShowPassword); + }, []); + + return ( + + + + : } + onClick={handlePasswordIconClick} + variant="ghostIcon" + /> + + + ); +}; + +export { PasswordInput }; diff --git a/frontend/src/bundles/common/components/components.ts b/frontend/src/bundles/common/components/components.ts index 71c774689..9da09a971 100644 --- a/frontend/src/bundles/common/components/components.ts +++ b/frontend/src/bundles/common/components/components.ts @@ -4,12 +4,18 @@ export { Link } from './link/link.js'; export { Loader } from './loader/loader.js'; export { Overlay } from './overlay/overlay.js'; export { RouterProvider } from './router-provider/router-provider.js'; +export { ViewIcon, ViewOffIcon } from '@chakra-ui/icons'; export { Box, + Center, Circle, ChakraProvider as ComponentsProvider, Flex, Heading, + IconButton, + InputGroup, + InputRightElement, + SimpleGrid, Text, VStack, } from '@chakra-ui/react'; diff --git a/frontend/src/framework/theme/styles/components.styles.ts b/frontend/src/framework/theme/styles/components.styles.ts index 417d40ef9..cb0d05804 100644 --- a/frontend/src/framework/theme/styles/components.styles.ts +++ b/frontend/src/framework/theme/styles/components.styles.ts @@ -78,6 +78,16 @@ const components = { }, }, }, + Button: { + variants: { + ghostIcon: { + color: 'white', + _hover: { + color: 'brand.secondary.300', + }, + }, + }, + }, }; export { components }; diff --git a/package-lock.json b/package-lock.json index 711edfde0..c679dfd41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,6 +71,7 @@ "frontend": { "version": "1.0.0", "dependencies": { + "@chakra-ui/icons": "2.1.1", "@chakra-ui/react": "2.8.2", "@emotion/react": "11.13.0", "@emotion/styled": "11.13.0", @@ -803,6 +804,18 @@ "react": ">=18" } }, + "node_modules/@chakra-ui/icons": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.1.1.tgz", + "integrity": "sha512-3p30hdo4LlRZTT5CwoAJq3G9fHI0wDc0pBaMHj4SUn0yomO+RcDRlzhdXqdr5cVnzax44sqXJVnf3oQG0eI+4g==", + "dependencies": { + "@chakra-ui/icon": "3.2.0" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, "node_modules/@chakra-ui/image": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-2.1.0.tgz", From aaa8b5d9cfc54bf8b13a847d8b0b736490c2571d Mon Sep 17 00:00:00 2001 From: Oleksandra Nedashkivska Date: Sun, 18 Aug 2024 15:24:26 +0300 Subject: [PATCH 02/20] OV-1: + signin validation schema --- .../sign-in-form/constants/constants.ts | 8 +++++ frontend/src/bundles/users/types/types.ts | 1 + frontend/src/bundles/users/users.ts | 6 +++- .../validation-schemas/validation-schemas.ts | 2 +- .../enums/user-validation-message.enum.ts | 3 ++ .../users/enums/user-validation-rule.enum.ts | 5 ++- shared/src/bundles/users/types/types.ts | 1 + .../types/user-sign-in-request-dto.type.ts | 6 ++++ shared/src/bundles/users/users.ts | 6 +++- .../user-sign-in.validation-schema.ts | 36 +++++++++++++++++++ .../validation-schemas/validation-schemas.ts | 1 + shared/src/index.ts | 2 ++ 12 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 frontend/src/bundles/auth/components/sign-in-form/constants/constants.ts create mode 100644 shared/src/bundles/users/types/user-sign-in-request-dto.type.ts create mode 100644 shared/src/bundles/users/validation-schemas/user-sign-in.validation-schema.ts diff --git a/frontend/src/bundles/auth/components/sign-in-form/constants/constants.ts b/frontend/src/bundles/auth/components/sign-in-form/constants/constants.ts new file mode 100644 index 000000000..3e3264e83 --- /dev/null +++ b/frontend/src/bundles/auth/components/sign-in-form/constants/constants.ts @@ -0,0 +1,8 @@ +import { type UserSignInRequestDto } from '~/bundles/users/users.js'; + +const DEFAULT_SIGN_IN_PAYLOAD: UserSignInRequestDto = { + email: '', + password: '', +}; + +export { DEFAULT_SIGN_IN_PAYLOAD }; diff --git a/frontend/src/bundles/users/types/types.ts b/frontend/src/bundles/users/types/types.ts index fb8e20c76..0a38e94bf 100644 --- a/frontend/src/bundles/users/types/types.ts +++ b/frontend/src/bundles/users/types/types.ts @@ -1,6 +1,7 @@ export { type UserGetAllItemResponseDto, type UserGetAllResponseDto, + type UserSignInRequestDto, type UserSignUpRequestDto, type UserSignUpResponseDto, } from 'shared'; diff --git a/frontend/src/bundles/users/users.ts b/frontend/src/bundles/users/users.ts index 443083e1c..59ffe28cb 100644 --- a/frontend/src/bundles/users/users.ts +++ b/frontend/src/bundles/users/users.ts @@ -14,7 +14,11 @@ export { userApi }; export { type UserGetAllItemResponseDto, type UserGetAllResponseDto, + type UserSignInRequestDto, type UserSignUpRequestDto, type UserSignUpResponseDto, } from './types/types.js'; -export { userSignUpValidationSchema } from './validation-schemas/validation-schemas.js'; +export { + userSignInValidationSchema, + userSignUpValidationSchema, +} from './validation-schemas/validation-schemas.js'; diff --git a/frontend/src/bundles/users/validation-schemas/validation-schemas.ts b/frontend/src/bundles/users/validation-schemas/validation-schemas.ts index 7bc9a09c5..5952fe0cf 100644 --- a/frontend/src/bundles/users/validation-schemas/validation-schemas.ts +++ b/frontend/src/bundles/users/validation-schemas/validation-schemas.ts @@ -1 +1 @@ -export { userSignUpValidationSchema } from 'shared'; +export { userSignInValidationSchema, userSignUpValidationSchema } from 'shared'; diff --git a/shared/src/bundles/users/enums/user-validation-message.enum.ts b/shared/src/bundles/users/enums/user-validation-message.enum.ts index b28063d96..f369a8c1a 100644 --- a/shared/src/bundles/users/enums/user-validation-message.enum.ts +++ b/shared/src/bundles/users/enums/user-validation-message.enum.ts @@ -1,6 +1,9 @@ const UserValidationMessage = { EMAIL_REQUIRE: 'Email is required', EMAIL_WRONG: 'Email is wrong', + FIELD_REQUIRE: 'Please fill out this field', + EMAIL_INVALID: 'Please enter a valid email', + PASSWORD_LENGTH: 'Password must have from 6 to 12 characters', } as const; export { UserValidationMessage }; diff --git a/shared/src/bundles/users/enums/user-validation-rule.enum.ts b/shared/src/bundles/users/enums/user-validation-rule.enum.ts index 36ca9c2e2..eb7d606aa 100644 --- a/shared/src/bundles/users/enums/user-validation-rule.enum.ts +++ b/shared/src/bundles/users/enums/user-validation-rule.enum.ts @@ -1,5 +1,8 @@ const UserValidationRule = { - EMAIL_MINIMUM_LENGTH: 1, + EMAIL_MINIMUM_LENGTH: 6, + EMAIL_MAXIMUM_LENGTH: 320, + PASSWORD_MINIMUM_LENGTH: 6, + PASSWORD_MAXIMUM_LENGTH: 12, } as const; export { UserValidationRule }; diff --git a/shared/src/bundles/users/types/types.ts b/shared/src/bundles/users/types/types.ts index 7564f70b2..f6fd8caa2 100644 --- a/shared/src/bundles/users/types/types.ts +++ b/shared/src/bundles/users/types/types.ts @@ -1,4 +1,5 @@ export { type UserGetAllItemResponseDto } from './user-get-all-item-response-dto.type.js'; export { type UserGetAllResponseDto } from './user-get-all-response-dto.type.js'; +export { type UserSignInRequestDto } from './user-sign-in-request-dto.type.js'; export { type UserSignUpRequestDto } from './user-sign-up-request-dto.type.js'; export { type UserSignUpResponseDto } from './user-sign-up-response-dto.type.js'; diff --git a/shared/src/bundles/users/types/user-sign-in-request-dto.type.ts b/shared/src/bundles/users/types/user-sign-in-request-dto.type.ts new file mode 100644 index 000000000..8098c64cf --- /dev/null +++ b/shared/src/bundles/users/types/user-sign-in-request-dto.type.ts @@ -0,0 +1,6 @@ +type UserSignInRequestDto = { + email: string; + password: string; +}; + +export { type UserSignInRequestDto }; diff --git a/shared/src/bundles/users/users.ts b/shared/src/bundles/users/users.ts index e65858985..162c57439 100644 --- a/shared/src/bundles/users/users.ts +++ b/shared/src/bundles/users/users.ts @@ -2,7 +2,11 @@ export { UsersApiPath, UserValidationMessage } from './enums/enums.js'; export { type UserGetAllItemResponseDto, type UserGetAllResponseDto, + type UserSignInRequestDto, type UserSignUpRequestDto, type UserSignUpResponseDto, } from './types/types.js'; -export { userSignUp as userSignUpValidationSchema } from './validation-schemas/validation-schemas.js'; +export { + userSignIn as userSignInValidationSchema, + userSignUp as userSignUpValidationSchema, +} from './validation-schemas/validation-schemas.js'; diff --git a/shared/src/bundles/users/validation-schemas/user-sign-in.validation-schema.ts b/shared/src/bundles/users/validation-schemas/user-sign-in.validation-schema.ts new file mode 100644 index 000000000..100cb3dad --- /dev/null +++ b/shared/src/bundles/users/validation-schemas/user-sign-in.validation-schema.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; + +import { UserValidationMessage, UserValidationRule } from '../enums/enums.js'; + +type UserSignInRequestValidationDto = { + email: z.ZodString; + password: z.ZodString; +}; + +const userSignIn = z + .object({ + email: z + .string({ required_error: UserValidationMessage.FIELD_REQUIRE }) + .trim() + .min(UserValidationRule.EMAIL_MINIMUM_LENGTH, { + message: UserValidationMessage.EMAIL_INVALID, + }) + .max(UserValidationRule.EMAIL_MAXIMUM_LENGTH, { + message: UserValidationMessage.EMAIL_INVALID, + }) + .email({ + message: UserValidationMessage.EMAIL_INVALID, + }), + password: z + .string({ required_error: UserValidationMessage.FIELD_REQUIRE }) + .trim() + .min(UserValidationRule.PASSWORD_MINIMUM_LENGTH, { + message: UserValidationMessage.PASSWORD_LENGTH, + }) + .max(UserValidationRule.PASSWORD_MAXIMUM_LENGTH, { + message: UserValidationMessage.PASSWORD_LENGTH, + }), + }) + .required(); + +export { userSignIn }; diff --git a/shared/src/bundles/users/validation-schemas/validation-schemas.ts b/shared/src/bundles/users/validation-schemas/validation-schemas.ts index cb1c2ad60..f6c85f13c 100644 --- a/shared/src/bundles/users/validation-schemas/validation-schemas.ts +++ b/shared/src/bundles/users/validation-schemas/validation-schemas.ts @@ -1 +1,2 @@ +export { userSignIn } from './user-sign-in.validation-schema.js'; export { userSignUp } from './user-sign-up.validation-schema.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index df887038b..a0f2d2c57 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -2,9 +2,11 @@ export { AuthApiPath } from './bundles/auth/auth.js'; export { type UserGetAllItemResponseDto, type UserGetAllResponseDto, + type UserSignInRequestDto, type UserSignUpRequestDto, type UserSignUpResponseDto, UsersApiPath, + userSignInValidationSchema, userSignUpValidationSchema, } from './bundles/users/users.js'; export { From 9ecc8efbd9c75db7ce9c59e4049b9e2e4c5a593f Mon Sep 17 00:00:00 2001 From: Oleksandra Nedashkivska Date: Sun, 18 Aug 2024 15:26:32 +0300 Subject: [PATCH 03/20] OV-1: + button customization --- .../src/framework/theme/styles/components.styles.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frontend/src/framework/theme/styles/components.styles.ts b/frontend/src/framework/theme/styles/components.styles.ts index cb0d05804..a64bd5171 100644 --- a/frontend/src/framework/theme/styles/components.styles.ts +++ b/frontend/src/framework/theme/styles/components.styles.ts @@ -80,6 +80,16 @@ const components = { }, Button: { variants: { + solid: { + color: 'white', + bgColor: 'brand.secondary.300', + _hover: { + bg: 'brand.secondary.600', + _disabled: { + bg: 'brand.secondary.600', + }, + }, + }, ghostIcon: { color: 'white', _hover: { From e7e9112f88ae169148cb9272a21bcedb04f9c680 Mon Sep 17 00:00:00 2001 From: Oleksandra Nedashkivska Date: Sun, 18 Aug 2024 15:51:16 +0300 Subject: [PATCH 04/20] OV-1: * signin form --- .../common/password-input/password-input.tsx | 10 ++- .../components/sign-in-form/sign-in-form.tsx | 64 ++++++++++++++++--- .../common/components/button/button.tsx | 11 +++- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/frontend/src/bundles/auth/components/common/password-input/password-input.tsx b/frontend/src/bundles/auth/components/common/password-input/password-input.tsx index a87a0e65b..2a2252066 100644 --- a/frontend/src/bundles/auth/components/common/password-input/password-input.tsx +++ b/frontend/src/bundles/auth/components/common/password-input/password-input.tsx @@ -8,7 +8,11 @@ import { } from '~/bundles/common/components/components.js'; import { useCallback, useState } from '~/bundles/common/hooks/hooks.js'; -const PasswordInput: React.FC = () => { +type Properties = { + hasError: boolean; +}; + +const PasswordInput: React.FC = ({ hasError }) => { const [showPassword, setShowPassword] = useState(false); const handlePasswordIconClick = useCallback((): void => { @@ -16,14 +20,14 @@ const PasswordInput: React.FC = () => { }, []); return ( - + - + void; + onSubmit: (payload: UserSignInRequestDto) => void; }; -const SignInForm: React.FC = () => ( - <> - Sign In +const SignInForm: React.FC = ({ onSubmit }) => { + const form = useAppForm({ + initialValues: DEFAULT_SIGN_IN_PAYLOAD, + validationSchema: userSignInValidationSchema, + onSubmit, + }); + + const { handleSubmit, errors } = form; -
-