feat: add forgot password and username recovery flow
Run Tests on Branches / Detect Changes (push) Successful in 14s
Run Tests on Branches / Backend Tests (push) Successful in 2m24s
Run Tests on Branches / Frontend Tests (push) Successful in 1m57s
Run Tests on Branches / Frontend Mobile Tests (push) Has been skipped
Run Tests on Branches / Parapharmacy API Tests (push) Has been skipped
Run Tests on Branches / PIP Platform Tests (push) Has been skipped

- Add Mailpit SMTP container to docker-compose for dev email capture
- Add nodemailer dependency for email sending
- Add password_reset_tokens table (PG + SQLite)
- Add POST /api/auth/forgot-username endpoint
- Add POST /api/auth/forgot-password endpoint (token-based, 1h expiry)
- Add POST /api/auth/reset-password endpoint
- Create ForgotPasswordModal component (choose mode → email → sent)
- Create ResetPasswordView (token-based new password form)
- Add forgot/recovery links to LoginModal
- Add i18n translations (ES/CA) for the full flow
This commit is contained in:
Antoni Nuñez Romeu
2026-07-27 15:57:54 +02:00
parent 271d23b072
commit 87df61ab15
15 changed files with 839 additions and 1 deletions
+39
View File
@@ -251,6 +251,45 @@ const ca = {
'profile.languageCatalan': 'Català',
'profile.languageSpanish': 'Castellà',
// ForgotPasswordModal
'forgot.title': 'Problemes per accedir?',
'forgot.subtitle': 'Tria què necessites recuperar',
'forgot.password': 'He oblidat la meva contrasenya',
'forgot.passwordDesc': 'T\'enviarem un enllaç per crear-ne una de nova',
'forgot.username': 'He oblidat el meu usuari',
'forgot.usernameDesc': 'T\'enviarem el teu nom d\'usuari',
'forgot.resetTitle': 'Restablir contrasenya',
'forgot.resetDesc': 'Introdueix el teu correu electrònic i t\'enviarem un enllaç per crear una nova contrasenya.',
'forgot.usernameTitle': 'Recuperar usuari',
'forgot.usernameDesc2': 'Introdueix el teu correu electrònic i t\'enviarem el teu nom d\'usuari.',
'forgot.email': 'Correu electrònic',
'forgot.emailPlaceholder': 'el_teu@email.com',
'forgot.send': 'Enviar',
'forgot.sending': 'Enviant...',
'forgot.cancel': 'Cancel·lar',
'forgot.back': 'Tornar',
'forgot.backToLogin': 'Tornar a iniciar sessió',
'forgot.sentTitle': 'Correu enviat',
'forgot.sentText': 'Si l\'adreça de correu existeix a la nostra base de dades, rebràs un missatge en uns minuts. Revisa la teva safata d\'entrada.',
'forgot.close': 'Tancar',
'forgot.error': 'Error en processar la sol·licitud',
'forgot.forgotPassword': 'Has oblidat la contrasenya?',
'forgot.forgotUsername': 'Has oblidat l\'usuari?',
// ResetPasswordView
'reset.title': 'Crear nova contrasenya',
'reset.subtitle': 'Introdueix la teva nova contrasenya',
'reset.newPassword': 'Nova contrasenya',
'reset.confirmPassword': 'Confirmar contrasenya',
'reset.saveBtn': 'Canviar contrasenya',
'reset.saving': 'Desant...',
'reset.passwordsDontMatch': 'Les contrasenyes no coincideixen',
'reset.successTitle': 'Contrasenya actualitzada',
'reset.successText': 'La teva contrasenya s\'ha actualitzat correctament. Ja pots iniciar sessió amb la teva nova contrasenya.',
'reset.goToLogin': 'Anar a iniciar sessió',
'reset.error': 'Error en restablir la contrasenya',
'reset.invalidToken': 'Enllaç invàlid o caducat. Sol·licita un nou restabliment de contrasenya.',
// SavedNotifications
'savedNotifications.title': '🔔 Notificacions Desades',
'savedNotifications.close': 'Tancar',