diff --git a/backend/src/main/java/org/raddatz/familienarchiv/dto/RegisterRequest.java b/backend/src/main/java/org/raddatz/familienarchiv/dto/RegisterRequest.java index 9401943a..c715670f 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/dto/RegisterRequest.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/dto/RegisterRequest.java @@ -15,4 +15,5 @@ public class RegisterRequest { private String password; private String firstName; private String lastName; + private boolean notifyOnMention = true; } diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/InviteService.java b/backend/src/main/java/org/raddatz/familienarchiv/service/InviteService.java index acbf49bc..79c19703 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/InviteService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/InviteService.java @@ -91,6 +91,8 @@ public class InviteService { token.getGroupIds() ); + userService.updateNotificationPreferences(user.getId(), dto.isNotifyOnMention(), dto.isNotifyOnMention()); + token.setUseCount(token.getUseCount() + 1); inviteTokenRepository.save(token); diff --git a/frontend/.gitignore b/frontend/.gitignore index 5b5d80b6..b05dec47 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -34,3 +34,8 @@ src/lib/paraglide_bak* # Playwright auth state — regenerated at the start of each CI run via auth.setup.ts e2e/.auth/ + +**/test-results/** + +# Proofshot browser verification artifacts +proofshot-artifacts/ diff --git a/frontend/messages/de.json b/frontend/messages/de.json index 49f631fb..3635270a 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -658,6 +658,22 @@ "register_invalid_code": "Ungültiger Einladungslink", "register_invalid_code_desc": "Dieser Einladungslink ist nicht gültig, wurde bereits verwendet oder ist abgelaufen. Bitte wende dich an den Administrator.", "register_success": "Dein Konto wurde erfolgreich erstellt. Du kannst dich jetzt anmelden.", + "register_eyebrow": "Ein Familienprojekt", + "register_hero_headline": "Schön, dass du da bist.", + "register_hero_subtext": "Gemeinsam bewahren wir Briefe und Dokumente – für die Familie, jetzt und in Zukunft.", + "register_section_about": "Über dich", + "register_section_account": "Konto", + "register_section_notifications": "Benachrichtigungen", + "register_label_password_confirm": "Passwort bestätigen", + "register_pw_hint": "Mindestens 8 Zeichen.", + "register_pw_ok": "Mindestens 8 Zeichen. ✓", + "register_pw_match_ok": "Passwörter stimmen überein.", + "register_pw_match_no": "Die beiden Passwörter stimmen noch nicht überein.", + "register_notify_title": "Benachrichtige mich,", + "register_notify_desc": "wenn jemand mich in einem Kommentar erwähnt oder mir auf einen Kommentar antwortet.", + "register_btn_loading": "Wird erstellt …", + "register_already_have_account": "Du hast bereits ein Konto?", + "register_sign_in": "Anmelden", "login_registered_success": "Dein Konto wurde erfolgreich erstellt. Melde dich jetzt an.", "admin_tab_invites": "Einladungen", "admin_invites_list_title": "Einladungen", diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 42bda41f..a05ce326 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -658,6 +658,22 @@ "register_invalid_code": "Invalid invite link", "register_invalid_code_desc": "This invite link is not valid, has already been used, or has expired. Please contact the administrator.", "register_success": "Your account has been created. You can now sign in.", + "register_eyebrow": "A family project", + "register_hero_headline": "Glad you're here.", + "register_hero_subtext": "Together we preserve letters and documents – for the family, now and in the future.", + "register_section_about": "About you", + "register_section_account": "Account", + "register_section_notifications": "Notifications", + "register_label_password_confirm": "Confirm password", + "register_pw_hint": "At least 8 characters.", + "register_pw_ok": "At least 8 characters. ✓", + "register_pw_match_ok": "Passwords match.", + "register_pw_match_no": "The two passwords don't match yet.", + "register_notify_title": "Notify me", + "register_notify_desc": "when someone mentions me in a comment or replies to one of my comments.", + "register_btn_loading": "Creating …", + "register_already_have_account": "Already have an account?", + "register_sign_in": "Sign in", "login_registered_success": "Your account was created successfully. Sign in now.", "admin_tab_invites": "Invites", "admin_invites_list_title": "Invites", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index ca9750dc..93c4d870 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -658,6 +658,22 @@ "register_invalid_code": "Enlace de invitación inválido", "register_invalid_code_desc": "Este enlace de invitación no es válido, ya ha sido utilizado o ha expirado. Contacta al administrador.", "register_success": "Tu cuenta ha sido creada. Ahora puedes iniciar sesión.", + "register_eyebrow": "Un proyecto familiar", + "register_hero_headline": "Qué bueno que estés aquí.", + "register_hero_subtext": "Juntos conservamos cartas y documentos – para la familia, ahora y en el futuro.", + "register_section_about": "Sobre ti", + "register_section_account": "Cuenta", + "register_section_notifications": "Notificaciones", + "register_label_password_confirm": "Confirmar contraseña", + "register_pw_hint": "Al menos 8 caracteres.", + "register_pw_ok": "Al menos 8 caracteres. ✓", + "register_pw_match_ok": "Las contraseñas coinciden.", + "register_pw_match_no": "Las dos contraseñas aún no coinciden.", + "register_notify_title": "Notifícame", + "register_notify_desc": "cuando alguien me mencione en un comentario o responda a uno de mis comentarios.", + "register_btn_loading": "Creando …", + "register_already_have_account": "¿Ya tienes una cuenta?", + "register_sign_in": "Iniciar sesión", "login_registered_success": "Tu cuenta fue creada con éxito. Inicia sesión ahora.", "admin_tab_invites": "Invitaciones", "admin_invites_list_title": "Invitaciones", diff --git a/frontend/src/routes/AuthHeader.svelte b/frontend/src/routes/AuthHeader.svelte index 5520bf8f..d2560817 100644 --- a/frontend/src/routes/AuthHeader.svelte +++ b/frontend/src/routes/AuthHeader.svelte @@ -5,7 +5,7 @@ import LanguageSwitcher from '$lib/components/LanguageSwitcher.svelte';
-
+
Familienarchiv import { m } from '$lib/paraglide/messages.js'; import { getErrorMessage } from '$lib/errors'; +import { enhance } from '$app/forms'; import AuthHeader from '../AuthHeader.svelte'; let { @@ -16,6 +17,22 @@ let { } = $props(); let showPassword = $state(false); +let showPasswordConfirm = $state(false); +let password = $state(''); +let passwordConfirm = $state(''); +let notifyOnMention = $state(true); +let submitAttempted = $state(false); +let submitting = $state(false); + +const pwValid = $derived(password.length >= 8); +const pwMatch = $derived(passwordConfirm.length > 0 && password === passwordConfirm); +const pwMismatch = $derived(passwordConfirm.length > 0 && password !== passwordConfirm); +const showPwHint = $derived(submitAttempted || password.length > 0); +const showMatchHint = $derived(submitAttempted || passwordConfirm.length > 0); + +$effect(() => { + if (form?.error) submitting = false; +}); @@ -25,16 +42,8 @@ let showPassword = $state(false);
-
-
- - +
+
{#if data.codeError}
{:else} -
-

- {m.register_heading()} + +
+

+ {m.register_eyebrow()} +

+

+ {m.register_hero_headline()}

- {#if data.code} -

{m.register_subtext()}

- {/if} +

+ {m.register_hero_subtext()} +

+
-
+ +
+ { + if (!pwValid || pwMismatch) { + submitAttempted = true; + return async () => {}; + } + submitAttempted = true; + submitting = true; + return async ({ update }) => { + await update(); + }; + }} + > -
- - -
+ +
+

+ {m.register_section_about()} +

+
+
+ + +
+
+ + +
+
+
-
- - -
+ +
+

+ {m.register_section_account()} +

-
- - - {#if data.prefill?.email} -

{m.register_prefill_hint()}

- {/if} -
- -
- -
- - +
+ {#if showPwHint} +

+ {pwValid ? m.register_pw_ok() : m.register_pw_hint()} +

+ {/if} +
+ +
+ +
+ + +
+ {#if showMatchHint} + {#if pwMatch} +

+ {m.register_pw_match_ok()} +

+ {:else if pwMismatch} +

{m.register_pw_match_no()}

+ {/if} + {/if} +
+
+ + +
+

+ {m.register_section_notifications()} +

+
-

+ + + {m.register_notify_title()} + {m.register_notify_desc()} + + + {#if form?.error}
@@ -181,12 +289,51 @@ let showPassword = $state(false);
{/if} - +
+ + +

+ {m.register_already_have_account()} + {m.register_sign_in()} +

+
{/if}