Avant : SargassesMap faisait 1 appel /api/spots (API Platform) puis
N appels /api/spots/{id}/score (un par spot, ~100+ pour la Guadeloupe).
Après : un seul GET /api/spots/overview (LATERAL JOIN spots+scores)
avec Cache-Control: public, max-age=1800, stale-while-revalidate=300.
Les marqueurs colorés s'affichent immédiatement depuis la réponse unique ;
/api/spots/{id}/score n'est appelé qu'au clic sur un spot (SpotPanel).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
S3 OLCI n'a pas de bande SWIR : impossible de filtrer sun glint résiduel
et aérosols sahariens → faux positifs massifs à 300 m de résolution.
- Tuiles : ajout des propriétés source/confidence/coverage_km2
- Carte : styling data-driven par source
S2 → orange vif (#f4720a), opacité 65 % — signal confirmé
S3 → or pâle (#d4b830), opacité 20 % — signal incertain
- Légende : entrées distinctes S2 / S3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Le style basculait de positron (URL) vers cartoonizeStyle() ~500 ms
après le premier rendu. Ce setStyle() déclenchait une réinscription
des sources/layers (react-map-gl v8 / maplibre-gl v5) qui échouait
silencieusement — les bancs de sargasses devenaient invisibles.
La carte est désormais montée UNE SEULE FOIS quand le style est prêt
(avec timeout 4 s → fallback positron). Plus de transition post-mount,
plus de race condition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remplace le logo PNG par un SVG radar inline (cercles concentriques +
bras rotatif + blip) en bleu #2563eb/#60a5fa sur fond #1a1a2e.
Même SVG utilisé pour favicon.svg et le picto dans la topbar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scoreLabel/etaLabel/SpotMarker conditionnent Veille à distance<100km
pour éviter l'alerte ambre sur les spots sans sargasses proches
- "patch" → "banc de sargasses" dans le SpotPanel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- "Indice de risque" en petit header explicite au-dessus
- Le label (VEILLE / RISQUE / IMPACT) devient l'élément visuel principal (30px)
- Le nombre /100 rétrogradé en hint discret sous la barre
- Suppression de l'ambiguïté "est-ce une note ou un risque ?"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scoreLabel() : low <15 → "OK", low ≥15 → "Veille", cohérence avec valeur numérique
- etaLabel() : score ≥15 sans ETA → "Sargasses en surveillance" (eta--watch)
- SpotMarker : étoile ambre pour level=low + scoreValue≥15 vs étoile verte pure OK
- spotScores stocke {level, value} au lieu de level seul
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ST_Dump sur la dernière observation → 5 patches les plus proches dans 200km, exposés
dans /spots/{id}/score. SpotPanel affiche le nombre de patches et la distance+surface
de chacun sous forme de barres (échelle 0–100km).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Expose breakdown {distance, density, velocity, trend} dans l'API /spots/{id}/score
(pour le score courant reconstruit depuis les champs stockés, et pour chaque horizon
avec confidence appliquée). Affiche les barres avec valeur/max dans le SpotPanel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Symfony Scheduler (MainSchedule) : cron 0,6,12,18h UTC
- IngestionScheduleMessage + IngestionScheduleHandler : pipeline complet
ingestion → forecasts → impact scores pour toutes les zones Antilles
- messenger.yaml : transport scheduler_main + async Redis (rs971_async)
- entrypoint.sh : 2 workers en background (scheduler_main + async)
- GET /api/status : date/heure de la dernière observation
- SargassesMap : badge "Données du JJ/MM à HH:MM" en bas à gauche
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Les prévisions utilisent la même couleur (#f4a020/#c47a10) que les
observations confirmées, avec fill à 20% (vs 50%) et contour tirets.
Lecture immédiate : "sargasses futures" sans rupture visuelle arbitraire.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Les prévisions sont des estimations approximatives : réduire le fill à 0.12
laisse voir la carte (et la terre) en dessous, communiquant visuellement
"zone probable" vs observation confirmée. Contour tirets [6,4] plus lisible.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Les dots couvraient tout le tile Sentinel (pas seulement les pixels
sargasses), saturant la vue. Fill opacity réduit à 0.5 pour laisser
respirer la carte sous-jacente.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MapLibre considère null comme "propriété présente" → le filtre !has
ne prenait pas le relais → tous les polygones étaient masqués.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passe afaiIndex en propriété GeoJSON et applique un filtre MapLibre
sur les layers observation : seules les features avec afai > 0 sont
affichées. Fallback : si la propriété est absente, affichage normal.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Topbar glassmorphism : logo + boutons île (Guadeloupe/Martinique/Barbade/St-Martin/Dominique) + timeline intégrée
- flyTo() animé par île, vue initiale centrée sur Guadeloupe
- Marqueurs spots colorés par niveau d'impact (vert/jaune/rouge) chargés progressivement
- Score remplacé par un gauge : valeur en grand + barre de progression animée
- Légende flottante bas-gauche (observations / prévisions / niveaux)
- Transition fade 350ms sur les layers MapLibre au changement d'horizon temporel
- NavigationControl déplacé en bas à droite
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>