diff --git a/frontend/src/common/i18n/en/auth.json b/frontend/src/common/i18n/en/auth.json
new file mode 100644
index 00000000..20e163e2
--- /dev/null
+++ b/frontend/src/common/i18n/en/auth.json
@@ -0,0 +1,35 @@
+{
+ "email-verification": {
+ "title": "Email Verification",
+ "message": "Please enter the verification code sent to your email address.",
+ "success": "Your email has been successfully verified.",
+ "code-resent": "A new verification code has been sent to your email."
+ },
+ "validation": {
+ "required": "This field is required.",
+ "numeric": "This field must contain only numbers.",
+ "exact-length": "This field must be exactly {{length}} characters."
+ },
+ "error": {
+ "no-email": "Email address not found. Please try again."
+ },
+ "label": {
+ "verification-code": "Verification code",
+ "email": "Email"
+ },
+ "confirm": "Confirm",
+ "resend-code": "Request new code",
+ "verification": {
+ "loading": "Verifying your code...",
+ "enter-code": "Please enter the verification code we sent to"
+ },
+ "confirm-account": {
+ "title": "Confirm Account",
+ "message": "Please enter the verification code we sent to",
+ "submit": "Confirm Account"
+ },
+ "request-new-code": "Request new code",
+ "back-to-login": "Back to Log in",
+ "signin": "Log in",
+ "logo-alt": "MEDReport AI Logo"
+}
diff --git a/frontend/src/common/i18n/en/common.json b/frontend/src/common/i18n/en/common.json
new file mode 100644
index 00000000..755daef9
--- /dev/null
+++ b/frontend/src/common/i18n/en/common.json
@@ -0,0 +1,13 @@
+{
+ "logo-alt": "MEDReport AI Logo",
+ "app": {
+ "name": "MEDReport AI"
+ },
+ "confirm": "Confirm",
+ "cancel": "Cancel",
+ "loading": "Loading...",
+ "error": "Error",
+ "success": "Success",
+ "back": "Back",
+ "next": "Next"
+}
diff --git a/frontend/src/common/utils/i18n/resources/en/auth.json b/frontend/src/common/utils/i18n/resources/en/auth.json
index 27fcb35e..b2f41e63 100644
--- a/frontend/src/common/utils/i18n/resources/en/auth.json
+++ b/frontend/src/common/utils/i18n/resources/en/auth.json
@@ -41,7 +41,7 @@
"or-signin-with": "Or sign in with",
"submit": "Submit",
"confirm": "Confirm",
- "resend-code": "Resend Code",
+ "resend-code": "Request new code",
"forgot-password": "Forgot Password?",
"password-recovery": {
"title": "Password Recovery",
@@ -62,6 +62,16 @@
"success": "Email verified successfully!",
"code-resent": "A new verification code has been sent to your email."
},
+ "confirm-account": {
+ "title": "Confirm Account",
+ "message": "Please enter the verification code we sent to",
+ "submit": "Confirm Account"
+ },
+ "back-to-login": "Back to Log in",
+ "registration": {
+ "success": "Registration successful!",
+ "verify-email": "Please verify your email to activate your account."
+ },
"oauth": {
"processing": "Processing your login...",
"redirecting": "Redirecting...",
@@ -80,5 +90,6 @@
"uppercase": "Must contain at least one uppercase letter",
"number": "Must contain at least one number",
"special-char": "Must contain at least one special character"
- }
+ },
+ "please-fill-details": "Please fill in your personal details"
}
diff --git a/frontend/src/common/utils/i18n/resources/es/auth.json b/frontend/src/common/utils/i18n/resources/es/auth.json
index 350ad8b8..8695f245 100644
--- a/frontend/src/common/utils/i18n/resources/es/auth.json
+++ b/frontend/src/common/utils/i18n/resources/es/auth.json
@@ -16,5 +16,10 @@
},
"signin": "Iniciar sesión",
"signin.title": "Iniciar sesión",
- "signin.subtitle": "Iniciar sesión para acceder a MEDReport AI"
+ "signin.subtitle": "Iniciar sesión para acceder a MEDReport AI",
+ "registration": {
+ "success": "¡Registro exitoso!",
+ "verify-email": "Por favor verifica tu correo electrónico para activar tu cuenta."
+ },
+ "please-fill-details": "Por favor complete sus datos personales"
}
diff --git a/frontend/src/common/utils/i18n/resources/fr/auth.json b/frontend/src/common/utils/i18n/resources/fr/auth.json
index 11a4abfe..99fa750d 100644
--- a/frontend/src/common/utils/i18n/resources/fr/auth.json
+++ b/frontend/src/common/utils/i18n/resources/fr/auth.json
@@ -16,5 +16,10 @@
},
"signin": "Se connecter",
"signin.title": "Se connecter",
- "signin.subtitle": "Connectez-vous pour accéder à MEDReport AI"
+ "signin.subtitle": "Connectez-vous pour accéder à MEDReport AI",
+ "registration": {
+ "success": "Inscription réussie !",
+ "verify-email": "Veuillez vérifier votre e-mail pour activer votre compte."
+ },
+ "please-fill-details": "Veuillez remplir vos coordonnées personnelles"
}
diff --git a/frontend/src/pages/Auth/SignUp/components/SignUpForm.scss b/frontend/src/pages/Auth/SignUp/components/SignUpForm.scss
index c6d0ffdc..9c5e723a 100644
--- a/frontend/src/pages/Auth/SignUp/components/SignUpForm.scss
+++ b/frontend/src/pages/Auth/SignUp/components/SignUpForm.scss
@@ -82,9 +82,10 @@
&-icon {
margin-right: 0.375rem;
font-size: 1.1rem;
+ color: var(--ion-color-medium);
}
- &-valid {
+ &.valid {
color: var(--ion-color-success);
}
@@ -93,4 +94,37 @@
}
}
}
+
+ &__success {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ padding: 2rem 1.5rem;
+ background-color: #f8fff8;
+ border: 1px solid var(--ion-color-success);
+ border-radius: 8px;
+ margin: 1rem 0;
+
+ &-icon {
+ font-size: 4rem;
+ margin-bottom: 1rem;
+ }
+
+ h3 {
+ font-size: 1.4rem;
+ font-weight: 600;
+ margin: 0 0 0.75rem;
+ color: var(--ion-color-success);
+ }
+
+ p {
+ font-size: 1rem;
+ margin: 0;
+ color: #666;
+ line-height: 1.5;
+ max-width: 320px;
+ }
+ }
}
diff --git a/frontend/src/pages/Auth/SignUp/components/SignUpForm.tsx b/frontend/src/pages/Auth/SignUp/components/SignUpForm.tsx
index 50291afa..4620502c 100644
--- a/frontend/src/pages/Auth/SignUp/components/SignUpForm.tsx
+++ b/frontend/src/pages/Auth/SignUp/components/SignUpForm.tsx
@@ -13,7 +13,7 @@ import classNames from 'classnames';
import { Form, Formik, useFormikContext } from 'formik';
import { object, string, ref } from 'yup';
import { useTranslation } from 'react-i18next';
-import { checkmarkCircle, ellipseOutline } from 'ionicons/icons';
+import { checkmarkCircle, checkmarkCircleOutline } from 'ionicons/icons';
import './SignUpForm.scss';
import { BaseComponentProps } from 'common/components/types';
@@ -41,6 +41,27 @@ interface SignUpFormValues {
confirmPassword: string;
}
+/**
+ * Registration success message component
+ */
+const RegistrationSuccess = ({ email }: { email: string }) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
{t('registration.success', { ns: 'auth' })}
+
+ {t('registration.verify-email', {
+ ns: 'auth',
+ email,
+ defaultValue: 'Please verify your email to activate your account.',
+ })}
+
+
+ );
+};
+
/**
* Password guidelines component
*/
@@ -62,7 +83,7 @@ const PasswordGuidelines = () => {
}`}
>
{text}
@@ -89,6 +110,8 @@ const SignUpForm = ({ className, testid = 'form-signup' }: SignUpFormProps): JSX
const focusInput = useRef(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
+ const [registrationSuccess, setRegistrationSuccess] = useState(false);
+ const [registeredEmail, setRegisteredEmail] = useState('');
const { setIsActive: setShowProgress } = useProgress();
const router = useIonRouter();
const { signUp, isLoading: isSignUpLoading } = useSignUp();
@@ -124,6 +147,13 @@ const SignUpForm = ({ className, testid = 'form-signup' }: SignUpFormProps): JSX
focusInput.current?.setFocus();
});
+ // Redirect to verification page after showing success message
+ const handleRedirectAfterSuccess = () => {
+ setTimeout(() => {
+ router.push('/auth/verify', 'forward', 'replace');
+ }, 3000); // Show success message for 3 seconds before redirecting
+ };
+
return (
-
- initialValues={{
- email: '',
- firstName: '',
- lastName: '',
- password: '',
- confirmPassword: '',
- }}
- onSubmit={async (values, { setSubmitting }) => {
- try {
- setError(null);
- setIsLoading(true);
- setShowProgress(true);
- await signUp(values.email, values.password, values.firstName, values.lastName);
+ {registrationSuccess ? (
+
+ ) : (
+
+ initialValues={{
+ email: '',
+ firstName: '',
+ lastName: '',
+ password: '',
+ confirmPassword: '',
+ }}
+ onSubmit={async (values, { setSubmitting }) => {
+ try {
+ setError(null);
+ setIsLoading(true);
+ setShowProgress(true);
+ await signUp(values.email, values.password, values.firstName, values.lastName);
- // Store the email in sessionStorage for the verification page
- sessionStorage.setItem('verification_email', values.email);
+ // Store the email in sessionStorage for the verification page
+ sessionStorage.setItem('verification_email', values.email);
- // Show success briefly before redirecting
- setIsLoading(false);
+ // Show success message
+ setIsLoading(false);
+ setRegisteredEmail(values.email);
+ setRegistrationSuccess(true);
- // Navigate to verification page
- router.push('/auth/verify', 'forward', 'replace');
- } catch (err) {
- setError(formatAuthError(err));
- } finally {
- setShowProgress(false);
- setSubmitting(false);
- setIsLoading(false);
- }
- }}
- validationSchema={validationSchema}
- >
- {({ dirty, isSubmitting, isValid }) => (
-
+ )}
+
+ )}
);
};
diff --git a/frontend/src/pages/Auth/Verify/VerificationPage.scss b/frontend/src/pages/Auth/Verify/VerificationPage.scss
index b304a641..df188d80 100644
--- a/frontend/src/pages/Auth/Verify/VerificationPage.scss
+++ b/frontend/src/pages/Auth/Verify/VerificationPage.scss
@@ -1,13 +1,53 @@
.ls-verification-page {
- .ls-verification-page__container {
- max-width: 32rem;
+ --ion-background-color: transparent;
+
+ &__background {
+ width: 100%;
height: 100%;
display: flex;
flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+ padding: 2rem 1.5rem;
+ background-color: #1c1e2e;
+ background-image: url('../../../assets/Splash.png');
+ background-size: cover;
+ background-position: center;
+ position: relative;
+ }
+
+ &__logo-container {
+ display: flex;
+ align-items: center;
justify-content: center;
+ margin-bottom: 2.5rem;
+ margin-top: 2rem;
+ }
+
+ &__logo {
+ width: 3.5rem;
+ height: auto;
+ margin-right: 0.75rem;
+ }
+
+ &__logo-text {
+ color: white;
+ font-size: 1.75rem;
+ font-weight: 600;
+ }
+
+ &__card {
+ width: 100%;
+ max-width: 30rem;
+ background-color: white;
+ border-radius: 1.5rem;
+ padding: 2.5rem 2rem;
+ box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 15%);
+ z-index: 1;
}
- .ls-verification-page__form {
+ &__form {
width: 100%;
+ margin: 0;
}
}
diff --git a/frontend/src/pages/Auth/Verify/VerificationPage.tsx b/frontend/src/pages/Auth/Verify/VerificationPage.tsx
index 9aa331a1..c54d847a 100644
--- a/frontend/src/pages/Auth/Verify/VerificationPage.tsx
+++ b/frontend/src/pages/Auth/Verify/VerificationPage.tsx
@@ -1,13 +1,12 @@
-import { IonContent, IonPage } from '@ionic/react';
+import { IonContent, IonPage, IonImg } from '@ionic/react';
import { useTranslation } from 'react-i18next';
import { useEffect, useState } from 'react';
import './VerificationPage.scss';
import { PropsWithTestId } from 'common/components/types';
import ProgressProvider from 'common/providers/ProgressProvider';
-import Header from 'common/components/Header/Header';
import VerificationForm from './components/VerificationForm';
-import Container from 'common/components/Content/Container';
+import logo from '../../../assets/logo_ls.png';
/**
* Properties for the `VerificationPage` component.
@@ -34,12 +33,23 @@ const VerificationPage = ({ testid = 'page-verification' }: VerificationPageProp
return (
-
+
+
+
+
+
+ {t('app.name', { ns: 'common' })}
+
+
-
-
-
-
+
+
+
+
diff --git a/frontend/src/pages/Auth/Verify/components/VerificationForm.scss b/frontend/src/pages/Auth/Verify/components/VerificationForm.scss
index 6f03a82d..575cef2e 100644
--- a/frontend/src/pages/Auth/Verify/components/VerificationForm.scss
+++ b/frontend/src/pages/Auth/Verify/components/VerificationForm.scss
@@ -1,34 +1,53 @@
.ls-verification-form {
- padding: 1rem;
+ width: 100%;
- .ls-verification-form__message {
- margin: 1rem 0;
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
+ .ls-verification-form__title {
+ font-size: 2rem;
+ font-weight: 600;
+ color: #333;
+ margin-bottom: 1.25rem;
+ margin-top: 0;
+ text-align: center;
}
- .ls-verification-form__email {
- display: block;
- margin-top: 0.5rem;
+ .ls-verification-form__message {
+ margin: 1rem 0 1.5rem;
+ text-align: center;
+ color: #666;
+ font-size: 1rem;
+ line-height: 1.5;
}
.ls-verification-form__input {
- margin-bottom: 1rem;
+ margin-bottom: 1.5rem;
}
.ls-verification-form__button {
margin-top: 1rem;
+ margin-bottom: 0.75rem;
+ height: 3rem;
+ font-weight: 500;
+
+ --border-radius: 0.75rem;
+ }
+
+ .ls-verification-form__resend-button {
+ margin-bottom: 1.5rem;
+ height: 3rem;
+ font-weight: 500;
+
+ --border-radius: 0.75rem;
}
- .ls-verification-form__resend {
+ .ls-verification-form__back-link {
display: flex;
justify-content: center;
margin-top: 1rem;
+ font-size: 0.9rem;
}
.ls-verification-form__success {
- background-color: rgba(45, 211, 111, 0.1);
+ background-color: rgb(45 211 111 / 10%);
border-radius: 8px;
padding: 12px;
margin-bottom: 1rem;
diff --git a/frontend/src/pages/Auth/Verify/components/VerificationForm.tsx b/frontend/src/pages/Auth/Verify/components/VerificationForm.tsx
index 8620d344..231d788e 100644
--- a/frontend/src/pages/Auth/Verify/components/VerificationForm.tsx
+++ b/frontend/src/pages/Auth/Verify/components/VerificationForm.tsx
@@ -11,7 +11,6 @@ import { AuthError } from 'common/models/auth';
import { useAuth } from 'common/hooks/useAuth';
import { useProgress } from 'common/hooks/useProgress';
import Input from 'common/components/Input/Input';
-import HeaderRow from 'common/components/Text/HeaderRow';
import { formatAuthError } from 'common/utils/auth-errors';
import AuthErrorDisplay from 'common/components/Auth/AuthErrorDisplay';
import AuthLoadingIndicator from 'common/components/Auth/AuthLoadingIndicator';
@@ -152,17 +151,14 @@ const VerificationForm = ({
>
{({ dirty, isSubmitting }) => (