Aller au contenu

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 — utilise Tabs primitive 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 de ContractEditDrawer (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.ts AC-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