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
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:
@@ -8,6 +8,8 @@ import AlertsView from './views/AlertsView';
|
||||
import ProfileView from './views/ProfileView';
|
||||
import AdminView from './views/AdminView';
|
||||
import LoginModal from './components/LoginModal';
|
||||
import ForgotPasswordModal from './components/ForgotPasswordModal';
|
||||
import ResetPasswordView from './views/ResetPasswordView';
|
||||
import SavedNotifications from './components/SavedNotifications';
|
||||
import BottomNav from './components/BottomNav';
|
||||
import { getFaro } from './utils/faro';
|
||||
@@ -17,6 +19,9 @@ function App() {
|
||||
const [currentUser, setCurrentUser] = useState(null);
|
||||
const [authChecked, setAuthChecked] = useState(false);
|
||||
const [showLogin, setShowLogin] = useState(false);
|
||||
const [showForgot, setShowForgot] = useState(false);
|
||||
const [forgotMode, setForgotMode] = useState('password');
|
||||
const [resetToken, setResetToken] = useState(null);
|
||||
const [showSaved, setShowSaved] = useState(false);
|
||||
const [badgeCount, setBadgeCount] = useState(0);
|
||||
const [prescriptionSearch, setPrescriptionSearch] = useState('');
|
||||
@@ -67,6 +72,13 @@ function App() {
|
||||
});
|
||||
};
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const token = params.get('token');
|
||||
if (token) {
|
||||
setResetToken(token);
|
||||
setScreen('reset-password');
|
||||
}
|
||||
|
||||
fetch('/api/auth/check')
|
||||
.then(r => r.json())
|
||||
.then(data => { if (data.authenticated) setCurrentUser(data.user); })
|
||||
@@ -126,6 +138,18 @@ function App() {
|
||||
setCurrentUser(prev => ({ ...prev, ...updated }));
|
||||
}
|
||||
|
||||
function handleForgotPassword(mode) {
|
||||
setForgotMode(mode);
|
||||
setShowLogin(false);
|
||||
setShowForgot(true);
|
||||
}
|
||||
|
||||
function handleResetComplete() {
|
||||
setResetToken(null);
|
||||
setShowLogin(true);
|
||||
window.history.replaceState({}, '', '/');
|
||||
}
|
||||
|
||||
function handleAdminClick() {
|
||||
setScreen('admin');
|
||||
}
|
||||
@@ -211,6 +235,14 @@ function App() {
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'reset-password':
|
||||
activeView = (
|
||||
<ResetPasswordView
|
||||
token={resetToken}
|
||||
onReset={handleResetComplete}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'admin':
|
||||
activeView = <AdminView />;
|
||||
break;
|
||||
@@ -243,6 +275,18 @@ function App() {
|
||||
<LoginModal
|
||||
onLogin={handleLogin}
|
||||
onClose={() => setShowLogin(false)}
|
||||
onForgotPassword={handleForgotPassword}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showForgot && (
|
||||
<ForgotPasswordModal
|
||||
initialMode={forgotMode}
|
||||
onClose={() => setShowForgot(false)}
|
||||
onBackToLogin={() => {
|
||||
setShowForgot(false);
|
||||
setShowLogin(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user