# Prompt p03 — Dashboard CEO (web)
*Contextes requis : ctx-global.md + ctx-web-nextjs.md + ctx-laravel-bff.md*

---

## Profil & Accès
- **Rôle** : CEO (Directeur Général Exécutif)
- **Nombre d'utilisateurs** : 1
- **Accès** : LECTURE SEULE — aucun bouton de création/modification/suppression
- **Session** : 8h, OTP à chaque connexion
- **Périmètre** : toutes les 23 stations, tous les modules (vue consolidée)

---

## Fichiers à créer

```
app/(erp)/dashboard/ceo/page.tsx
app/(erp)/dashboard/ceo/layout.tsx
components/dashboard/ceo/KpiGrid.tsx
components/dashboard/ceo/StationsMap.tsx
components/dashboard/ceo/ChartCAMensuel.tsx
components/dashboard/ceo/ChartRepartitionProduits.tsx
components/dashboard/ceo/ChartTopBottomStations.tsx
components/dashboard/ceo/AlertesFeed.tsx
components/dashboard/ceo/KpiCard.tsx
hooks/useCeoDashboard.ts
hooks/useAlerteWebSocket.ts
```

---

## Spec UX condensée

```
┌─────────────────────────────────────────────────────────────────────┐
│ FLOWUP ERP  [logo]          Dashboard CEO — 13 mai 2026  [OPE][AUD] │
│ ████████████████████████████████████████████████ Actualisé 10:42:17│
├─────────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐  │
│ │ CA Jour  │ │CA Semaine│ │ CA Mois  │ │Vol. Total│ │Encaissmt │  │
│ │12,4M GNF │ │78,2M GNF │ │312M GNF  │ │48 320 L  │ │98,7%     │  │
│ │▲ +3,2%   │ │▲ +1,8%   │ │▲ +5,1%   │ │▼ -0,4%   │ │▲ +0,3%   │  │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘  │
│ ┌──────────┐ ┌──────────────────────────────────────────────────┐  │
│ │  Écarts  │ │         🔴 ALERTES CRITIQUES (2)                 │  │
│ │  0,82%   │ │  ⚠ Station Ratoma — Fuite cuve #2 (10:38)       │  │
│ │▼ à surveill│ │  ⚠ Station Kaloum — Niveau <10% SP95 (10:41) │  │
│ └──────────┘ └──────────────────────────────────────────────────┘  │
├───────────────────────────┬─────────────────────────────────────────┤
│  CARTE 23 STATIONS        │  CA MENSUEL 12 MOIS (graphique ligne)  │
│  [Leaflet OpenStreetMap]  │  ─────────────────────────────────────  │
│                           │  400M ┤         ╭──╮                    │
│  ● Vert : opérationnelle  │  300M ┤    ╭────╯  ╰─────              │
│  ● Orange : alerte seuil  │  200M ┤───╯                            │
│  ● Rouge : alerte critique│  100M ┤                                 │
│                           │       └──────────────────────────────── │
│  [clic = popup KPIs stat.]│       Mai'25                   Mai'26   │
├───────────────────────────┴─────────────────────────────────────────┤
│  RÉPARTITION PRODUITS (donut)    │  TOP/BOTTOM STATIONS (bar chart) │
│  ■ Gasoil 58%  ■ SP95 31%        │  ▌ Kaloum   312M   ✓            │
│  ■ SP98  8%    ■ Pétrole 3%      │  ▌ Ratoma   287M   ✓            │
│                                  │  …                               │
│                                  │  ▌ Matoto    89M   ⚠            │
└──────────────────────────────────┴─────────────────────────────────┘
```

### Modules clés
- **KPI Grid** : 7 cartes (CA Jour, CA Semaine, CA Mois, Volume Total, Encaissements, Écarts, Alertes actives). Chaque carte affiche valeur + variation % + tendance (▲▼). Montants en VARCHAR → affichage formaté côté client.
- **StationsMap** : Leaflet.js, marqueurs colorés (vert = OK, orange = alerte seuil, rouge = alerte critique). Clic sur marqueur = popup avec KPIs station (CA jour, niveaux cuves, shifts actifs).
- **ChartCAMensuel** : ligne, 12 mois glissants, recharts. Tooltip avec montant + variation vs même mois N-1.
- **ChartRepartitionProduits** : donut recharts, 4-6 produits, légende latérale.
- **ChartTopBottomStations** : bar chart horizontal, top 5 + bottom 5, code couleur.
- **AlertesFeed** : feed temps réel WebSocket, alertes classées par sévérité (CRITIQUE > ALERTE > INFO). Badge rouge persistant si alertes critiques non acquittées (acquittement non disponible pour CEO — info seulement).

---

## Endpoints BFF

