Skip to content

Commit f4a5df9

Browse files
committed
Small improvements to Sign Up page
1 parent 51932fe commit f4a5df9

File tree

5 files changed

+203
-119
lines changed

5 files changed

+203
-119
lines changed

frontend/src/common/utils/i18n/resources/en/auth.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
"success": "Email verified successfully!",
6363
"code-resent": "A new verification code has been sent to your email."
6464
},
65+
"registration": {
66+
"success": "Registration successful!",
67+
"verify-email": "Please verify your email to activate your account."
68+
},
6569
"oauth": {
6670
"processing": "Processing your login...",
6771
"redirecting": "Redirecting...",
@@ -80,5 +84,6 @@
8084
"uppercase": "Must contain at least one uppercase letter",
8185
"number": "Must contain at least one number",
8286
"special-char": "Must contain at least one special character"
83-
}
87+
},
88+
"please-fill-details": "Please fill in your personal details"
8489
}

frontend/src/common/utils/i18n/resources/es/auth.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,10 @@
1616
},
1717
"signin": "Iniciar sesión",
1818
"signin.title": "Iniciar sesión",
19-
"signin.subtitle": "Iniciar sesión para acceder a MEDReport AI"
19+
"signin.subtitle": "Iniciar sesión para acceder a MEDReport AI",
20+
"registration": {
21+
"success": "¡Registro exitoso!",
22+
"verify-email": "Por favor verifica tu correo electrónico para activar tu cuenta."
23+
},
24+
"please-fill-details": "Por favor complete sus datos personales"
2025
}

frontend/src/common/utils/i18n/resources/fr/auth.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,10 @@
1616
},
1717
"signin": "Se connecter",
1818
"signin.title": "Se connecter",
19-
"signin.subtitle": "Connectez-vous pour accéder à MEDReport AI"
19+
"signin.subtitle": "Connectez-vous pour accéder à MEDReport AI",
20+
"registration": {
21+
"success": "Inscription réussie !",
22+
"verify-email": "Veuillez vérifier votre e-mail pour activer votre compte."
23+
},
24+
"please-fill-details": "Veuillez remplir vos coordonnées personnelles"
2025
}

frontend/src/pages/Auth/SignUp/components/SignUpForm.scss

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,37 @@
9494
}
9595
}
9696
}
97+
98+
&__success {
99+
display: flex;
100+
flex-direction: column;
101+
align-items: center;
102+
justify-content: center;
103+
text-align: center;
104+
padding: 2rem 1.5rem;
105+
background-color: #f8fff8;
106+
border: 1px solid var(--ion-color-success);
107+
border-radius: 8px;
108+
margin: 1rem 0;
109+
110+
&-icon {
111+
font-size: 4rem;
112+
margin-bottom: 1rem;
113+
}
114+
115+
h3 {
116+
font-size: 1.4rem;
117+
font-weight: 600;
118+
margin: 0 0 0.75rem;
119+
color: var(--ion-color-success);
120+
}
121+
122+
p {
123+
font-size: 1rem;
124+
margin: 0;
125+
color: #666;
126+
line-height: 1.5;
127+
max-width: 320px;
128+
}
129+
}
97130
}

frontend/src/pages/Auth/SignUp/components/SignUpForm.tsx

Lines changed: 152 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,27 @@ interface SignUpFormValues {
4141
confirmPassword: string;
4242
}
4343

44+
/**
45+
* Registration success message component
46+
*/
47+
const RegistrationSuccess = ({ email }: { email: string }) => {
48+
const { t } = useTranslation();
49+
50+
return (
51+
<div className="ls-signup-form__success">
52+
<IonIcon icon={checkmarkCircle} color="success" className="ls-signup-form__success-icon" />
53+
<h3>{t('registration.success', { ns: 'auth' })}</h3>
54+
<p>
55+
{t('registration.verify-email', {
56+
ns: 'auth',
57+
email,
58+
defaultValue: 'Please verify your email to activate your account.',
59+
})}
60+
</p>
61+
</div>
62+
);
63+
};
64+
4465
/**
4566
* Password guidelines component
4667
*/
@@ -89,6 +110,8 @@ const SignUpForm = ({ className, testid = 'form-signup' }: SignUpFormProps): JSX
89110
const focusInput = useRef<HTMLIonInputElement>(null);
90111
const [error, setError] = useState<AuthError | null>(null);
91112
const [isLoading, setIsLoading] = useState(false);
113+
const [registrationSuccess, setRegistrationSuccess] = useState(false);
114+
const [registeredEmail, setRegisteredEmail] = useState('');
92115
const { setIsActive: setShowProgress } = useProgress();
93116
const router = useIonRouter();
94117
const { signUp, isLoading: isSignUpLoading } = useSignUp();
@@ -124,6 +147,13 @@ const SignUpForm = ({ className, testid = 'form-signup' }: SignUpFormProps): JSX
124147
focusInput.current?.setFocus();
125148
});
126149

