From 5fe0d635becc23e832c64d0d21496e82ddd8f4b9 Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Sun, 18 Aug 2024 12:18:43 -0400 Subject: [PATCH 01/21] OV-4: + name and repeatPassword properties for sign-up form --- .../components/sign-up-form/constants/constants.ts | 2 ++ .../auth/components/sign-up-form/sign-up-form.tsx | 12 ++++++++++++ .../users/types/user-sign-up-request-dto.type.ts | 2 ++ .../user-sign-up.validation-schema.ts | 4 ++++ 4 files changed, 20 insertions(+) diff --git a/frontend/src/bundles/auth/components/sign-up-form/constants/constants.ts b/frontend/src/bundles/auth/components/sign-up-form/constants/constants.ts index 219f8854a..49ecd1635 100644 --- a/frontend/src/bundles/auth/components/sign-up-form/constants/constants.ts +++ b/frontend/src/bundles/auth/components/sign-up-form/constants/constants.ts @@ -1,8 +1,10 @@ import { type UserSignUpRequestDto } from '~/bundles/users/users.js'; const DEFAULT_SIGN_UP_PAYLOAD: UserSignUpRequestDto = { + name: '', email: '', password: '', + repeatPassword: '', }; export { DEFAULT_SIGN_UP_PAYLOAD }; diff --git a/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx b/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx index 82d4620d0..90b956282 100644 --- a/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx +++ b/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx @@ -34,6 +34,12 @@ const SignUpForm: React.FC = ({ onSubmit }) => {
+ = ({ onSubmit }) => { placeholder="Enter your password" name="password" /> + + + + ); +}; + +export { PasswordInput }; From e94407cf957a6c944f23a49fe78b96a1e49db8bd Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Sun, 18 Aug 2024 20:51:20 -0400 Subject: [PATCH 06/21] OV-4: + redirect to root after sign-up submit --- frontend/src/bundles/auth/pages/auth.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/bundles/auth/pages/auth.tsx b/frontend/src/bundles/auth/pages/auth.tsx index 6592265c3..f15c3e020 100644 --- a/frontend/src/bundles/auth/pages/auth.tsx +++ b/frontend/src/bundles/auth/pages/auth.tsx @@ -1,4 +1,6 @@ -import { AppRoute } from '~/bundles/common/enums/enums.js'; +import { Navigate } from 'react-router-dom'; + +import { AppRoute, DataStatus } from '~/bundles/common/enums/enums.js'; import { useAppDispatch, useAppSelector, @@ -41,6 +43,10 @@ const Auth: React.FC = () => { return null; }; + if(dataStatus === DataStatus.FULFILLED) { + return ; + } + return ( <> state: {dataStatus} From 547891c8f64cb702b382ddc9e43796798bafe35d Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Sun, 18 Aug 2024 21:04:32 -0400 Subject: [PATCH 07/21] OV-4: + save authenticated user after sign-up --- frontend/src/bundles/auth/store/slice.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/src/bundles/auth/store/slice.ts b/frontend/src/bundles/auth/store/slice.ts index 746d4b107..8dc90ddad 100644 --- a/frontend/src/bundles/auth/store/slice.ts +++ b/frontend/src/bundles/auth/store/slice.ts @@ -2,15 +2,18 @@ import { createSlice } from '@reduxjs/toolkit'; import { DataStatus } from '~/bundles/common/enums/enums.js'; import { type ValueOf } from '~/bundles/common/types/types.js'; +import { type UserSignUpResponseDto } from '~/bundles/users/users.js'; import { signUp } from './actions.js'; type State = { dataStatus: ValueOf; + user: UserSignUpResponseDto | undefined | null; }; const initialState: State = { dataStatus: DataStatus.IDLE, + user: null, }; const { reducer, actions, name } = createSlice({ @@ -21,11 +24,15 @@ const { reducer, actions, name } = createSlice({ builder.addCase(signUp.pending, (state) => { state.dataStatus = DataStatus.PENDING; }); - builder.addCase(signUp.fulfilled, (state) => { + builder.addCase(signUp.fulfilled, (state, action) => { + const payload = action.payload; + state.dataStatus = DataStatus.FULFILLED; + state.user = payload; }); builder.addCase(signUp.rejected, (state) => { state.dataStatus = DataStatus.REJECTED; + state.user = null; }); }, }); From 60dec102faefcda40e7e50282ab3ea42db6c0c12 Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Mon, 19 Aug 2024 10:20:22 -0400 Subject: [PATCH 08/21] OV-4: * Improvement in sign-up form validations --- .../components/sign-up-form/sign-up-form.tsx | 29 +++++++++++++------ .../common/components/button/button.tsx | 5 ++-- .../bundles/common/components/components.ts | 2 ++ .../components/form-error/form-error.tsx | 19 ++++++++++++ .../enums/user-validation-message.enum.ts | 8 +++-- .../users/enums/user-validation-rule.enum.ts | 5 +++- .../user-sign-up.validation-schema.ts | 29 ++++++++++++++++--- 7 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 frontend/src/bundles/common/components/form-error/form-error.tsx diff --git a/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx b/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx index c3ba658eb..d00052912 100644 --- a/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx +++ b/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx @@ -1,3 +1,5 @@ +import { UserValidationMessage } from 'shared/src/bundles/users/users.js'; + import { Box, Button, @@ -9,8 +11,9 @@ import { Text, VStack, } from '~/bundles/common/components/components.js'; -import { AppRoute } from '~/bundles/common/enums/enums.js'; -import { useAppForm } from '~/bundles/common/hooks/hooks.js'; +import { FormError } from '~/bundles/common/components/form-error/form-error.js'; +import { AppRoute, DataStatus } from '~/bundles/common/enums/enums.js'; +import { useAppForm, useAppSelector } from '~/bundles/common/hooks/hooks.js'; import { type UserSignUpRequestDto, userSignUpValidationSchema, @@ -23,13 +26,17 @@ type Properties = { }; const SignUpForm: React.FC = ({ onSubmit }) => { + const { dataStatus } = useAppSelector(({ auth }) => ({ + dataStatus: auth.dataStatus, + })); const form = useAppForm({ initialValues: DEFAULT_SIGN_UP_PAYLOAD, validationSchema: userSignUpValidationSchema, onSubmit, + mode: 'onChange', }); - const { handleSubmit } = form; + const { handleSubmit, isValid } = form; return ( @@ -43,26 +50,30 @@ const SignUpForm: React.FC = ({ onSubmit }) => { - - - - ); -}; - -export { PasswordInput }; From 95c3a324d086e7914e4f2f047ea87ef9f4906633 Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Mon, 19 Aug 2024 19:52:05 -0400 Subject: [PATCH 11/21] OV-4: * change names to match, the one already made --- .../users/enums/user-validation-message.enum.ts | 4 ++-- .../user-sign-up.validation-schema.ts | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) 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 e8ef590b3..90decf5d5 100644 --- a/shared/src/bundles/users/enums/user-validation-message.enum.ts +++ b/shared/src/bundles/users/enums/user-validation-message.enum.ts @@ -1,8 +1,8 @@ const UserValidationMessage = { FIELD_IS_REQUIRE: 'Please fill out this field', - EMAIL_WRONG: 'Please enter a valid email', + EMAIL_INVALID: 'Please enter a valid email', + PASSWORD_LENGTH: 'Password must have from 6 to 12 characters', PASS_DONT_MATCH: 'Passwords must be identical', - PASS_WRONG: 'Password must have from 6 to 12 characters', USER_IS_NOT_AVAILABLE: 'User with this email already exists. Log in if it is you', } as const; diff --git a/shared/src/bundles/users/validation-schemas/user-sign-up.validation-schema.ts b/shared/src/bundles/users/validation-schemas/user-sign-up.validation-schema.ts index 0af9d16d3..785644fca 100644 --- a/shared/src/bundles/users/validation-schemas/user-sign-up.validation-schema.ts +++ b/shared/src/bundles/users/validation-schemas/user-sign-up.validation-schema.ts @@ -18,31 +18,31 @@ const userSignUp = z .string() .trim() .min(UserValidationRule.EMAIL_MINIMUM_LENGTH, { - message: UserValidationMessage.EMAIL_WRONG, + message: UserValidationMessage.EMAIL_INVALID, }) .max(UserValidationRule.EMAIL_MAXIMUM_LENGTH, { - message: UserValidationMessage.EMAIL_WRONG, + message: UserValidationMessage.EMAIL_INVALID, }) .email({ - message: UserValidationMessage.EMAIL_WRONG, + message: UserValidationMessage.EMAIL_INVALID, }), password: z .string() .trim() .min(UserValidationRule.PASSWORD_MINIMUM_LENGTH, { - message: UserValidationMessage.PASS_WRONG, + message: UserValidationMessage.PASSWORD_LENGTH, }) .max(UserValidationRule.PASSWORD_MAXIMUM_LENGTH, { - message: UserValidationMessage.PASS_WRONG, + message: UserValidationMessage.PASSWORD_LENGTH, }), confirmPassword: z .string() .trim() .min(UserValidationRule.PASSWORD_MINIMUM_LENGTH, { - message: UserValidationMessage.PASS_WRONG, + message: UserValidationMessage.PASSWORD_LENGTH, }) .max(UserValidationRule.PASSWORD_MAXIMUM_LENGTH, { - message: UserValidationMessage.PASS_WRONG, + message: UserValidationMessage.PASSWORD_LENGTH, }), }) .required() From 253804a9ec716a5588b2f75019a0fd32929eba54 Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Mon, 19 Aug 2024 19:53:32 -0400 Subject: [PATCH 12/21] OV-4: * change to match layout already made --- frontend/src/app/app.tsx | 57 ++------------ frontend/src/bundles/auth/pages/auth.tsx | 24 ++++-- .../framework/theme/styles/colors.styles.ts | 17 +++++ .../theme/styles/components.styles.ts | 76 ++++++++++++++++++- 4 files changed, 115 insertions(+), 59 deletions(-) diff --git a/frontend/src/app/app.tsx b/frontend/src/app/app.tsx index e1f671b35..671be91a9 100644 --- a/frontend/src/app/app.tsx +++ b/frontend/src/app/app.tsx @@ -1,61 +1,18 @@ -import reactLogo from '~/assets/img/react.svg'; -import { Link, RouterOutlet } from '~/bundles/common/components/components.js'; +import { RouterOutlet } from '~/bundles/common/components/components.js'; import { AppRoute } from '~/bundles/common/enums/enums.js'; -import { - useAppDispatch, - useAppSelector, - useEffect, - useLocation, -} from '~/bundles/common/hooks/hooks.js'; -import { actions as userActions } from '~/bundles/users/store/users.js'; +import { useLocation } from '~/bundles/common/hooks/hooks.js'; const App: React.FC = () => { const { pathname } = useLocation(); - const dispatch = useAppDispatch(); - const { users, dataStatus } = useAppSelector(({ users }) => ({ - users: users.users, - dataStatus: users.dataStatus, - })); - const isRoot = pathname === AppRoute.ROOT; - - useEffect(() => { - if (isRoot) { - void dispatch(userActions.loadAll()); - } - }, [isRoot, dispatch]); + const isAuth = + pathname === AppRoute.SIGN_IN || pathname === AppRoute.SIGN_UP; return ( <> - logo - -
    -
  • - Root -
  • -
  • - Sign in -
  • -
  • - Sign up -
  • -
-

Current path: {pathname}

- -
- -
- {isRoot && ( - <> -

Users:

-

Status: {dataStatus}

-
    - {users.map((it) => ( -
  • {it.email}
  • - ))} -
- - )} + {/* TODO Header */} + {!isAuth && 'Header'} + ); }; diff --git a/frontend/src/bundles/auth/pages/auth.tsx b/frontend/src/bundles/auth/pages/auth.tsx index f15c3e020..612a0ffcb 100644 --- a/frontend/src/bundles/auth/pages/auth.tsx +++ b/frontend/src/bundles/auth/pages/auth.tsx @@ -1,5 +1,6 @@ import { Navigate } from 'react-router-dom'; +import { Center, SimpleGrid } from '~/bundles/common/components/components.js'; import { AppRoute, DataStatus } from '~/bundles/common/enums/enums.js'; import { useAppDispatch, @@ -30,6 +31,10 @@ const Auth: React.FC = () => { [dispatch], ); + if(dataStatus === DataStatus.FULFILLED) { + return ; + } + const getScreen = (screen: string): React.ReactNode => { switch (screen) { case AppRoute.SIGN_IN: { @@ -43,15 +48,18 @@ const Auth: React.FC = () => { return null; }; - if(dataStatus === DataStatus.FULFILLED) { - return ; - } - return ( - <> - state: {dataStatus} - {getScreen(pathname)} - + + {/* TODO: Replace with valid loader */} + {dataStatus === DataStatus.PENDING && ( +

+ Loading... +

+ )} +
{getScreen(pathname)}
+ {/* TODO: Add logo */} +
LOGO
+
); }; diff --git a/frontend/src/framework/theme/styles/colors.styles.ts b/frontend/src/framework/theme/styles/colors.styles.ts index 75c91a9c5..78fc063ee 100644 --- a/frontend/src/framework/theme/styles/colors.styles.ts +++ b/frontend/src/framework/theme/styles/colors.styles.ts @@ -1,7 +1,24 @@ const colors = { + white: '#ffffff', + background: { + 900: '#0a0049', + 600: '#35399a', + 300: '#3c9cf5', + 50: '#e2e1ec', + }, brand: { 900: '#1a365d', 200: '#b3e0ff', + secondary: { + 300: '#ff6e1c', + 600: '#eb5500', + 900: '#e13b00', + }, + }, + typography: { + 900: '#181b1a', + 600: '#616271', + 300: '#989898', }, text: { default: '#36454f', diff --git a/frontend/src/framework/theme/styles/components.styles.ts b/frontend/src/framework/theme/styles/components.styles.ts index 2e62e5878..417d40ef9 100644 --- a/frontend/src/framework/theme/styles/components.styles.ts +++ b/frontend/src/framework/theme/styles/components.styles.ts @@ -1,7 +1,81 @@ +import { colors } from './colors.styles.js'; + const components = { Heading: { baseStyle: { - color: 'text.accent', + color: colors.text.accent, + }, + }, + Button: { + variants: { + solid: { + color: colors.white, + bgColor: colors.brand.secondary[300], + _hover: { + bg: colors.brand.secondary[600], + _disabled: { + bg: colors.brand.secondary[600], + }, + }, + }, + ghostIcon: { + color: colors.white, + _hover: { + color: colors.brand.secondary[300], + }, + }, + }, + }, + Link: { + variants: { + primary: { + color: colors.text.default, + }, + secondary: { + color: colors.brand.secondary[300], + _hover: { + color: colors.brand.secondary[600], + }, + }, + }, + baseStyle: { + _hover: { + textDecoration: 'none', + }, + }, + }, + Input: { + variants: { + outline: { + field: { + _focus: { + borderWidth: '2px', + borderColor: colors.brand.secondary[300], + boxShadow: 'none', + }, + _placeholder: { + color: colors.typography[300], + }, + _invalid: { + borderWidth: '2px', + borderColor: colors.brand.secondary[900], + boxShadow: 'none', + }, + _autofill: { + textFillColor: colors.white, + caretColor: colors.white, + boxShadow: '0 0 0 0 inherit inset', + transition: 'background-color 5000s ease-in-out 0s', + }, + }, + }, + }, + }, + FormError: { + baseStyle: { + text: { + color: colors.brand.secondary[900], + }, }, }, }; From dcff05901767014ecc159cc34e8ea37ddf58a602 Mon Sep 17 00:00:00 2001 From: Luis Felix Date: Mon, 19 Aug 2024 20:27:24 -0400 Subject: [PATCH 13/21] OV-4: * improvement styles in sign-up form --- .../components/sign-up-form/sign-up-form.tsx | 48 ++++++++++++------- .../common/components/button/button.tsx | 23 +++++++-- .../bundles/common/components/components.ts | 5 +- .../bundles/common/components/link/link.tsx | 6 ++- 4 files changed, 59 insertions(+), 23 deletions(-) diff --git a/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx b/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx index d00052912..98bcdffa0 100644 --- a/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx +++ b/frontend/src/bundles/auth/components/sign-up-form/sign-up-form.tsx @@ -4,21 +4,18 @@ import { Box, Button, FormProvider, - Heading, Input, Link, - PasswordInput, - Text, VStack, } from '~/bundles/common/components/components.js'; -import { FormError } from '~/bundles/common/components/form-error/form-error.js'; import { AppRoute, DataStatus } from '~/bundles/common/enums/enums.js'; -import { useAppForm, useAppSelector } from '~/bundles/common/hooks/hooks.js'; +import { useAppForm, useAppSelector, useMemo } from '~/bundles/common/hooks/hooks.js'; import { type UserSignUpRequestDto, userSignUpValidationSchema, } from '~/bundles/users/users.js'; +import { FormError, FormHeader, PasswordInput } from '../common/components.js'; import { DEFAULT_SIGN_UP_PAYLOAD } from './constants/constants.js'; type Properties = { @@ -33,18 +30,29 @@ const SignUpForm: React.FC = ({ onSubmit }) => { initialValues: DEFAULT_SIGN_UP_PAYLOAD, validationSchema: userSignUpValidationSchema, onSubmit, - mode: 'onChange', }); - const { handleSubmit, isValid } = form; + const { handleSubmit, errors, values } = form; + + const isEmpty = useMemo( + () => Object.values(values).some((value) => value.trim().length === 0), + [values], + ); return ( - - Create an account - Already registerd? - Log In - + + + Already registerd?{' '} + + Log In + + + } + />
= ({ onSubmit }) => { /> +