mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 13:31:43 +02:00
4.6 KiB
4.6 KiB
Frontend — Patterns : Forms
Extrait de la base de connaissance Lead_tech. Voir
knowledge/frontend/patterns/README.mdpour l'index complet.
Pattern : Formulaire robuste avec validation et erreurs explicites
Synthèse
- Objectif : garantir des formulaires fiables, compréhensibles et maintenables.
- Contexte : toute interface avec saisie utilisateur et règles métier.
- Quand l'utiliser : dès qu'un formulaire dépasse un simple champ isolé.
- Quand l'éviter : formulaires ultra-simples sans validation réelle.
Analyse
- Avantages :
- UX claire (l'utilisateur sait quoi corriger)
- Moins d'erreurs silencieuses
- Base saine pour tests et accessibilité
- Limites / vigilance :
- Peut sembler verbeux sans discipline
- Risque de duplication si mal factorisé
Validation
- Validé le : 25-01-2026
- Contexte technique : Front-end agnostique, API HTTP
Implémentation (exemple minimal)
- Validation côté client (format, champs requis)
- Validation côté serveur (règles métier)
- Mapping explicite des erreurs serveur → champs UI
- Aucun submit silencieux
Checklist
- Messages d'erreur compréhensibles et localisés
- Validation client + serveur cohérente
- Focus automatique sur le champ en erreur
- États loading / disabled gérés
- Tests sur cas valides et invalides
Pattern : Toggle optimiste avec rollback (React Server Action)
Synthèse
- Objectif : masquer la latence serveur sur un toggle boolean en mettant à jour l'UI immédiatement, avec rollback en cas d'erreur.
- Contexte : toggles boolean (visibilité, disponibilité, settings) où la latence doit être masquée.
- Quand l'utiliser : toggles sans besoin de re-fetcher l'entité entière après mutation.
- Quand l'éviter : mutations qui retournent des données complexes → préférer le pattern "Server Action retournant l'entité".
Validation
- Validé le : 21-03-2026
- Contexte technique : React / Next.js App Router — app-template-resto
Implémentation
const [optimistic, setOptimistic] = useState(initialValue);
async function handleToggle() {
const prev = optimistic;
setOptimistic(!prev); // update immédiat
try {
await toggleAction(!prev);
router.refresh(); // synchronise le Server Component parent
} catch {
setOptimistic(prev); // rollback si erreur
}
}
Pattern : Server Action retournant l'entité — élimination de router.refresh() sur create/edit
Synthèse
- Objectif : mettre à jour l'état local directement avec les données réelles retournées par le serveur, sans round-trip SSR supplémentaire.
- Contexte : liste d'items managée côté client (
useState) avec création et modification via Server Actions. - Quand l'utiliser : create et edit d'entités dans une liste. Plus performant que toggle optimiste +
router.refresh(). - Quand l'éviter : simples toggles boolean → le pattern optimiste avec rollback suffit.
Analyse
- Avantages vs toggle optimiste +
router.refresh():- Zéro aller-retour SSR supplémentaire (~500ms–2s économisés sur mobile)
- État local garanti cohérent avec la DB (données réelles, pas calculées localement)
- Pas de flash de rechargement
- Limites / vigilance :
revalidatePathreste nécessaire pour invalider le cache des pages publiques
Validation
- Validé le : 22-03-2026
- Contexte technique : React / Next.js App Router — app-template-resto story 3.8
Implémentation
// Repository — retourne l'entité complète
export async function createItem(tenantId: string, data: Input): Promise<ItemRow> {
return prisma.item.create({ data: { tenantId, ...data }, select: { ...fullSelect } });
}
// Action — retourne la donnée au client
export async function createItemAction(formData: FormData): Promise<ItemRow> {
const actor = await requireOwner();
const item = await createItem(actor.tenantId, input);
revalidatePath("/dashboard/..."); // invalider cache pages publiques
return item; // ← clé : retourner l'entité
}
// Client — mise à jour locale sans round-trip SSR
const created = await createItemAction(formData);
setItems((prev) => [...prev, created]); // pas de router.refresh()
Pour les entités avec relations : utiliser un helper findItemById(tenantId, id) appelé après la mutation pour retourner la forme complète avec les relations résolues.