diff --git a/src/components/Account/AccountInfo.tsx b/src/components/Account/AccountInfo.tsx index 954d873..4f4d347 100644 --- a/src/components/Account/AccountInfo.tsx +++ b/src/components/Account/AccountInfo.tsx @@ -47,116 +47,123 @@ const AccountInfo: FC = () => { ), }); - const { register, handleSubmit, formState, reset } = useForm< - z.infer - >({ - resolver: zodResolver(EditUserSchema), - defaultValues: { - username: user!.username, - email: user!.email, - firstName: user!.firstName, - lastName: user!.lastName, - }, - }); - - const [inEditMode, setInEditMode] = useState(false); + const [editToggled, setEditToggled] = useState(false); const onSubmit = async (data: z.infer) => { const loadingToast = toast.loading('Submitting edits...'); try { await sendEditUserRequest({ user: user!, data }); - await mutate!(); - setInEditMode(false); toast.remove(loadingToast); toast.success('Edits submitted successfully.'); + setEditToggled(false); + await mutate!(); } catch (error) { - setInEditMode(false); + setEditToggled(false); toast.remove(loadingToast); createErrorToast(error); await mutate!(); } }; + const { register, handleSubmit, formState, reset } = useForm< + z.infer + >({ + resolver: zodResolver(EditUserSchema), + }); return ( -
-
-
- - -
- - Username - {formState.errors.username?.message} - - - - Email - {formState.errors.email?.message} - - - -
-
- - First Name - {formState.errors.firstName?.message} - - -
-
- - Last Name - {formState.errors.lastName?.message} - - -
-
+
+
+
+
+

Edit Your Account Info

+

Update your personal account information.

- {inEditMode && ( - - )} - +
+ { + setEditToggled((val) => !val); + await mutate!(); + reset({ + username: user!.username, + email: user!.email, + firstName: user!.firstName, + lastName: user!.lastName, + }); + }} + /> +
+
+ {editToggled && ( +
+
+ + Username + {formState.errors.username?.message} + + + + Email + {formState.errors.email?.message} + + + +
+
+ + First Name + {formState.errors.firstName?.message} + + +
+
+ + Last Name + {formState.errors.lastName?.message} + + +
+
+ +
+
+ )}
); diff --git a/src/components/Account/Security.tsx b/src/components/Account/Security.tsx index 1fc4991..739c99b 100644 --- a/src/components/Account/Security.tsx +++ b/src/components/Account/Security.tsx @@ -20,56 +20,65 @@ const Security: FunctionComponent = () => { const onSubmit: SubmitHandler> = async (data) => { await sendUpdatePasswordRequest(data); - + setEditToggled(value => !value) reset(); }; return ( -
-
-
-

Change Your Password

-

Update your password to maintain the safety of your account.

+
+
+
+
+

Change Your Password

+

Update your password to maintain the safety of your account.

+
+
+ { + setEditToggled((val) => !val); + reset(); + }} + /> +
-
- setEditToggled((val) => !val)} - /> -
-
- {editToggled && ( -
- - New Password - {formState.errors.password?.message} - - - - Confirm Password - {formState.errors.confirmPassword?.message} - - + {editToggled && ( + + + New Password + {formState.errors.password?.message} + + + + Confirm Password + {formState.errors.confirmPassword?.message} + + - - - )} + + + )} +
); }; diff --git a/src/components/ui/CustomToast.tsx b/src/components/ui/CustomToast.tsx index ca445fb..d6b1281 100644 --- a/src/components/ui/CustomToast.tsx +++ b/src/components/ui/CustomToast.tsx @@ -22,14 +22,14 @@ const toastToClassName = (toastType: Toast['type']) => { const CustomToast: FC<{ children: ReactNode }> = ({ children }) => { return ( <> - + {(t) => { const alertType = toastToClassName(t.type); return (
-

{resolveValue(t.message, t)}

+

{resolveValue(t.message, t)}

{t.type !== 'loading' && (
+ + )} - setConfirmationResent(true); - } catch (err) { - createErrorToast(err); - } - }; - - return ( - <> - - Confirm User | The Biergarten App - -
- {!confirmationResent ? ( - <> -

- Your confirmation token is expired. -

- - - ) : ( - <> -

- Resent your confirmation link. -

-

Please check your email.

- - )} -
- - ); - } - - return null; + {!needsToLogin && tokenInvalid && confirmationResent && ( + <> +

+ Resent your confirmation link. +

+

Please check your email.

+ + )} +
+ + ); }; export default ConfirmUserPage; diff --git a/src/pages/users/current.tsx b/src/pages/users/current.tsx index 58980d2..2111bbc 100644 --- a/src/pages/users/current.tsx +++ b/src/pages/users/current.tsx @@ -20,7 +20,7 @@ const ProtectedPage: NextPage = () => { return ( <> - Hello, {user?.firstName}! | The Biergarten App + Hello! | The Biergarten App
{isLoading && } diff --git a/src/services/User/schema/CreateUserValidationSchemas.ts b/src/services/User/schema/CreateUserValidationSchemas.ts index 485edcc..3d1bf12 100644 --- a/src/services/User/schema/CreateUserValidationSchemas.ts +++ b/src/services/User/schema/CreateUserValidationSchemas.ts @@ -4,6 +4,8 @@ import sub from 'date-fns/sub'; import { z } from 'zod'; const MINIMUM_DATE_OF_BIRTH = sub(new Date(), { years: 19 }); +const NAME_REGEX = + /^[a-zA-ZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųūÿýżźçčšžÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ∂ðæ ,.'-]+$/u; export const BaseCreateUserSchema = z.object({ password: z @@ -23,14 +25,14 @@ export const BaseCreateUserSchema = z.object({ .string() .min(1, { message: 'First name must not be empty.' }) .max(20, { message: 'First name must be less than 20 characters.' }) - .refine((firstName) => /^[a-zA-Z]+$/.test(firstName), { - message: 'First name must only contain letters.', + .refine((firstName) => NAME_REGEX.test(firstName), { + message: 'First name must only contain letters or hyphens.', }), lastName: z .string() .min(1, { message: 'Last name must not be empty.' }) .max(20, { message: 'Last name must be less than 20 characters.' }) - .refine((lastName) => /^[a-zA-Z]+$/.test(lastName), { + .refine((lastName) => NAME_REGEX.test(lastName), { message: 'Last name must only contain letters.', }), dateOfBirth: z