150+
// Redirect to verification page after showing success message
151+
const handleRedirectAfterSuccess = () => {
152+
setTimeout(() => {
153+
router.push('/auth/verify', 'forward', 'replace');
154+
}, 3000); // Show success message for 3 seconds before redirecting
155+
};
156+
127157
return (
128158
<div className={classNames('ls-signup-form', className)} data-testid={testid}>
129159
<AuthErrorDisplay
@@ -139,133 +169,139 @@ const SignUpForm = ({ className, testid = 'form-signup' }: SignUpFormProps): JSX
139169
testid={`${testid}-loading`}
140170
/>
141171

142-
<Formik<SignUpFormValues>
143-
initialValues={{
144-
email: '',
145-
firstName: '',
146-
lastName: '',
147-
password: '',
148-
confirmPassword: '',
149-
}}
150-
onSubmit={async (values, { setSubmitting }) => {
151-
try {
152-
setError(null);
153-
setIsLoading(true);
154-
setShowProgress(true);
155-
await signUp(values.email, values.password, values.firstName, values.lastName);
172+
{registrationSuccess ? (
173+
<RegistrationSuccess email={registeredEmail} />
174+
) : (
175+
<Formik<SignUpFormValues>
176+
initialValues={{
177+
email: '',
178+
firstName: '',
179+
lastName: '',
180+
password: '',
181+
confirmPassword: '',
182+
}}
183+
onSubmit={async (values, { setSubmitting }) => {
184+
try {
185+
setError(null);
186+
setIsLoading(true);
187+
setShowProgress(true);
188+
await signUp(values.email, values.password, values.firstName, values.lastName);
156189

157-
// Store the email in sessionStorage for the verification page
158-
sessionStorage.setItem('verification_email', values.email);
190+
// Store the email in sessionStorage for the verification page
191+
sessionStorage.setItem('verification_email', values.email);
159192

160-
// Show success briefly before redirecting
161-
setIsLoading(false);
193+
// Show success message
194+
setIsLoading(false);
195+
setRegisteredEmail(values.email);
196+
setRegistrationSuccess(true);
162197

163-
// Navigate to verification page
164-
router.push('/auth/verify', 'forward', 'replace');
165-
} catch (err) {
166-
setError(formatAuthError(err));
167-
} finally {
168-
setShowProgress(false);
169-
setSubmitting(false);
170-
setIsLoading(false);
171-
}
172-
}}
173-
validationSchema={validationSchema}
174-
>
175-
{({ dirty, isSubmitting, isValid }) => (
176-
<Form data-testid={`${testid}-form`}>
177-
<div className="ls-signup-form__content">
178-
<h2 className="ls-signup-form__title">{t('signup', { ns: 'auth' })}</h2>
179-
<p className="ls-signup-form__subtitle">
180-
{t('please-fill-details', {
181-
ns: 'auth',
182-
defaultValue: 'Please fill in your personal details',
183-
})}
184-
</p>
198+
// Redirect after showing success message
199+
handleRedirectAfterSuccess();
200+
} catch (err) {
201+
setError(formatAuthError(err));
202+
} finally {
203+
setShowProgress(false);
204+
setSubmitting(false);
205+
setIsLoading(false);
206+
}
207+
}}
208+
validationSchema={validationSchema}
209+
>
210+
{({ dirty, isSubmitting, isValid }) => (
211+
<Form data-testid={`${testid}-form`}>
212+
<div className="ls-signup-form__content">
213+
<h2 className="ls-signup-form__title">{t('signup', { ns: 'auth' })}</h2>
214+
<p className="ls-signup-form__subtitle">
215+
{t('please-fill-details', {
216+
ns: 'auth',
217+
defaultValue: 'Please fill in your personal details',
218+
})}
219+
</p>
185220

186-
<Input
187-
name="firstName"
188-
label={t('label.first-name', { ns: 'auth' })}
189-
labelPlacement="stacked"
190-
maxlength={50}
191-
autocomplete="given-name"
192-
className="ls-signup-form__input"
193-
data-testid={`${testid}-field-first-name`}
194-
/>
221+
<Input
222+
name="firstName"
223+
label={t('label.first-name', { ns: 'auth' })}
224+
labelPlacement="stacked"
225+
maxlength={50}
226+
autocomplete="given-name"
227+
className="ls-signup-form__input"
228+
data-testid={`${testid}-field-first-name`}
229+
/>
195230

196-
<Input
197-
name="lastName"
198-
label={t('label.last-name', { ns: 'auth' })}
199-
labelPlacement="stacked"
200-
maxlength={50}
201-
autocomplete="family-name"
202-
className="ls-signup-form__input"
203-
data-testid={`${testid}-field-last-name`}
204-
/>
231+
<Input
232+
name="lastName"
233+
label={t('label.last-name', { ns: 'auth' })}
234+
labelPlacement="stacked"
235+
maxlength={50}
236+
autocomplete="family-name"
237+
className="ls-signup-form__input"
238+
data-testid={`${testid}-field-last-name`}
239+
/>
205240

206-
<Input
207-
name="email"
208-
label={t('label.email', { ns: 'auth' })}
209-
labelPlacement="stacked"
210-
maxlength={50}
211-
autocomplete="email"
212-
className="ls-signup-form__input"
213-
ref={focusInput}
214-
data-testid={`${testid}-field-email`}
215-
type="email"
216-
/>
241+
<Input
242+
name="email"
243+
label={t('label.email', { ns: 'auth' })}
244+
labelPlacement="stacked"
245+
maxlength={50}
246+
autocomplete="email"
247+
className="ls-signup-form__input"
248+
ref={focusInput}
249+
data-testid={`${testid}-field-email`}
250+
type="email"
251+
/>
217252

218-
<Input
219-
type="password"
220-
name="password"
221-
label={t('label.password', { ns: 'auth' })}
222-
labelPlacement="stacked"
223-
maxlength={30}
224-
autocomplete="new-password"
225-
className="ls-signup-form__input"
226-
data-testid={`${testid}-field-password`}
227-
>
228-
<IonInputPasswordToggle slot="end"></IonInputPasswordToggle>
229-
</Input>
253+
<Input
254+
type="password"
255+
name="password"
256+
label={t('label.password', { ns: 'auth' })}
257+
labelPlacement="stacked"
258+
maxlength={30}
259+
autocomplete="new-password"
260+
className="ls-signup-form__input"
261+
data-testid={`${testid}-field-password`}
262+
>
263+
<IonInputPasswordToggle slot="end"></IonInputPasswordToggle>
264+
</Input>
230265

231-
<Input
232-
type="password"
233-
name="confirmPassword"
234-
label={t('label.confirm-password', { ns: 'auth' })}
235-
labelPlacement="stacked"
236-
maxlength={30}
237-
autocomplete="new-password"
238-
className="ls-signup-form__input"
239-
data-testid={`${testid}-field-confirm-password`}
240-
>
241-
<IonInputPasswordToggle slot="end"></IonInputPasswordToggle>
242-
</Input>
266+
<Input
267+
type="password"
268+
name="confirmPassword"
269+
label={t('label.confirm-password', { ns: 'auth' })}
270+
labelPlacement="stacked"
271+
maxlength={30}
272+
autocomplete="new-password"
273+
className="ls-signup-form__input"
274+
data-testid={`${testid}-field-confirm-password`}
275+
>
276+
<IonInputPasswordToggle slot="end"></IonInputPasswordToggle>
277+
</Input>
243278

244-
<PasswordGuidelines />
279+
<PasswordGuidelines />
245280

246-
<IonButton
247-
type="submit"
248-
color="primary"
249-
className="ls-signup-form__button"
250-
expand="block"
251-
disabled={isSubmitting || !isValid || !dirty || isSignUpLoading || isLoading}
252-
data-testid={`${testid}-button-submit`}
253-
>
254-
{t('signup.button', { ns: 'auth' })}
255-
</IonButton>
281+
<IonButton
282+
type="submit"
283+
color="primary"
284+
className="ls-signup-form__button"
285+
expand="block"
286+
disabled={isSubmitting || !isValid || !dirty || isSignUpLoading || isLoading}
287+
data-testid={`${testid}-button-submit`}
288+
>
289+
{t('signup.button', { ns: 'auth' })}
290+
</IonButton>
256291

257-
<IonRow className="ion-text-center ion-padding-top">
258-
<IonCol>
259-
<IonText color="medium">
260-
{t('already-have-account', { ns: 'auth' })}{' '}
261-
<a href="/auth/signin">{t('signin', { ns: 'auth' })}</a>
262-
</IonText>
263-
</IonCol>
264-
</IonRow>
265-
</div>
266-
</Form>
267-
)}
268-
</Formik>
292+
<IonRow className="ion-text-center ion-padding-top">
293+
<IonCol>
294+
<IonText color="medium">
295+
{t('already-have-account', { ns: 'auth' })}{' '}
296+
<a href="/auth/signin">{t('signin', { ns: 'auth' })}</a>
297+
</IonText>
298+
</IonCol>
299+
</IonRow>
300+
</div>
301+
</Form>
302+
)}
303+
</Formik>
304+
)}
269305
</div>
270306
);
271307
};

0 commit comments

Comments
 (0)