peak usability

This commit is contained in:
Polen 2026-04-02 14:45:06 -04:00
parent bd176b9895
commit cdec0834e9

View file

@ -132,6 +132,38 @@
.pin-icon { filter: drop-shadow(0 1px 3px rgba(0,0,0,0.35)); } .pin-icon { filter: drop-shadow(0 1px 3px rgba(0,0,0,0.35)); }
.cluster-info-tip {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px; height: 16px;
border-radius: 50%;
border: 1px solid var(--muted-foreground);
color: var(--muted-foreground);
font-size: 10px; font-weight: 700;
cursor: default;
flex-shrink: 0;
}
.cluster-info-tip:hover .cluster-info-tooltip { display: block; }
.cluster-info-tooltip {
display: none;
position: absolute;
left: 22px; top: 50%;
transform: translateY(-50%);
background: var(--card);
color: var(--card-foreground);
border: 1px solid var(--border);
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
padding: 10px 12px;
font-size: 12px; font-weight: 400;
white-space: nowrap;
z-index: 2000;
pointer-events: none;
line-height: 1.6;
}
.fuel-btn { .fuel-btn {
padding: 4px 12px; padding: 4px 12px;
border: 1px solid var(--border); border: 1px solid var(--border);
@ -259,6 +291,23 @@
<select id="region-select"> <select id="region-select">
<option value="">Toutes les régions</option> <option value="">Toutes les régions</option>
</select> </select>
<div style="display:flex; align-items:center; gap:6px; margin-bottom:10px;">
<div class="fuel-btns" id="cluster-btns" style="margin-bottom:0;">
<button class="fuel-btn cluster-btn" data-mode="min">Min</button>
<button class="fuel-btn cluster-btn active" data-mode="avg">Moy</button>
<button class="fuel-btn cluster-btn" data-mode="max">Max</button>
</div>
<div class="cluster-info-tip">
?
<div class="cluster-info-tooltip">
Prix affiché sur chaque groupe de stations :<br><br>
<strong>Min</strong> — prix le plus bas du groupe<br>
<strong>Moy</strong> — prix moyen du groupe<br>
<strong>Max</strong> — prix le plus élevé du groupe<br><br>
La couleur reflète également la valeur affichée.
</div>
</div>
</div>
<label for="price-slider">Prix max: <span id="slider-label">-</span></label> <label for="price-slider">Prix max: <span id="slider-label">-</span></label>
<input type="range" id="price-slider" min="0" max="300" step="0.5" value="300"> <input type="range" id="price-slider" min="0" max="300" step="0.5" value="300">
<div id="slider-value"> <div id="slider-value">
@ -397,6 +446,7 @@
let currentFuel = 'regular'; let currentFuel = 'regular';
let currentRegion = ''; let currentRegion = '';
let clusterMode = 'avg'; // 'min' | 'avg' | 'max'
let allStations = []; let allStations = [];
let allMarkers = []; let allMarkers = [];
let visibleSet = new Set(); let visibleSet = new Set();
@ -414,9 +464,12 @@
const count = cluster.getChildCount(); const count = cluster.getChildCount();
let fill, label; let fill, label;
if (prices.length > 0) { if (prices.length > 0) {
const avg = prices.reduce((a, b) => a + b, 0) / prices.length; let displayPrice;
fill = priceColor(avg, minPrice, maxPrice); if (clusterMode === 'min') displayPrice = Math.min(...prices);
label = avg.toFixed(1); else if (clusterMode === 'max') displayPrice = Math.max(...prices);
else displayPrice = prices.reduce((a, b) => a + b, 0) / prices.length;
fill = priceColor(displayPrice, minPrice, maxPrice);
label = displayPrice.toFixed(1);
} else { } else {
fill = '#9ca3af'; fill = '#9ca3af';
label = count; label = count;
@ -483,11 +536,20 @@
setTimeout(() => { loading.style.display = 'none'; }, 4000); setTimeout(() => { loading.style.display = 'none'; }, 4000);
}); });
document.querySelectorAll('.fuel-btn').forEach(btn => { document.querySelectorAll('.cluster-btn').forEach(btn => {
btn.addEventListener('click', () => {
if (btn.dataset.mode === clusterMode) return;
clusterMode = btn.dataset.mode;
document.querySelectorAll('.cluster-btn').forEach(b => b.classList.toggle('active', b.dataset.mode === clusterMode));
if (allStations.length) clusterGroup.refreshClusters();
});
});
document.querySelectorAll('.fuel-btn[data-fuel]').forEach(btn => {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
if (btn.dataset.fuel === currentFuel) return; if (btn.dataset.fuel === currentFuel) return;
currentFuel = btn.dataset.fuel; currentFuel = btn.dataset.fuel;
document.querySelectorAll('.fuel-btn').forEach(b => b.classList.toggle('active', b.dataset.fuel === currentFuel)); document.querySelectorAll('.fuel-btn[data-fuel]').forEach(b => b.classList.toggle('active', b.dataset.fuel === currentFuel));
if (allStations.length) rebuildMarkers(); if (allStations.length) rebuildMarkers();
}); });
}); });
@ -538,8 +600,11 @@
clusterGroup.clearLayers(); clusterGroup.clearLayers();
visibleSet.clear(); visibleSet.clear();
// Recompute min/max for the active fuel // Recompute min/max for the active fuel, scoped to the selected region
const prices = allStations.map(s => s[currentFuel]).filter(p => p > 0); const scopedStations = currentRegion
? allStations.filter(s => s.region === currentRegion)
: allStations;
const prices = scopedStations.map(s => s[currentFuel]).filter(p => p > 0);
minPrice = prices.length ? Math.min(...prices) : 0; minPrice = prices.length ? Math.min(...prices) : 0;
maxPrice = prices.length ? Math.max(...prices) : 300; maxPrice = prices.length ? Math.max(...prices) : 300;