diff --git a/src/components/FranceMap.astro b/src/components/FranceMap.astro index def4185..b038c37 100644 --- a/src/components/FranceMap.astro +++ b/src/components/FranceMap.astro @@ -1,7 +1,7 @@ --- import franceMap from '../data/france-map.json'; -import { COLORS, COLOR_LABEL, PHENOMENA } from '../lib/phenomena'; -import type { ColorId, PhenomenonId } from '../lib/phenomena'; +import { COLORS, PHENOMENA } from '../lib/phenomena'; +import type { ColorId } from '../lib/phenomena'; import type { VigilanceAlert } from '../lib/vigilance'; import { getDepartement } from '../lib/departements'; @@ -10,7 +10,7 @@ interface Props { alertsByDept?: Map; } -const { colorsByDept, alertsByDept = new Map() } = Astro.props; +const { colorsByDept, alertsByDept = new Map() } = Astro.props; const entries = Object.entries(franceMap.paths) as [string, { d: string; name: string }][]; // Construire un objet { code: { name, color, alerts: [{phenLabel, colorName, colorId}] } } diff --git a/src/pages/departement/[code].astro b/src/pages/departement/[code].astro index 1d8fecf..aed4731 100644 --- a/src/pages/departement/[code].astro +++ b/src/pages/departement/[code].astro @@ -147,16 +147,20 @@ const j1Available = snapshot ? (ech === 'J' && hasJ1Period(snapshot)) : false; const today = snapshot ? alertsForDepartement(snapshot, dept.code, ech) : []; const tomorrow = j1Available ? alertsForDepartement(snapshot!, dept.code, 'J1') : []; -// Sort by severity desc, pick top alert for the hero block +// Sort by severity desc. "Active" = vigilance jaune ou plus (colorId >= 2). +// Le flux MF renvoie parfois des phénomènes explicitement au vert (colorId 1) — +// ce ne sont PAS des alertes : ils rejoignent le dropdown "tous au vert", au même +// titre que les phénomènes absents du flux. topAlert = la plus sévère des actives +// (sert aux numéros d'urgence + carte "Kit" en bas de page). const sortedToday = [...today].sort((a, b) => b.colorId - a.colorId); -const topAlert = sortedToday[0] ?? null; -const otherAlerts = sortedToday.slice(1); +const activeToday = sortedToday.filter((a) => a.colorId >= 2); +const topAlert = activeToday[0] ?? null; -const adviceFor = topAlert ? ADVICE[topAlert.phenomenonId] : null; -// First 3 action items as quick bullets inside the hero block -const quickActions = adviceFor - ? adviceFor.blocks.flatMap((b) => b.items).slice(0, 3) - : []; +// First 3 action items, par phénomène, pour le bloc "Que faire maintenant ?" +function quickActionsFor(phenId: PhenomenonId): string[] { + const advice = ADVICE[phenId]; + return advice ? advice.blocks.flatMap((b) => b.items).slice(0, 3) : []; +} // Per-phenomenon color maps for the comparison table const PHENOM_IDS: PhenomenonId[] = [1, 2, 3, 5, 6, 8, 9]; @@ -179,9 +183,10 @@ const comparisonRows = PHENOM_IDS.map((id) => ({ changed: j1Available && (todayByPhenom.get(id) ?? 1) !== (tomorrowByPhenom.get(id) ?? 1), })); -// Phenomena with no active alert today (green) -const activePhenomIds = new Set(today.map((a) => a.phenomenonId)); -const inactivePhenomIds = PHENOM_IDS.filter((id) => !activePhenomIds.has(id)); +// Phénomènes au vert aujourd'hui = ceux sans alerte active (jaune+). Inclut aussi +// les phénomènes absents du flux MF (réputés verts). Tous regroupés dans le dropdown. +const activePhenomIds = new Set(activeToday.map((a) => a.phenomenonId)); +const greenPhenomIds = PHENOM_IDS.filter((id) => !activePhenomIds.has(id)); const productDate = snapshot?.productDatetime ? new Date(snapshot.productDatetime).toLocaleString('fr-FR', { @@ -204,10 +209,6 @@ const tomorrowLabel = tomorrow[0] ? labelDate(tomorrow[0].beginTime) : ''; // Glyphs matching the pill levels const GLYPHS: Record = { 1: '●', 2: '▲', 3: '◆', 4: '■' }; - -// Pre-computed display values for the hero alert block -const topColorName = topAlert ? COLORS[topAlert.colorId].name : null; -const topPhen = topAlert ? PHENOMENA[topAlert.phenomenonId] : null; --- - {/* All-green state */} - {sortedToday.length === 0 && ( + {/* All-green state — aucune vigilance active (jaune+) */} + {activeToday.length === 0 && (

● Aucune vigilance active {todayLabel ? `pour ${todayLabel}` : "aujourd'hui"}

- Tous les phénomènes sont au vert pour {dept.name}. Restez attentif aux mises à jour Météo France. + Tous les phénomènes sont au vert pour {dept.name} — rien de particulier à signaler. + Restez attentif aux mises à jour Météo France.

)} - {/* Hero — top alert */} - {topAlert && topColorName && topPhen && ( -
-
- -

- {GLYPHS[topAlert.colorId]} {topPhen.label} — {COLOR_LABEL[topAlert.colorId]} -

-
- - {adviceFor && ( -
- Que faire maintenant ? -
    - {quickActions.map((a) =>
  • {a}
  • )} -
- - Voir le kit complet {topPhen.label} → - -
- )} - -

- Valide du {fmtTime(topAlert.beginTime)} au {fmtTime(topAlert.endTime)} — heure de Paris. -

-
- )} - - {/* Other active alerts */} - {otherAlerts.map((a) => { + {/* Active alerts (jaune+) — bloc complet "Que faire maintenant ?" sur chacune */} + {activeToday.map((a) => { const colorName = COLORS[a.colorId].name; const phen = PHENOMENA[a.phenomenonId]; + const advice = ADVICE[a.phenomenonId]; + const quickActions = quickActionsFor(a.phenomenonId); return ( -
-
-
- - {phen.label} -
- +
+
+ +

+ {GLYPHS[a.colorId]} {phen.label} — {COLOR_LABEL[a.colorId]} +

-

- Du {fmtTime(a.beginTime)} au {fmtTime(a.endTime)} + + {advice && ( +

+ Que faire maintenant ? +
    + {quickActions.map((item) =>
  • {item}
  • )} +
+ + Voir le kit complet {phen.label} → + +
+ )} + +

+ Valide du {fmtTime(a.beginTime)} au {fmtTime(a.endTime)} — heure de Paris.

); })} - {/* Collapsible: inactive phenomena (all green) */} - {inactivePhenomIds.length > 0 && ( + {/* Collapsible: phénomènes au vert (sans vigilance) */} + {greenPhenomIds.length > 0 && (
- {inactivePhenomIds.length} phénomène{inactivePhenomIds.length > 1 ? 's' : ''} — tous au vert + {greenPhenomIds.length} phénomène{greenPhenomIds.length > 1 ? 's' : ''} au vert — aucune vigilance
- {inactivePhenomIds.map((id) => ( + {greenPhenomIds.map((id) => (
{PHENOMENA[id].label}