From ad6c197f5c08e741cd39acc312cdd97560a5f7de Mon Sep 17 00:00:00 2001 From: Poulpe Date: Mon, 27 Apr 2026 13:45:20 +0000 Subject: [PATCH] feat(viewer): calendar date-picker + mission name from backend 8766 - date-picker bar with datalist highlighting available dates - fetch /api/data-dates from 192.168.0.83:8766 on load - mission name + session count shown on date change - Aujourd hui button sets today - slider 24h intact --- viewer/index.html | 129 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 2 deletions(-) diff --git a/viewer/index.html b/viewer/index.html index 4740ad8..390e63c 100644 --- a/viewer/index.html +++ b/viewer/index.html @@ -9,6 +9,51 @@ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: monospace; background: #1a1a2e; color: #e0e0e0; display: flex; flex-direction: column; height: 100vh; } #map { flex: 1; } + + /* ── top bar: date picker ── */ + #datebar { + background: #0d1b2a; + padding: 6px 12px; + display: flex; + align-items: center; + gap: 10px; + border-bottom: 1px solid #0f3460; + flex-wrap: wrap; + } + #datebar label { font-size: 11px; color: #a0c4ff; white-space: nowrap; } + #date-picker { + background: #16213e; + color: #e0e0e0; + border: 1px solid #0f3460; + padding: 4px 8px; + font-family: monospace; + font-size: 12px; + cursor: pointer; + } + #date-picker::-webkit-calendar-picker-indicator { filter: invert(1); } + #btn-today { + background: #0f3460; + color: #a0c4ff; + border: 1px solid #1a5276; + padding: 4px 10px; + font-family: monospace; + font-size: 11px; + cursor: pointer; + } + #btn-today:hover { background: #1a5276; } + #mission-label { + font-size: 12px; + color: #e94560; + font-weight: bold; + min-width: 160px; + } + #dates-hint { + font-size: 10px; + color: #556; + white-space: nowrap; + } + + /* ── bottom bar: slider ── */ #controls { background: #16213e; padding: 8px 12px; @@ -23,7 +68,19 @@ + + +
+ + + + + Chargement calendrier… +
+
+ +
USV Track @@ -47,7 +104,6 @@ const seamarks = L.tileLayer('https://tiles.openseamap.org/seamark/{z}/{x}/{y}.p opacity: 0.8, }); -// GEBCO bathymetry (tile-based, simpler than WMS) const gebco = L.tileLayer( 'https://tiles.arcgis.com/tiles/C8EMgrsFcRFL6LrL/arcgis/rest/services/GEBCO_basemap_NCEI/MapServer/tile/{z}/{y}/{x}', { @@ -78,7 +134,74 @@ function makeArrowIcon(heading) { }); } -// ── Data loading ────────────────────────────────────────────────────────── +// ── Calendar data ───────────────────────────────────────────────────────── +const BACKEND = 'http://192.168.0.83:8766'; +let dataMissions = {}; // date → {missions, session_count} + +async function loadCalendar() { + try { + const resp = await fetch(`${BACKEND}/api/data-dates`); + if (!resp.ok) throw new Error(`HTTP ${resp.status}`); + const json = await resp.json(); + json.dates.forEach(d => { + dataMissions[d.date] = { missions: d.missions, session_count: d.session_count }; + }); + + const availDates = Object.keys(dataMissions).sort(); + const picker = document.getElementById('date-picker'); + + if (availDates.length > 0) { + picker.min = availDates[0]; + picker.max = availDates[availDates.length - 1]; + } + + // Highlight available dates via custom attribute list (CSS trick) + // We inject a datalist for browsers that support it + const dl = document.createElement('datalist'); + dl.id = 'available-dates'; + availDates.forEach(d => { + const opt = document.createElement('option'); + opt.value = d; + dl.appendChild(opt); + }); + document.body.appendChild(dl); + picker.setAttribute('list', 'available-dates'); + + document.getElementById('dates-hint').textContent = + `${availDates.length} dates avec données`; + + // Select most recent date by default + if (availDates.length > 0) { + picker.value = availDates[availDates.length - 1]; + onDateChange(picker.value); + } + } catch (e) { + document.getElementById('dates-hint').textContent = 'Calendrier indispo: ' + e.message; + } +} + +function onDateChange(date) { + const label = document.getElementById('mission-label'); + const info = dataMissions[date]; + if (info) { + label.textContent = info.missions.join(', ') + ` (${info.session_count} session${info.session_count > 1 ? 's' : ''})`; + label.style.color = '#00e676'; + } else { + label.textContent = 'Aucune donnée pour cette date'; + label.style.color = '#666'; + } +} + +document.getElementById('date-picker').addEventListener('change', e => onDateChange(e.target.value)); + +document.getElementById('btn-today').addEventListener('click', () => { + const today = new Date().toISOString().split('T')[0]; + const picker = document.getElementById('date-picker'); + picker.value = today; + onDateChange(today); +}); + +// ── Track data loading ──────────────────────────────────────────────────── let points = []; let trackLayer = null; let marker = null; @@ -136,6 +259,8 @@ function updateInfo(idx) { `[${idx+1}/${points.length}] ${p.t} | Lat: ${p.lat.toFixed(6)} Lon: ${p.lon.toFixed(6)} | Cap: ${hdg}`; } +// ── Init ────────────────────────────────────────────────────────────────── +loadCalendar(); loadData();