From 364bb5dfcc3f64b4bc835c26e72c4c9957d83ac8 Mon Sep 17 00:00:00 2001 From: Gwadaking Date: Wed, 8 Apr 2026 01:58:11 -0400 Subject: [PATCH] fix: label "Veille" pour scores low 15-30, marqueur ambre, ETA sous surveillance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- frontend/src/components/Map/SargassesMap.jsx | 32 +++++++++++-------- .../src/components/SpotPanel/SpotPanel.css | 1 + .../src/components/SpotPanel/SpotPanel.jsx | 26 +++++++++------ 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/Map/SargassesMap.jsx b/frontend/src/components/Map/SargassesMap.jsx index 2065327..a8cc8f3 100644 --- a/frontend/src/components/Map/SargassesMap.jsx +++ b/frontend/src/components/Map/SargassesMap.jsx @@ -98,7 +98,7 @@ const makeLayerStyles = (isPrediction, opacity) => ({ }); // ── SVG Markers ─────────────────────────────────────────────────────────── -function SpotMarker({ level, isSelected, name }) { +function SpotMarker({ level, scoreValue, isSelected, name }) { const size = isSelected ? 36 : 28; const shadow = 'filter: drop-shadow(2px 3px 0px rgba(0,0,0,0.35))'; @@ -122,15 +122,18 @@ function SpotMarker({ level, isSelected, name }) { ); - if (level === 'low') return ( -
- - - - -
- ); + if (level === 'low') { + const isWatch = (scoreValue ?? 0) >= 15; + return ( +
+ + + + +
+ ); + } // No score yet const s = isSelected ? 22 : 14; @@ -191,7 +194,8 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep, api.spots.score(s.id) .then(d => { const level = d?.score?.level; - if (level) setSpotScores(prev => ({ ...prev, [s.id]: level })); + const value = d?.score?.value ?? 0; + if (level) setSpotScores(prev => ({ ...prev, [s.id]: { level, value } })); }) .catch(() => {}); }); @@ -292,7 +296,9 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep, const coords = getCoords(spot); if (!coords) return null; const isSelected = spot.id === selectedSpotId; - const level = spotScores[spot.id]; + const sc = spotScores[spot.id]; + const level = sc?.level; + const scoreValue = sc?.value ?? 0; return ( onSpotSelect(spot)} > - + ); })} diff --git a/frontend/src/components/SpotPanel/SpotPanel.css b/frontend/src/components/SpotPanel/SpotPanel.css index 193dcd7..d8db858 100644 --- a/frontend/src/components/SpotPanel/SpotPanel.css +++ b/frontend/src/components/SpotPanel/SpotPanel.css @@ -140,6 +140,7 @@ .eta--now { background: #fee2e2; color: #b91c1c; border-color: #fca5a5; } .eta--soon { background: #fef9c3; color: #92400e; border-color: #fde68a; } .eta--later { background: #fff7ed; color: #9a3412; border-color: #fed7aa; } +.eta--watch { background: #fef3c7; color: #78350f; border-color: #fde68a; } .eta--safe { background: #dcfce7; color: #15803d; border-color: #86efac; } .spot-panel__eta-icon { font-size: 20px; line-height: 1; flex-shrink: 0; } diff --git a/frontend/src/components/SpotPanel/SpotPanel.jsx b/frontend/src/components/SpotPanel/SpotPanel.jsx index dc2dc54..edc1b91 100644 --- a/frontend/src/components/SpotPanel/SpotPanel.jsx +++ b/frontend/src/components/SpotPanel/SpotPanel.jsx @@ -3,7 +3,12 @@ import { api } from '../../api/client'; import usePushSubscription from '../../hooks/usePushSubscription'; import './SpotPanel.css'; -const LEVEL_LABEL = { low: 'OK', medium: 'Risque', high: 'Impact' }; +function scoreLabel(value, level) { + if (level === 'high') return 'Impact'; + if (level === 'medium') return 'Risque'; + if (value >= 15) return 'Veille'; + return 'OK'; +} const TYPE_ICON = { beach: '🏖', port: '⚓', surf: '🏄', fishing: '🎣' }; const TREND_CONFIG = { @@ -23,13 +28,14 @@ function computeEta(score, horizons) { return null; } -function etaLabel(etaHours) { - if (etaHours === 0) return { icon: '🚨', label: 'Impact en cours', cls: 'eta--now' }; - if (etaHours === 6) return { icon: '⚠️', label: 'Impact prévu dans ~6h', cls: 'eta--soon' }; - if (etaHours === 12) return { icon: '⚠️', label: 'Impact prévu dans ~12h', cls: 'eta--soon' }; - if (etaHours === 24) return { icon: '🕐', label: 'Impact prévu dans ~24h', cls: 'eta--later' }; - if (etaHours === 48) return { icon: '🕐', label: 'Impact prévu dans ~48h', cls: 'eta--later' }; - return { icon: '✅', label: 'Aucun impact prévu (48h)', cls: 'eta--safe' }; +function etaLabel(etaHours, score) { + if (etaHours === 0) return { icon: '🚨', label: 'Impact en cours', cls: 'eta--now' }; + if (etaHours === 6) return { icon: '⚠️', label: 'Impact prévu dans ~6h', cls: 'eta--soon' }; + if (etaHours === 12) return { icon: '⚠️', label: 'Impact prévu dans ~12h', cls: 'eta--soon' }; + if (etaHours === 24) return { icon: '🕐', label: 'Impact prévu dans ~24h', cls: 'eta--later' }; + if (etaHours === 48) return { icon: '🕐', label: 'Impact prévu dans ~48h', cls: 'eta--later' }; + if ((score ?? 0) >= 15) return { icon: '👁', label: 'Sargasses en surveillance', cls: 'eta--watch' }; + return { icon: '✅', label: 'Aucun impact prévu (48h)', cls: 'eta--safe' }; } const HORIZON_LABELS = { now: 'Maintenant', h6: '+6h', h12: '+12h', h24: '+24h', h48: '+48h' }; @@ -94,7 +100,7 @@ export default function SpotPanel({ spot, activeStep, onClose }) { : ( <> {activeStep === 'now' && (() => { - const eta = etaLabel(computeEta(data?.score, data?.horizons)); + const eta = etaLabel(computeEta(data?.score, data?.horizons), data?.score?.value); return (
{eta.icon} @@ -105,7 +111,7 @@ export default function SpotPanel({ spot, activeStep, onClose }) {
- {LEVEL_LABEL[lvl] ?? lvl} + {scoreLabel(displayScore.value, lvl)} {displayScore.value} /100