diff --git a/.gitignore b/.gitignore index c49f35d8..87431789 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,6 @@ GoogleService-Info.plist scripts/doppler_variables.sh .env -env.json \ No newline at end of file +env.json + +.vercel \ No newline at end of file diff --git a/src/hooks/forms/index.ts b/src/hooks/forms/index.ts index 14f4e5d7..c026210d 100644 --- a/src/hooks/forms/index.ts +++ b/src/hooks/forms/index.ts @@ -1,3 +1,4 @@ export * from './useSignInForm' export * from './useSignUpForm' export * from './useTestForm' +export * from './useUpdateProfileForm' diff --git a/src/hooks/forms/useSignInForm.ts b/src/hooks/forms/useSignInForm.ts index 55e75b6d..beb116da 100644 --- a/src/hooks/forms/useSignInForm.ts +++ b/src/hooks/forms/useSignInForm.ts @@ -1,11 +1,15 @@ import { useAuthControllerLogin } from '@baca/api/query/auth/auth' +import { AuthEmailLoginDto } from '@baca/api/types' import { setToken } from '@baca/services' import { isSignedInAtom } from '@baca/store/auth' -import { SignInFormValues } from '@baca/types/authForms' import { hapticImpact } from '@baca/utils' +import { handleFormError } from '@baca/utils/handleFormErrors' import { useSetAtom } from 'jotai' import { useForm } from 'react-hook-form' -import { notify } from 'react-native-notificated' + +type SignInFormValues = AuthEmailLoginDto & { + confirm: boolean +} const defaultValues: SignInFormValues = { // TODO: Reset this values when building production app @@ -24,8 +28,9 @@ export const useSignInForm = () => { const { control, formState: { errors }, - setFocus, handleSubmit, + setError: setFormError, + setFocus, } = useForm({ mode: 'onTouched', defaultValues, @@ -40,7 +45,13 @@ export const useSignInForm = () => { // FIXME: add proper notification handling, generate some global config { onError: (e) => { - notify('error', { params: { title: 'ERROR', description: e?.message } }) + handleFormError( + e as unknown as keyof AuthEmailLoginDto, + ({ field, description }) => { + setFormError(field, { message: description }) + } + ) + hapticImpact() }, onSuccess: async (response) => { diff --git a/src/hooks/forms/useSignUpForm.ts b/src/hooks/forms/useSignUpForm.ts index 0906ebf3..6b86e218 100644 --- a/src/hooks/forms/useSignUpForm.ts +++ b/src/hooks/forms/useSignUpForm.ts @@ -2,8 +2,6 @@ import { useAuthControllerRegister } from '@baca/api/query/auth/auth' import { AuthRegisterLoginDto } from '@baca/api/types' import { hapticImpact } from '@baca/utils' import { handleFormError } from '@baca/utils/handleFormErrors' -import { isError } from '@tanstack/react-query' -import { useState } from 'react' import { useForm } from 'react-hook-form' import { useTranslation } from 'react-i18next' import { notify } from 'react-native-notificated' @@ -20,9 +18,7 @@ const defaultValues: AuthRegisterLoginDto = { } export const useSignUpForm = () => { - const [error, setError] = useState('') - const [isSubmitting, setIsSubmitting] = useState(false) - const { mutateAsync } = useAuthControllerRegister() + const { mutate: signUpMutation, isLoading } = useAuthControllerRegister() const { t } = useTranslation() const { @@ -36,46 +32,39 @@ export const useSignUpForm = () => { defaultValues, }) - const onSubmit = async (data: AuthRegisterLoginDto) => { - try { - setIsSubmitting(true) - setError('') - - await mutateAsync({ data }) - notify('success', { - params: { - style: { multiline: 100 }, - title: 'SUCCESS', - description: t('sign_up_screen.created_new_account', { userEmail: data.email }), + const onSubmit = (data: AuthRegisterLoginDto) => { + signUpMutation( + { + data, + }, + { + onSuccess: () => { + notify('success', { + params: { + style: { multiline: 100 }, + title: 'SUCCESS', + description: t('toast.success.new_account_created', { userEmail: data.email }), + }, + }) + }, + onError: (e) => { + handleFormError( + e as unknown as keyof AuthRegisterLoginDto, + ({ field, description }) => { + setFormError(field, { message: description }) + } + ) + hapticImpact() }, - }) - } catch (e) { - if (isError(e)) { - setError(e.message) - } else { - setError(t('errors.something_went_wrong')) } - - handleFormError( - e as keyof AuthRegisterLoginDto, - ({ field, description }) => { - setFormError(field as keyof AuthRegisterLoginDto, { message: description }) - } - ) - - hapticImpact() - } finally { - setIsSubmitting(false) - } + ) } return { control, - error, errors, - isRegisterLoading: isSubmitting, - setFocus, - setIsSubmitting, + isSubmitting: isLoading, register: handleSubmit(onSubmit), + setFocus, } } diff --git a/src/hooks/forms/useUpdateProfileForm.ts b/src/hooks/forms/useUpdateProfileForm.ts new file mode 100644 index 00000000..b8b98618 --- /dev/null +++ b/src/hooks/forms/useUpdateProfileForm.ts @@ -0,0 +1,74 @@ +import { useAuthControllerUpdate, useAuthControllerMe } from '@baca/api/query/auth/auth' +import { AuthUpdateDto } from '@baca/api/types' +import { hapticImpact } from '@baca/utils' +import { handleFormError } from '@baca/utils/handleFormErrors' +import { useMemo, useEffect } from 'react' +import { useForm } from 'react-hook-form' +import { useTranslation } from 'react-i18next' +import { notify } from 'react-native-notificated' + +export const useUpdateProfileForm = () => { + const { data: userData } = useAuthControllerMe() + const { t } = useTranslation() + const { mutate: updateUserMutation, isLoading } = useAuthControllerUpdate() + + const defaultValues: AuthUpdateDto = useMemo( + () => ({ + email: userData?.email || '', + firstName: userData?.firstName || '', + lastName: userData?.lastName || '', + }), + [userData] + ) + + const { + control, + formState: { errors }, + handleSubmit, + reset, + setError: setFormError, + setFocus, + } = useForm({ + mode: 'onTouched', + defaultValues, + }) + + useEffect(() => { + reset(defaultValues) + }, [reset, defaultValues]) + + const onSubmit = (data: AuthUpdateDto) => { + updateUserMutation( + { data }, + { + onSuccess: () => { + notify('success', { + params: { + style: { multiline: 100 }, + title: 'SUCCESS', + description: t('toast.success.profile_updated'), + }, + }) + }, + onError: (e) => { + handleFormError( + e as unknown as keyof AuthUpdateDto, + ({ field, description }) => { + setFormError(field, { message: description }) + } + ) + + hapticImpact() + }, + } + ) + } + + return { + control, + errors, + isSubmitting: isLoading, + setFocus, + submit: handleSubmit(onSubmit), + } +} diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 91527b8e..6fabeca1 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -3,45 +3,61 @@ "add": "Add", "back": "Back", "cancel": "Cancel", - "email_label": "E-mail", - "email_placeholder": "john@doe.com", - "empty_list": "The list is empty", "go_back": "Go back", - "log_in": "Login", - "phone_label": "Telephone", "remove": "Remove", "save": "Save", "search": "Search", - "send_again": "Send again", - "show_on_map": "Show on map", - "sign_in": "Sign in", - "sign_up": "Register", "try_again_later": "Please try again later", - "try_again": "Try again", - "user_label": "User", - "user_placeholder": "user" + "try_again": "Try again" }, "errors": { + "invalid_email": "Niepoprawny adres e-mail", + "invalid_password": "Niepoprawne has艂o", + "missing_auth": "Missing auth", "screen_not_found": "NotFound screen", "something_went_wrong": "Something went wrong", - "token_expired": "Token expired", - "missing_auth": "Missing auth" + "token_expired": "Token expired" + }, + "examples_component": { + "example": "Example" }, "form": { - "invalid_email_format": "Incorrect e-mail address", - "invalid_password_format": "Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character", - "invalid_password": "Incorrect password", - "required": "This field is required" + "checkbox": { + "privacy_policy": "I鈥檝e read and accept Privacy Policy", + "remember_me": "Remember me", + "terms_accepted": "I agree to the Terms and Conditions" + }, + "errors": {}, + "labels": { + "email": "E-mail address", + "first_name": "First name", + "last_name": "Last name", + "password": "Password" + }, + "placeholders": { + "create_password": "Create a password", + "email": "Enter your email", + "first_name": "Enter your first name", + "last_name": "Enter your last name", + "password": "Password" + }, + "select": {}, + "validation": { + "invalid_email_format": "Incorrect e-mail address format", + "invalid_password_format": "Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character", + "required": "This field is required" + } }, "navigation": { "prevent_go_back_alert": { - "title": "Discard changes?", "description": "You have unsaved changes. Are you sure to discard them and leave the screen?", + "discard": "Discard", "do_not_leave": "Don't leave", - "discard": "Discard" + "title": "Discard changes?" }, "screen_titles": { "application_info": "ApplicationInfo", + "blog": "Blog", "colors": "Colors", "components": "Components", "data_from_be_screen_example": "Data from BE", @@ -55,25 +71,24 @@ "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", - "typography": "Typography", "test_form": "Test form", - "blog": "Blog" + "typography": "Typography" } }, + "toast": { + "error": {}, + "success": { + "new_account_created": "A new account has been created. An email with an activation link was sent to {{userEmail}}.", + "profile_updated": "Successfully updated your profile data." + }, + "warning": {} + }, "update": { - "alert_title": "New version available", "alert_message": "You will have to restart the application to have better experiences while using it", + "alert_title": "New version available", "restart": "Restart" }, - "examples_component": { - "example": "Example" - }, - "landing_screen": { - "go_to_blog": "Open blog", - "go_to_form": "Open full screen form", - "login_cta": "Log in", - "sign_up": "Sign up" - }, + "application_info_screen": { "navigation_info": "When you will try to go back it will double ask if you really want to leave \n" }, @@ -81,18 +96,6 @@ "colors_label": "Colors" }, "components_screen": { - "test_notification": "Test notification", - "typography": { - "label": "Typography", - "xs": "xs", - "sm": "sm", - "md": "md", - "lg": "lg", - "xl": "xl", - "2xl": "2xl", - "3xl": "3xl", - "4xl": "4xl" - }, "button_variants": { "disabled": "Button disabled", "ghost": "Button ghost", @@ -104,6 +107,7 @@ "secondary": "Button secondary", "with_icons": "Button with icons" }, + "loader_variants": { "bricks": "Bricks loader", "bubbles": "Bubbles loader", @@ -115,6 +119,18 @@ "notification": { "description": "by react-native-notificated 馃帀", "title": "In-app notification example" + }, + "test_notification": "Test notification", + "typography": { + "label": "Typography", + "xs": "xs", + "sm": "sm", + "md": "md", + "lg": "lg", + "xl": "xl", + "2xl": "2xl", + "3xl": "3xl", + "4xl": "4xl" } }, "details_screen": { @@ -137,6 +153,12 @@ "home_screen": { "details": "Details" }, + "landing_screen": { + "go_to_blog": "Open blog", + "go_to_form": "Open full screen form", + "login_cta": "Log in", + "sign_up": "Sign up" + }, "settings_screen": { "copy_push_token": "Copy push token", "current_theme": "Current theme: {{theme}}", @@ -145,31 +167,11 @@ }, "sign_in_screen": { "do_not_have_an_account": "Don't have an account?", - "email_helper_text": "Email must be here", - "forgot_password": "Forgot your password?", - "or_pass": "or enter:", - "password_helper_text": "Password must be here", - "password_label": "Password", - "password_placeholder": "password", - "remember_me": "Remember me", "sign_in": "Sign in", "sign_up": "Sign up" }, "sign_up_screen": { - "created_new_account": "A new account has been created. An email with an activation link was sent to {{userEmail}}.", - "email_label": "Email", - "email_placeholder": "Enter your email", - "first_name_label": "First name", - "first_name_placeholder": "Enter your first name", - "last_name_label": "Last name", - "last_name_placeholder": "Enter your last name", - "newsletter_label": "Subscribe to our newsletter", - "password_placeholder": "Create a password", - "password_label": "Password", - "privacy_policy_label": "I鈥檝e read and accept Privacy Policy", - "sign_up": "Sign up", - "trail_descirption": "Start your 30-day free trial.", - "terms_accepted_label": "I agree to the Terms and Conditions" + "sign_up": "Sign up" }, "test_form": { "additional_comment": "Additional comment", diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json index da2299af..73c882f4 100644 --- a/src/i18n/translations/pl.json +++ b/src/i18n/translations/pl.json @@ -3,35 +3,50 @@ "add": "Dodaj", "back": "Cofnij", "cancel": "Anuluj", - "email_label": "E-mail", - "email_placeholder": "john@doe.com", - "empty_list": "Lista jest pusta", "go_back": "Cofnij", - "log_in": "Login", - "phone_label": "Telefon", "remove": "Usu艅", "save": "Zapisz", "search": "Szukaj", - "send_again": "Wy艣lij ponownie", - "show_on_map": "Poka偶 na mapie", - "sign_in": "Zaloguj", - "sign_up": "Zarejestruj", "try_again_later": "Prosz臋 spr贸buj ponownie p贸藕niej", - "try_again": "Spr贸buj ponownie", - "user_label": "U偶ytkownik", - "user_placeholder": "U偶ytkownik" + "try_again": "Spr贸buj ponownie" }, "errors": { + "invalid_email": "Niepoprawny adres e-mail", + "invalid_password": "Niepoprawne has艂o", "missing_auth": "Brak autoryzacji", "screen_not_found": "NotFound screen", "something_went_wrong": "Co艣 posz艂o nie tak", "token_expired": "Token wygas艂" }, + "examples_component": { + "example": "Przyk艂ad" + }, "form": { - "invalid_email_format": "Z艂y adres e-mail", - "invalid_password_format": "Has艂o musi zawiera膰 minimum: 8 znak贸w, jedn膮 wielk膮 liter臋, jedn膮 mal膮 liter臋, jedn膮 cyfr臋 i jeden znak specjalny", - "invalid_password": "Niepoprawne has艂o", - "required": "Pole wymagane" + "checkbox": { + "privacy_policy": "Zapozna艂em si臋 i akceptuj臋 polityk臋 prywatno艣ci", + "remember_me": "Zapami臋taj mnie", + "terms_accepted": "Zgadzam si臋 z warunkami u偶ytkowania" + }, + "errors": {}, + "labels": { + "email": "Adres e-mail", + "first_name": "Imi臋", + "last_name": "Nazwisko", + "password": "Has艂o" + }, + "placeholders": { + "create_password": "Utw贸rz nowe has艂o", + "email": "Podaj adres e-mail", + "first_name": "Podaj swoje imi臋", + "last_name": "Podaj swoje nazwisko", + "password": "Has艂o" + }, + "select": {}, + "validation": { + "invalid_email_format": "Niepoprawny format adresu e-mail", + "invalid_password_format": "Has艂o musi zawiera膰 minimum: 8 znak贸w, jedn膮 wielk膮 liter臋, jedn膮 ma艂膮 liter臋, jedn膮 cyfr臋 i jeden znak specjalny", + "required": "Pole wymagane" + } }, "navigation": { "prevent_go_back_alert": { @@ -42,6 +57,7 @@ }, "screen_titles": { "application_info": "ApplicationInfo", + "blog": "Blog", "colors": "Colors", "components": "Components", "data_from_be_screen_example": "Dane z backend-u", @@ -55,25 +71,24 @@ "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", - "typography": "Typography", "test_form": "Formularz testowy", - "blog": "Blog" + "typography": "Typography" } }, + "toast": { + "error": {}, + "success": { + "new_account_created": "Nowe konto zosta艂o stworzone. Email z linkiem weryfikacyjnym zosta艂 wys艂any na {{userEmail}}.", + "profile_updated": "Zaktualizowano Twoje dane." + }, + "warning": {} + }, "update": { "alert_message": "B臋dziesz musia艂 zrestartowa膰 aplikacj臋, 偶eby mie膰 lepsze do艣wiadczenia podczas jej u偶ywania", "alert_title": "Aktualizacja", "restart": "Zrestartuj" }, - "examples_component": { - "example": "Przyk艂ad" - }, - "landing_screen": { - "login_cta": "Zaloguj si臋", - "sign_up": "Zarejestruj si臋", - "go_to_blog": "Otw贸rz blog", - "go_to_form": "Otw贸rz pe艂no ekranowy formularz full" - }, + "application_info_screen": { "navigation_info": "Kiedy b臋dziesz pr贸bowa艂 cofn膮膰 to zostaniesz podw贸jnie zapytany, czy na pewno tego chcesz \n" }, @@ -137,6 +152,12 @@ "home_screen": { "details": "Detale" }, + "landing_screen": { + "login_cta": "Zaloguj si臋", + "sign_up": "Zarejestruj si臋", + "go_to_blog": "Otw贸rz blog", + "go_to_form": "Otw贸rz pe艂no ekranowy formularz full" + }, "settings_screen": { "current_theme": "Current theme: {{theme}}", "selected": " - wybrano", @@ -144,31 +165,12 @@ }, "sign_in_screen": { "do_not_have_an_account": "Nie masz konta?", - "email_helper_text": "Email", - "forgot_password": "Zapomnia艂e艣 has艂a?", - "or_pass": "lub wprowad藕:", - "password_helper_text": "Has艂a musz膮 by膰 takie same", - "password_label": "Has艂o", - "password_placeholder": "has艂o", - "remember_me": "Zapami臋taj mnie", "sign_in": "Zaloguj", "sign_up": "Zarejestruj" }, "sign_up_screen": { "created_new_account": "Nowe konto zosta艂o stworzone. Email z linkiem weryfikacyjnym zosta艂 wys艂any na {{userEmail}}.", - "newsletter_label": "Subskrybuj nasz newsletter", - "sign_up": "Zarejestruj", - "email_label": "E-mail", - "email_placeholder": "Podaj sw贸j e-mail", - "first_name_label": "Imi臋", - "first_name_placeholder": "Wprowad藕 imi臋", - "last_name_label": "Nazwisko", - "last_name_placeholder": "Wprowad藕 nazwisko", - "password_placeholder": "Nowe has艂o", - "password_label": "Has艂o", - "privacy_policy_label": "Zapozna艂em si臋 i akceptuj臋 polityk臋 prywatno艣ci", - "trail_descirption": "Rozpocznij darmowy 30 dniowy okres pr贸bny.", - "terms_accepted_label": "Zgadzam si臋 z warunkami u偶ytkowania" + "sign_up": "Zarejestruj" }, "test_form": { "additional_comment": "Dodatkowy komentarz", diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 1b858bf2..d3e9b521 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,32 +1,77 @@ -import { darkLogo, lightLogo } from '@baca/constants' -import { useColorScheme } from '@baca/contexts' -import { Center, Text } from '@baca/design-system' -import { useScreenOptions } from '@baca/hooks' -import { Image, StyleSheet } from 'react-native' +import { ControlledField } from '@baca/components' +import { Button, Text, Spacer, Row, Box } from '@baca/design-system' +import { useCallback, useTranslation, useUpdateProfileForm, useScreenOptions } from '@baca/hooks' +import { useRouter } from 'expo-router' export const ProfileScreen = () => { - useScreenOptions({ - title: 'Profile', - }) + const { t } = useTranslation() + const { back } = useRouter() - const { colorScheme } = useColorScheme() + useScreenOptions({ headerShown: false }) + + const { control, errors, isSubmitting, setFocus, submit } = useUpdateProfileForm() + + const focusLastNameInput = useCallback(() => setFocus('lastName'), [setFocus]) return ( -
- - Profile screen -
+ + Profile + Update your personal details here. + + + + + + + + + + {t('common.cancel')} + + + + + ) } - -const styles = StyleSheet.create({ - logo: { - height: 100, - width: '100%', - }, -}) diff --git a/src/screens/SignInScreen.tsx b/src/screens/SignInScreen.tsx index d156352e..ad621289 100644 --- a/src/screens/SignInScreen.tsx +++ b/src/screens/SignInScreen.tsx @@ -52,15 +52,15 @@ export const SignInScreen = (): JSX.Element => { enterKeyHint="next" inputMode="email" isRequired - label={t('common.email_label')} + label={t('form.labels.email')} name="email" onSubmitEditing={focusPasswordInput} - placeholder={t('common.email_placeholder')} + placeholder={t('form.placeholders.email')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), pattern: { value: REGEX.EMAIL, - message: t('form.invalid_email_format'), + message: t('form.validation.invalid_email_format'), }, }} testID="emailInput" @@ -70,12 +70,12 @@ export const SignInScreen = (): JSX.Element => { autoCapitalize="none" enterKeyHint="send" isRequired - label={t('sign_in_screen.password_label')} + label={t('form.labels.password')} name="password" onSubmitEditing={submit} - placeholder={t('sign_in_screen.password_placeholder')} + placeholder={t('form.placeholders.password')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} testID="passwordInput" type="password" @@ -83,7 +83,7 @@ export const SignInScreen = (): JSX.Element => {
{ title: t('navigation.screen_titles.sign_up'), }) - const { control, errors, register, isRegisterLoading, setFocus } = useSignUpForm() + const { control, errors, register, isSubmitting, setFocus } = useSignUpForm() useEffect(() => { setTimeout(() => { @@ -30,13 +30,13 @@ export const SignUpScreen = () => { autoCapitalize="none" enterKeyHint="next" isRequired - label={t('sign_up_screen.first_name_label')} + label={t('form.labels.first_name')} mb={2} name="firstName" onSubmitEditing={focusLastNameInput} - placeholder={t('sign_up_screen.first_name_placeholder')} + placeholder={t('form.placeholders.first_name')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} /> { autoCapitalize="none" enterKeyHint="next" isRequired - label={t('sign_up_screen.last_name_label')} + label={t('form.labels.last_name')} mb={2} name="lastName" onSubmitEditing={focusEmailInput} - placeholder={t('sign_up_screen.last_name_placeholder')} + placeholder={t('form.placeholders.last_name')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} /> { enterKeyHint="next" inputMode="email" isRequired - label={t('sign_up_screen.email_label')} + label={t('form.labels.email')} mb={2} name="email" onSubmitEditing={focusPasswordInput} - placeholder={t('sign_up_screen.email_placeholder')} + placeholder={t('form.placeholders.email')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} /> { autoCapitalize="none" enterKeyHint="next" isRequired - label={t('sign_up_screen.password_label')} + label={t('form.labels.password')} mb={16} name="password" onSubmitEditing={register} - placeholder={t('sign_up_screen.password_placeholder')} + placeholder={t('form.placeholders.create_password')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} type="password" /> -
diff --git a/src/types/authForms.ts b/src/types/authForms.ts deleted file mode 100644 index af0838de..00000000 --- a/src/types/authForms.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type SignUpFormValues = { - user: string - email: string - password: string - agree: boolean - newsletter: boolean -} - -export type SignInFormValues = { - email: string - password: string - confirm: boolean -} diff --git a/src/utils/getApiError.ts b/src/utils/getApiError.ts index a3cf17ef..fd6bae3b 100644 --- a/src/utils/getApiError.ts +++ b/src/utils/getApiError.ts @@ -2,8 +2,8 @@ import i18n from '../i18n' //CONFIG: This are examples errors, change it export const API_ERRORS = [ - { errorMessage: 'invalidPassword', translation: i18n.t('form.invalid_password') }, - { errorMessage: 'ERROR.INCORRECT.EMAIL', translation: i18n.t('form.invalid_email_format') }, + { errorMessage: 'invalidPassword', translation: i18n.t('errors.invalid_password') }, + { errorMessage: 'ERROR.INCORRECT.EMAIL', translation: i18n.t('errors.invalid_email') }, { errorMessage: 'Token invalid', translation: i18n.t('errors.token_expired') }, { errorMessage: 'Missing authentication', translation: i18n.t('errors.missing_auth') }, ]