```
GET /api/dashboard/ceo/kpis
  Headers : Authorization: Bearer {token}
  Réponse : {
    ca_jour: "12400000",           // VARCHAR
    ca_semaine: "78200000",        // VARCHAR
    ca_mois: "312000000",          // VARCHAR
    volume_total_litres: "48320",  // VARCHAR
    taux_encaissement: "98.7",     // VARCHAR (%)
    ecart_moyen: "0.82",           // VARCHAR (%)
    alertes_actives: 2,
    variations: { ca_jour: "+3.2", ca_semaine: "+1.8", ca_mois: "+5.1" }
  }

GET /api/dashboard/ceo/stations
  Réponse : [{
    id: INT,
    nom: "Kaloum",
    lat: FLOAT, lng: FLOAT,
    statut: "ok"|"alerte"|"critique",
    ca_jour: "12400000",           // VARCHAR
    cuves: [{ produit: "Gasoil", niveau_pct: "78" }],
    shifts_actifs: 3
  }]

GET /api/dashboard/ceo/alertes
  Query : ?limite=50&gravite=critique|alerte|info
  Réponse : [{
    id: INT,
    station_nom: "Ratoma",
    type: "ALERTE_FUITE"|"ALERTE_SEUIL"|"ECART_STOCK",
    message: "Fuite cuve #2 détectée",
    gravite: "critique",
    created_at: "2026-05-13T10:38:00Z"
  }]

GET /api/dashboard/ceo/charts/ca-mensuel
  Query : ?mois=12
  Réponse : [{ mois: "2025-06", ca: "289000000", variation_n1: "+4.2" }]

GET /api/dashboard/ceo/charts/repartition-produits
  Réponse : [{ produit: "Gasoil", volume: "28025", pct: "58" }]

GET /api/dashboard/ceo/charts/stations-performance
  Réponse : { top: [...], bottom: [...] }

WS ws://127.0.0.1:4800
  Events : NIVEAU_CUVE | ALERTE_FUITE | ALERTE_SEUIL | ECART_STOCK
```

---

## Règles spécifiques

- **RGCEO-01** : Interface 100% lecture seule — zéro bouton POST/PUT/DELETE. Tout composant interactif limité aux filtres (date range, station, produit) et à la navigation.
- **RGCEO-02** : Tous les montants sont des VARCHAR côté BFF. Le formatage (espaces milliers, "GNF") se fait UNIQUEMENT côté client via `formatMontant(str: string): string`.
- **RGCEO-03** : WebSocket reconnexion automatique avec backoff exponentiel (1s, 2s, 4s, max 30s). Indicateur visuel de connexion (point vert/rouge en haut à droite).
- **RGCEO-04** : Alertes critiques = badge rouge persistant dans le header. Pas d'acquittement pour le CEO (lecture seule).
- **RGCEO-05** : La carte Leaflet ne charge que `react-leaflet` (pas Mapbox, pas Google Maps) — OpenStreetMap tiles uniquement.
- **RGCEO-06** : Auto-refresh KPIs toutes les 60 secondes via `setInterval` + SWR `refreshInterval`. WebSocket pour alertes uniquement.
- **RGCEO-07** : IDs = INT UNSIGNED dans toutes les interfaces TypeScript (`id: number`).
- **RGCEO-08** : Responsive obligatoire — le CEO consulte aussi sur tablette iPad Pro (1024px min).

---

## Tâche Claude

Génère le code complet Next.js 15 TypeScript pour le Dashboard CEO FlowUp ERP.

**Contraintes techniques absolues :**
- Palette navy `#1A2157`, blue `#1E5EFF`, cyan `#00C8C0` — Inter + JetBrains Mono
- Montants = VARCHAR(255) → jamais de DECIMAL/FLOAT dans les types TS
- IDs = `number` (INT UNSIGNED)
- Soft delete = `statut: 3` (jamais de champ `deleted_at` exposé)
- SWR pour le fetching, `useCallback`/`useMemo` pour les performances
- WebSocket dans un hook dédié `useAlerteWebSocket` avec cleanup dans `useEffect`

**Génère dans cet ordre :**
1. Types TypeScript (`types/dashboard-ceo.ts`)
2. Hook `useCeoDashboard.ts` (SWR, refresh 60s)
3. Hook `useAlerteWebSocket.ts` (reconnexion auto)
4. `KpiCard.tsx` (réutilisable)
5. `KpiGrid.tsx` (7 cartes)
6. `StationsMap.tsx` (Leaflet, SSR disabled)
7. `ChartCAMensuel.tsx`, `ChartRepartitionProduits.tsx`, `ChartTopBottomStations.tsx` (recharts)
8. `AlertesFeed.tsx` (feed temps réel)
9. `page.tsx` (assemblage, layout 2 colonnes)
