dcrey7's picture
feat: zoom-aware level switching + zoom indicator
20972ee
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>French Property Prices</title>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css">
<link rel="stylesheet" href="/static/style.css">
</head>
<body class="dark-mode">
<div id="app">
<!-- Left control panel -->
<div id="panel">
<div class="panel-header" style="display:flex;justify-content:space-between;align-items:flex-start;">
<div>
<h1>Property Prices</h1>
<p class="subtitle">France &middot; &euro;/m&sup2; &middot; DVF 2020&ndash;2025</p>
</div>
<button class="theme-toggle" id="theme-toggle" title="Toggle light/dark mode">&#9790;</button>
</div>
<!-- Map level (radio buttons 3x2 grid) -->
<div class="panel-section">
<span class="section-label">Map Level</span>
<div class="level-radios">
<label class="level-radio"><input type="radio" name="map-level" value="0" checked><span>Country</span></label>
<label class="level-radio"><input type="radio" name="map-level" value="1"><span>Region</span></label>
<label class="level-radio"><input type="radio" name="map-level" value="2"><span>Dept</span></label>
<label class="level-radio"><input type="radio" name="map-level" value="3"><span>Commune</span></label>
<label class="level-radio"><input type="radio" name="map-level" value="4"><span>Postcode</span></label>
<label class="level-radio"><input type="radio" name="map-level" value="5"><span>Section</span></label>
</div>
</div>
<!-- Property Type -->
<div class="panel-section">
<span class="section-label">Property Type</span>
<div class="type-checkboxes">
<label class="type-cb"><input type="checkbox" id="cb-appartement" checked><span>Apartments</span></label>
<label class="type-cb"><input type="checkbox" id="cb-maison" checked><span>Houses</span></label>
</div>
</div>
<!-- Area list: scrollable list of items for current level -->
<div class="panel-section">
<span class="section-label" id="area-list-label">Areas</span>
<div id="area-list" class="area-list"></div>
</div>
<!-- Price range filter -->
<div class="panel-section">
<span class="section-label">Price Range (&euro;/m&sup2;)</span>
<div class="price-inputs">
<input type="number" id="price-min-input" value="200" min="0" max="50000" step="100">
<span class="price-sep">&ndash;</span>
<input type="number" id="price-max-input" value="25000" min="0" max="50000" step="100">
</div>
<div class="range-container">
<div class="slider-bg"></div>
<div class="slider-track" id="slider-track"></div>
<input type="range" id="price-min-slider" min="200" max="25000" value="200" step="100">
<input type="range" id="price-max-slider" min="200" max="25000" value="25000" step="100">
</div>
</div>
<!-- Search: geocoding autocomplete -->
<div class="panel-section search-section">
<span class="section-label">Search Place</span>
<div class="search-wrapper">
<input type="text" id="place-search" class="place-search" placeholder="Search a city or commune..." autocomplete="off">
<div id="search-dropdown" class="search-dropdown hidden"></div>
</div>
<div id="place-details" class="place-details hidden"></div>
</div>
<div class="footer">
Source: DVF (data.gouv.fr)<br>
Method: Time-weighted trimmed mean
</div>
</div>
<!-- Map -->
<div id="map">
<!-- Floating overlay: stat + legend -->
<div id="map-overlay" class="map-overlay">
<div class="country-stat">
<span id="stat-label" class="country-label">National Average</span>
<span id="stat-price" class="country-price">&mdash;</span>
<span id="stat-detail" class="stat-detail"></span>
<span id="zoom-indicator" class="zoom-indicator">Zoom: 4.0</span>
</div>
<div id="legend">
<div class="legend-bar"></div>
<div class="legend-labels">
<span id="legend-min">&mdash;</span>
<span id="legend-max">&mdash;</span>
</div>
</div>
</div>
</div>
</div>
<!-- Floating hover tooltip -->
<div id="tooltip" class="hidden"></div>
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
<script src="/static/app.js"></script>
</body>
</html>