From e11c767c1c5e5ce2b9b7f4b06bf1d42e84a18d93 Mon Sep 17 00:00:00 2001 From: Olivier Date: Fri, 3 Jul 2026 19:02:44 +0200 Subject: [PATCH] =?UTF-8?q?UX=20am=C3=A9liorations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/server.js | 5 +- frontend/src/pages/MonCompte.jsx | 185 ++++++++++++++++--------------- frontend/src/styles.css | 11 ++ 3 files changed, 110 insertions(+), 91 deletions(-) diff --git a/backend/src/server.js b/backend/src/server.js index 2c1c459..64f4a64 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -71,9 +71,12 @@ const iconsDir2 = path.join(_dataDir, 'icons'); app.use('/api/icons-files', express.static(iconsDir2, { maxAge: '1h', fallthrough: false })); // Basic rate-limit on auth endpoints +// Seuil relevé (50 → 300) : usage local mono-utilisateur/multi-investisseur avec +// beaucoup d'allers-retours de test (login, 2FA, création de comptes admin/invitation…), +// l'ancien seuil de 50 req/15min était atteint trop facilement en usage normal. const authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, - max: 50, + max: 300, standardHeaders: true, legacyHeaders: false, }); diff --git a/frontend/src/pages/MonCompte.jsx b/frontend/src/pages/MonCompte.jsx index dd704fd..62af227 100644 --- a/frontend/src/pages/MonCompte.jsx +++ b/frontend/src/pages/MonCompte.jsx @@ -43,7 +43,7 @@ function ProfileSelect({ label, options, value, onChange }) { return (
- {label} +
setOpen(o => !o)} role="button" tabIndex={0} onKeyDown={e => e.key === 'Enter' && setOpen(o => !o)}> @@ -132,25 +132,31 @@ function EmailChangeForm({ onDone }) { }; return ( -
+

Après le changement, un email de vérification sera envoyé à la nouvelle adresse.

{err &&
{err}
} {msg &&
{msg}
} -
- - setNewEmail(e.target.value)} placeholder="nouvelle@email.com" /> +
+ + setNewEmail(e.target.value)} placeholder="nouvelle@email.com" />
-
- - setPwd(e.target.value)} placeholder="••••••••" /> +
+ + setPwd(e.target.value)} placeholder="••••••••" />
-
- - +
); @@ -191,64 +197,73 @@ function AccountForm() { const handleBlur = () => save(); return ( -
- + <> {/* ── Mon profil ──────────────────────────────────────── */} -
-

Mon profil

+
+

Mon profil

+

+ Vos informations personnelles et votre adresse email de connexion. +

{infoErr &&
{infoErr}
} {infoMsg &&
{infoMsg}
} -
-
- Prénom - setPrenom(e.target.value)} - onBlur={handleBlur} - placeholder="Prénom" /> +
+
+
+ + setPrenom(e.target.value)} + onBlur={handleBlur} + placeholder="Prénom" /> +
+
+ + setNom(e.target.value)} + onBlur={handleBlur} + placeholder="NOM" /> +
-
- Nom - setNom(e.target.value)} - onBlur={handleBlur} - placeholder="NOM" /> + +
+ +
+ {user?.email} + {user?.email_verified + ? ✓ Vérifié + : Non vérifié + } +
+ {!user?.email_verified && }
-
- Mon email -
- {user?.email} - {user?.email_verified - ? ✓ Vérifié - : Non vérifié - } + {!changingEmail && ( +
+
- {!user?.email_verified && } -
- -
- -
+ )} {changingEmail && setChangingEmail(false)} />} -
+ + {loading &&

Enregistrement…

} +
{/* ── Préférences ─────────────────────────────────────── */} -
-

Préférences

-
+
+

Préférences

+

+ Langue et devise utilisées dans l'application. +

+
-
- - {loading &&

Enregistrement…

} -
+
+ ); } @@ -322,15 +337,19 @@ function TwoFASection({ user }) { {/* ── État normal ── */} {status === 'idle' && !enabled && ( - +
+ +
)} {status === 'idle' && enabled && ( - +
+ +
)} {/* ── Setup : QR code + vérification ── */} @@ -374,10 +393,12 @@ function TwoFASection({ user }) { {busy ? '…' : 'Confirmer'} - +
+ +
)} @@ -399,10 +420,12 @@ function TwoFASection({ user }) { {busy ? '…' : 'Désactiver'}
- +
+ +
)} @@ -438,26 +461,6 @@ function SecurityForm() { finally { setPwdLoading(false); } }; - const handleBackfillComptes = async () => { - setLoadingBackfill(true); - setErrorMsg(null); - setSuccessMsg(null); - try { - const { updated, total } = await api.post('/remboursements/backfill-comptes', {}); - if (updated === 0) { - setSuccessMsg(`Aucun remboursement à corriger (${total} vérifié${total > 1 ? 's' : ''}).`); - } else { - setSuccessMsg(`${updated} remboursement${updated > 1 ? 's' : ''} mis à jour sur ${total} vérifié${total > 1 ? 's' : ''}.`); - } - setShowBackfillModal(false); - } catch (err) { - setErrorMsg(err.message || 'Une erreur est survenue.'); - setShowBackfillModal(false); - } finally { - setLoadingBackfill(false); - } - }; - return (

Mot de passe

@@ -742,9 +745,11 @@ export default function MonCompte() { ))} {/* ── Contenu ─────────────────────────────────────── */} -
- {section === 'profil' && } - {section === 'securite' && <>} +
+
+ {section === 'profil' && } + {section === 'securite' && <>} +
diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 033e396..1cf0fdc 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -1338,6 +1338,17 @@ tr:hover td { background: var(--surface-2); } padding: 24px 0 32px 28px; min-width: 0; } +/* Variante pour les pages "compte" à faible densité de contenu (MonCompte) : + évite que les cards s'étirent sur toute la largeur d'un grand écran. + Centrage via flex (plus fiable qu'un margin:auto sur un enfant de grid). */ +.account-content-center { + display: flex; + justify-content: center; +} +.account-content-narrow { + width: 100%; + max-width: 760px; +} /* AccountForm interne — profil + préférences côte-à-côte */ .profile-page {