Story OP-018: Frontend — Page Anomalies (queue + tabs + drawer)¶
Module: operator-console Slice: Architecture §11 OP-004c (frontend) Side: [OPERATOR] Version target: V0.0.3 Priority: 19 Depends on: OP-008 (Drawer + ContractEditDrawer), OP-014 (GET/PATCH /anomalies backend) Can develop concurrently with: OP-016, OP-017, OP-019 Merge order: After OP-014 Estimated complexity: M PRD User Stories: US-OP-08 AC1+AC2+AC3+AC4 Wireframe: docs/wireframes/operator-console/OP-018/ (brief design §4.8)
Objective¶
Livrer la page /anomalies : 3 tabs (Bloquantes / Non bloquantes / Surveillance) avec compteurs, liste filtrable, clic ouvre le drawer contrat focalisé sur le champ défectueux (highlight), action « Marquer résolu » (note obligatoire pour SURVEILLANCE).
Frontend Scope¶
Pages & Routes¶
- Route
/anomalies(TanStack Router).
Components¶
Sous frontend-operator/src/features/anomalies/:
AnomaliesPage.tsx— orchestrateur (tabs + filter bar + liste).AnomaliesTabs.tsx— utiliseTabsprimitive nouvelle ici :- 3 tabs :
🔴 Bloquantes ({count}),🟠 Non bloquantes ({count}),🟡 Surveillance ({count}). - Compteurs depuis
GET /anomalies?status=OUVERTE&type=...(3 queries en parallèle). - Tab actif via URL query
?tab=blocking|nonblocking|surveillance. AnomaliesList.tsx— table simple par type :- Colonnes : Description anomalie, Client, Référence, → Bouton [Ouvrir].
- Pagination cursor.
Tabs.tsx— primitive nouvelle (horizontal scroll en tablet).AnomalyResolveDrawer.tsx— extension deContractEditDrawer(OP-008) :- Champ défectueux highlight
outline: 2px solid var(--color-error). - Bouton « Marquer comme résolu » :
- Si type=SURVEILLANCE → ouvre sub-form note obligatoire (textarea > 5 chars).
- PATCH /anomalies/{id} avec note si pertinent.
- Toast « Anomalie marquée comme résolue. ».
- Drawer ferme + ligne disparait avec slide-out 200ms + compteur tab décrémente.
UI States (AnomaliesPage)¶
| State | Behavior | French Copy |
|---|---|---|
| Loading | 3 tabs skeleton + liste skeleton 6 lignes | — |
| Empty | EmptyState | « 🎉 Aucune anomalie ouverte. Bon travail. » |
| Error | InlineBanner + Réessayer | « Erreur de chargement. [Réessayer] » |
| Offline | Liste en cache + boutons « Marquer résolu » grisés | — |
| Success | Ligne résolue → slide-out + tab counter -1 | toast |
Responsive Behavior¶
- ≥ 1024 px : tabs full + liste pleine largeur.
- 768–1023 px : tabs scroll horizontal.
- Drawer : 420 px desktop, modal full tablet.
Interactions¶
- Tab changement : URL update
?tab=...+ invalidate query. - Clic ligne ou « [Ouvrir] » → drawer avec field highlight.
- SURVEILLANCE : « Marquer résolu » désactivé tant que note vide.
Acceptance Criteria¶
AC-001: Tabs avec compteurs par type (US-OP-08 AC1)
Given 12 anomalies bloquantes, 5 non bloquantes, 3 surveillance ouvertes
When je charge /anomalies
Then les 3 tabs affichent les compteurs exacts (12 / 5 / 3)
And le tab Bloquantes est actif par défaut.
AC-002: Clic anomalie ouvre drawer avec champ highlight (US-OP-08 AC2)
Given une anomalie "Téléphone manquant" sur un contrat
When je clique [Ouvrir]
Then le drawer ouvre sur la fiche contrat
And le champ Téléphone a outline rouge 2px
And le focus est sur ce champ.
AC-003: Marquer résolu (standard) → PATCH + ligne disparait (US-OP-08 AC3)
Given une anomalie NON_BLOCKING dans le drawer
When je clique "Marquer comme résolu"
Then PATCH /anomalies/{id} body={"status":"RÉSOLUE"} est appelé
And toast "Anomalie marquée comme résolue."
And la ligne disparait avec slide-out 200ms
And le compteur du tab décrémente.
AC-004: SURVEILLANCE — note obligatoire (US-OP-08 AC4)
Given une anomalie SURVEILLANCE dans le drawer
When je clique "Marquer comme résolu" sans note
Then un sub-form note apparait avec validation "Champ obligatoire"
And le bouton "Confirmer" est disabled tant que note < 5 chars
When je saisis "Vérifié client" et confirme
Then PATCH appelé avec body={"status":"RÉSOLUE","note":"Vérifié client"}.
Compliance Rules¶
- US-OP-08 AC4 : note obligatoire SURVEILLANCE.
VÉRIFIÉ. - ARTCI traçabilité : audit ANOMALY_RESOLVED via backend.
VÉRIFIÉ.
Standards & Conventions¶
docs/standards/design-system.md— Tabs primitive.docs/standards/react-typescript-guidelines.md
Testing Requirements¶
Unit Tests¶
TabsTest: a11y (role="tablist",aria-selected), keyboard arrows.AnomalyResolveDrawerTest: note obligatoire SURVEILLANCE.
Integration Tests¶
- Playwright
anomalies-flow.spec.tsAC-001..AC-004.
What QA Will Validate¶
- A11y tabs : navigation clavier.
- Rendu responsive.
Out of Scope¶
- Backend anomalies → OP-014.
- Assignment d'anomalies → V2.
Definition of Done¶
- [ ] Route /anomalies rend les 3 tabs
- [ ] AC-001..AC-004 passent
- [ ] Tabs primitive mergée
- [ ] AnomalyResolveDrawer extends ContractEditDrawer
- [ ] Field highlight rouge
- [ ] 5 états UI implémentés
- [ ] Tests verts