From d703ccfd80a4cd56ef7928dd6a0ab5017eb9cb32 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Sun, 1 Feb 2026 12:44:28 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(auth):=20add=20resend=20verifi?= =?UTF-8?q?cation=20email=20to=20registration=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add prominent email verification success UI with resend button - Show resend verification option when registration fails with "not verified" error - Improve form spacing with space-y-4 for better visual consistency - Add translations for resend verification in all languages (de, en, fr, it, es) - Update all 13 app register pages to pass onResendVerification prop Co-Authored-By: Claude Opus 4.5 --- .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../web/src/routes/auth/signup/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../apps/web/src/routes/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/routes/(auth)/register/+page.svelte | 5 + .../src/pages/RegisterPage.svelte | 155 ++++++++++++++++-- .../shared-i18n/src/translations/auth/de.json | 6 +- .../shared-i18n/src/translations/auth/en.json | 6 +- .../shared-i18n/src/translations/auth/es.json | 6 +- .../shared-i18n/src/translations/auth/fr.json | 6 +- .../src/translations/auth/index.ts | 4 + .../shared-i18n/src/translations/auth/it.json | 6 +- 20 files changed, 236 insertions(+), 18 deletions(-) diff --git a/apps/calendar/apps/web/src/routes/(auth)/register/+page.svelte b/apps/calendar/apps/web/src/routes/(auth)/register/+page.svelte index c344b4f5c..0c4682bb3 100644 --- a/apps/calendar/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/calendar/apps/web/src/routes/(auth)/register/+page.svelte @@ -29,6 +29,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -40,6 +44,7 @@ logo={CalendarLogo} primaryColor="#0ea5e9" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/chat/apps/web/src/routes/(auth)/register/+page.svelte b/apps/chat/apps/web/src/routes/(auth)/register/+page.svelte index ad70a98e7..b25959b0c 100644 --- a/apps/chat/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/chat/apps/web/src/routes/(auth)/register/+page.svelte @@ -29,6 +29,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -40,6 +44,7 @@ logo={ChatLogo} primaryColor="#0ea5e9" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/contacts/apps/web/src/routes/(auth)/register/+page.svelte b/apps/contacts/apps/web/src/routes/(auth)/register/+page.svelte index c458b5ebe..3f3275247 100644 --- a/apps/contacts/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/contacts/apps/web/src/routes/(auth)/register/+page.svelte @@ -26,6 +26,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -37,6 +41,7 @@ logo={ContactsLogo} primaryColor="#3b82f6" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/manacore/apps/web/src/routes/(auth)/register/+page.svelte b/apps/manacore/apps/web/src/routes/(auth)/register/+page.svelte index 71979b19e..555be440d 100644 --- a/apps/manacore/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(auth)/register/+page.svelte @@ -16,6 +16,10 @@ async function handleValidateReferralCode(code: string) { return authStore.validateReferralCode(code); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -34,6 +38,7 @@ logo={NutriPhiLogo} primaryColor="#22C55E" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/picture/apps/web/src/routes/auth/signup/+page.svelte b/apps/picture/apps/web/src/routes/auth/signup/+page.svelte index 1d12583eb..553f8142a 100644 --- a/apps/picture/apps/web/src/routes/auth/signup/+page.svelte +++ b/apps/picture/apps/web/src/routes/auth/signup/+page.svelte @@ -11,6 +11,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -22,6 +26,7 @@ logo={PictureLogo} primaryColor="#3b82f6" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect="/app/gallery" loginPath="/auth/login" diff --git a/apps/presi/apps/web/src/routes/(auth)/register/+page.svelte b/apps/presi/apps/web/src/routes/(auth)/register/+page.svelte index 6c76ec2ae..95be5a79e 100644 --- a/apps/presi/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/presi/apps/web/src/routes/(auth)/register/+page.svelte @@ -15,6 +15,10 @@ async function handleSignUp(email: string, password: string) { return auth.register(email, password); } + + async function handleResendVerification(email: string) { + return auth.resendVerificationEmail(email); + } @@ -26,6 +30,7 @@ logo={PresiLogo} primaryColor="#f97316" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect="/" loginPath="/login" diff --git a/apps/questions/apps/web/src/routes/(auth)/register/+page.svelte b/apps/questions/apps/web/src/routes/(auth)/register/+page.svelte index 0cc35bc43..a7b0d6ed4 100644 --- a/apps/questions/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/questions/apps/web/src/routes/(auth)/register/+page.svelte @@ -24,6 +24,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -35,6 +39,7 @@ logo={QuestionsLogo} primaryColor="#8b5cf6" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/skilltree/apps/web/src/routes/(auth)/register/+page.svelte b/apps/skilltree/apps/web/src/routes/(auth)/register/+page.svelte index fb574eedd..c17e71aaf 100644 --- a/apps/skilltree/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/skilltree/apps/web/src/routes/(auth)/register/+page.svelte @@ -24,6 +24,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -35,6 +39,7 @@ logo={SkillTreeLogo} primaryColor="#10b981" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/storage/apps/web/src/routes/register/+page.svelte b/apps/storage/apps/web/src/routes/register/+page.svelte index 431ad3302..8e40175e5 100644 --- a/apps/storage/apps/web/src/routes/register/+page.svelte +++ b/apps/storage/apps/web/src/routes/register/+page.svelte @@ -13,6 +13,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -24,6 +28,7 @@ logo={ManaIcon} primaryColor="#3b82f6" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect="/files" loginPath="/login" diff --git a/apps/todo/apps/web/src/routes/(auth)/register/+page.svelte b/apps/todo/apps/web/src/routes/(auth)/register/+page.svelte index 76e1393c2..80d822840 100644 --- a/apps/todo/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/todo/apps/web/src/routes/(auth)/register/+page.svelte @@ -28,6 +28,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -39,6 +43,7 @@ logo={TodoLogo} primaryColor="#8b5cf6" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect={redirectTo} loginPath="/login" diff --git a/apps/zitare/apps/web/src/routes/(auth)/register/+page.svelte b/apps/zitare/apps/web/src/routes/(auth)/register/+page.svelte index 6e46f40a0..8095c1057 100644 --- a/apps/zitare/apps/web/src/routes/(auth)/register/+page.svelte +++ b/apps/zitare/apps/web/src/routes/(auth)/register/+page.svelte @@ -13,6 +13,10 @@ async function handleSignUp(email: string, password: string) { return authStore.signUp(email, password); } + + async function handleResendVerification(email: string) { + return authStore.resendVerificationEmail(email); + } @@ -24,6 +28,7 @@ logo={ZitareLogo} primaryColor="#f59e0b" onSignUp={handleSignUp} + onResendVerification={handleResendVerification} {goto} successRedirect="/" loginPath="/login" diff --git a/packages/shared-auth-ui/src/pages/RegisterPage.svelte b/packages/shared-auth-ui/src/pages/RegisterPage.svelte index 688337dd8..2b1453443 100644 --- a/packages/shared-auth-ui/src/pages/RegisterPage.svelte +++ b/packages/shared-auth-ui/src/pages/RegisterPage.svelte @@ -33,6 +33,11 @@ registrationFailed: string; // Success messages accountCreated: string; + // Verification resend + resendVerification?: string; + resendingVerification?: string; + verificationEmailSent?: string; + checkYourEmail?: string; } /** Referral code validation result */ @@ -72,6 +77,11 @@ 'Password must include lowercase, uppercase, number, and special character', registrationFailed: 'Registration failed', accountCreated: 'Account created! Please check your email to verify your account.', + // Verification resend + resendVerification: 'Resend verification email', + resendingVerification: 'Sending...', + verificationEmailSent: 'Verification email sent! Please check your inbox.', + checkYourEmail: 'Check your email', }; interface Props { @@ -85,6 +95,8 @@ onSignUp: (email: string, password: string, referralCode?: string) => Promise; /** Navigation function */ goto: (path: string) => void; + /** Resend verification email function */ + onResendVerification?: (email: string) => Promise; /** Success redirect path */ successRedirect?: string; /** Login page path */ @@ -113,6 +125,7 @@ primaryColor, onSignUp, goto, + onResendVerification, successRedirect = '/dashboard', loginPath = '/login', lightBackground = '#f5f5f5', @@ -137,6 +150,8 @@ let confirmPassword = $state(''); let showPassword = $state(false); let showConfirmPassword = $state(false); + let resendingVerification = $state(false); + let verificationEmailSent = $state(false); // Referral state let referralCode = $state(initialReferralCode); @@ -310,6 +325,22 @@ error = result.error || t.registrationFailed; } } + + async function handleResendVerification() { + if (!onResendVerification || !email || resendingVerification) return; + + resendingVerification = true; + error = null; + + const result = await onResendVerification(email); + resendingVerification = false; + + if (result.success) { + verificationEmailSent = true; + } else { + error = result.error || t.registrationFailed; + } + } @@ -390,24 +421,122 @@ {/if} - - {#if success && needsVerification} -
-

- {t.accountCreated} + + {#if verificationEmailSent} +

+

+ {t.verificationEmailSent}

{/if} + + {#if success && needsVerification} +
+
+
+ + + +
+
+

+ {t.checkYourEmail || 'Check your email'} +

+

+ {t.accountCreated} +

+
+
+ + {#if onResendVerification} +
+

+ Didn't receive the email? +

+ +
+ {/if} +
+ {/if} +
{ e.preventDefault(); handleRegister(); }} - class="pb-4" + class="space-y-4" > -
+
-
+
-
+

{t.passwordRequirements}

{#if onValidateReferralCode} -
+