Aller au contenu

Story OP-016: Frontend — Annulation campagne (modale + cleanup)

Module: operator-console Slice: Architecture §11 OP-004a (frontend) Side: [OPERATOR] Version target: V0.0.3 Priority: 17 Depends on: OP-009 (vue ENVOYÉE), OP-012 (POST /cancel backend) Can develop concurrently with: OP-017, OP-018, OP-019 Merge order: After OP-012 + OP-009 Estimated complexity: S PRD User Stories: US-OP-07 AC1+AC2 (annulation), FR-OP-05 Wireframe: docs/wireframes/operator-console/OP-016/ (brief design §4.7 modale annulation)


Objective

Activer le bouton « ⋯ Annuler la campagne » (placeholder OP-009) sur la vue ENVOYÉE et la vue BROUILLON. Modale de confirmation avec compteur d'impact « X liens seront révoqués » (US-OP-07 AC1) ; sur confirmation, POST /cancel, toast succès, redirection vers liste.


Backend Scope

Consomme POST /api/operator/campaigns/{id}/cancel (OP-012). Pour calculer le compteur d'impact AVANT confirmation, consomme GET /campaigns/{id}/status (OP-006) et calcule nonTerminalCount = total - paye - regleHorsPlat - exclu - lienRevoque.


Frontend Scope

Components

Sous frontend-operator/src/features/campaigns/cancel/:

  • CancelCampaignButton.tsx — bouton kebab/dropdown item visible si role==cabinet_admin ET status ∈ {BROUILLON, ENVOYÉE}. Caché ailleurs.
  • CancelCampaignModal.tsx — modale de confirmation :
  • Calcule nonTerminalCount via status.
  • Affiche : « {N} lien(s) seront révoqués. Les clients qui cliqueront sur leur lien verront : « Ce lien n'est plus valide. Veuillez contacter votre cabinet. » Cette action est irréversible. »
  • Boutons : [Non, garder] (secondary) + [Oui, annuler] (danger).
  • Sur confirm : POST /cancel ; spinner ; toast success « Campagne annulée. {N} lien(s) révoqués. » ; redirect vers /campagnes + invalidation queries.
  • useCancelCampaign.ts — mutation React Query.

UI States

State Behavior French Copy
Loading Modale en spinner pendant POST
Empty N/A
Error 502 (AUTH down) InlineBanner rouge dans modale + retry « Service d'authentification indisponible. La campagne n'a pas été annulée. [Réessayer] »
Error 400 InlineBanner message backend
Offline Bouton « Oui, annuler » désactivé + tooltip « Indisponible hors-ligne. »
Success Toast 4s + redirect « Campagne annulée. {N} lien(s) révoqués. »

Responsive Behavior

  • Modale centrée 480 px desktop, 90 % largeur tablet.

Interactions

  • Esc ferme la modale (sans annuler la campagne).
  • Focus trap.
  • Bouton danger en rouge (token --color-danger).
  • Modale block-listener empêche fermeture par click outside (action destructive).

Acceptance Criteria

AC-001: Modale affiche le compteur de liens à révoquer (US-OP-07 AC1)
Given une campagne ENVOYÉE avec 16 cc non-terminaux
When je clique "⋯ Annuler la campagne" → modale ouvre
Then la modale affiche "16 liens seront révoqués"
And le bouton "Oui, annuler" est en danger (rouge).

AC-002: Confirmation déclenche POST /cancel + redirect (US-OP-07 AC2)
Given la modale est ouverte avec 16 liens
When je clique "Oui, annuler"
Then POST /campaigns/{id}/cancel est appelé
And toast "Campagne annulée. 16 liens révoqués." s'affiche 4s
And je suis redirigé vers /campagnes
And la liste est mise à jour (statut ANNULÉE visible).

AC-003: Erreur 502 AUTH → message dédié, campagne intacte
Given AUTH down (mock)
When je confirme l'annulation
Then la modale affiche "Service d'authentification indisponible. La campagne n'a pas été annulée. [Réessayer]"
And aucune redirection
And la campagne reste ENVOYÉE.

AC-004: agency_operator ne voit pas le bouton
Given je suis agency_operator
When je charge /campagnes/{id} (ENVOYÉE)
Then aucun bouton "Annuler" n'apparait dans le header ni dans le kebab.

Compliance Rules

  • FR-OP-05 + US-OP-07 : modale avec compteur d'impact, irréversible. VÉRIFIÉ.
  • PRD design §4.7 : exact wording. VÉRIFIÉ.

Standards & Conventions

  • docs/standards/design-system.md — Modal, Button danger variant.

Testing Requirements

Unit Tests

  • CancelCampaignModalTest : focus trap, Esc, danger button, RBAC visibility.

Integration Tests

  • Playwright cancel-flow.spec.ts AC-001..AC-004.

What QA Will Validate

  • A11y : annonces SR sur ouverture modale.
  • Rendu responsive.

Out of Scope

  • Annulation côté backend → OP-012.
  • Restauration campagne annulée → out-of-scope V1.

Definition of Done

  • [ ] Bouton "Annuler" actif pour cabinet_admin sur BROUILLON+ENVOYÉE
  • [ ] Modale conforme design §4.7
  • [ ] AC-001..AC-004 passent
  • [ ] 5 états UI implémentés
  • [ ] Toast + redirect + invalidation
  • [ ] Tests verts