diff --git a/frontend/src/components/AddPersonPanel.jsx b/frontend/src/components/AddPersonPanel.jsx index b23dc40..288e5fa 100644 --- a/frontend/src/components/AddPersonPanel.jsx +++ b/frontend/src/components/AddPersonPanel.jsx @@ -146,8 +146,6 @@ function AddPersonPanel({ visible, persons = [], loading = false, error = '', on }) } - const isValid = firstName.trim().length > 0 - const relationTypeLabels = { parent: t('Parent de'), child: t('Enfant de'), @@ -191,7 +189,6 @@ function AddPersonPanel({ visible, persons = [], loading = false, error = '', on className={touched.firstName && !firstName.trim() ? 'apn-input--error' : ''} value={firstName} onChange={(e) => setFirstName(e.target.value)} - onBlur={() => setTouched((prev) => ({ ...prev, firstName: true }))} placeholder={t('Marie')} autoComplete="off" aria-invalid={touched.firstName && !firstName.trim()} @@ -325,7 +322,9 @@ function AddPersonPanel({ visible, persons = [], loading = false, error = '', on - diff --git a/frontend/src/components/DateField.jsx b/frontend/src/components/DateField.jsx index a41ef4f..654b8b4 100644 --- a/frontend/src/components/DateField.jsx +++ b/frontend/src/components/DateField.jsx @@ -1,11 +1,14 @@ import { useState } from 'react' import { t } from '../i18n/index.js' -import { dateToInputText, parseDateInput } from '../utils/dateInput.js' +import { dateToInputText, formatDigitsAsDate, parseDateInput } from '../utils/dateInput.js' // Champ de date de la fiche : une année seule ou une date complète (issue #77). Le texte tapé reste tel // quel ; la valeur ne remonte qu'une fois comprise, sinon le champ le signale sans rien enregistrer. +// Le clavier numérique du téléphone n'a pas de barre oblique : au-delà de 4 chiffres, les barres se posent +// toutes seules (12031950 → 12/03/1950). Le message n'apparaît qu'en quittant le champ. export default function DateField({ id, value, onChange, placeholder, className = '' }) { const [text, setText] = useState(() => dateToInputText(value)) + const [touched, setTouched] = useState(false) const invalid = parseDateInput(text) === undefined return ( @@ -17,14 +20,23 @@ export default function DateField({ id, value, onChange, placeholder, className className={className} value={text} placeholder={placeholder || t('Année ou date')} - aria-invalid={invalid || undefined} + aria-invalid={(touched && invalid) || undefined} onChange={(e) => { - setText(e.target.value) - const parsed = parseDateInput(e.target.value) - if (parsed !== undefined) onChange(parsed) + const next = formatDigitsAsDate(e.target.value) + setText(next) + const parsed = parseDateInput(next) + if (parsed !== undefined) { + setTouched(false) + onChange(parsed) + } + }} + onBlur={() => { + const parsed = parseDateInput(text) + if (parsed === undefined) setTouched(true) + else setText(dateToInputText(parsed)) }} /> - {invalid && {t('Une année (1950) ou une date (12/03/1950)')}} + {touched && invalid && {t('Une année (1950) ou une date (12/03/1950)')}} ) } diff --git a/frontend/src/components/EditModeOverlay.css b/frontend/src/components/EditModeOverlay.css index 30edccb..850e1fc 100644 --- a/frontend/src/components/EditModeOverlay.css +++ b/frontend/src/components/EditModeOverlay.css @@ -53,6 +53,11 @@ .edit-mode-toast-text { font-size: 13px; } } +/* Téléphone : le texte se coupait en « Vous modifi… » à côté du bouton, qui suffit à lui seul */ +@media (max-width: 480px) { + .edit-mode-toast--with-submit .edit-mode-toast-text { display: none; } +} + @media (prefers-reduced-motion: reduce) { .edit-mode-toast { animation: pz-fade 160ms ease both; } } diff --git a/frontend/src/components/EditSessionBar.jsx b/frontend/src/components/EditSessionBar.jsx index 3113e39..79f9647 100644 --- a/frontend/src/components/EditSessionBar.jsx +++ b/frontend/src/components/EditSessionBar.jsx @@ -22,7 +22,7 @@ function EditSessionBar({ active, hasDraft, role = 'contributor', onDeactivate, <>