dcrey7 commited on
Commit
6c5b825
·
1 Parent(s): 907e67b

feat: compact panel, map overlay stat+legend, 3x2 radio grid, section explore fix

Browse files

- Wider panel (340px), compact spacing, no scrollbar
- Move stat card + color scale to floating map overlay (top-left)
- Radio buttons in 3x2 grid instead of vertical list
- Legend simplified to min/max only (removed confusing mid value)
- Fix section explore list: call updateExploreList after section data loads
- Remove property type filter section from panel

Files changed (3) hide show
  1. static/app.js +5 -2
  2. static/index.html +15 -19
  3. static/style.css +51 -33
static/app.js CHANGED
@@ -439,7 +439,11 @@ async function loadVisibleSections() {
439
  }
440
  }
441
  await Promise.all(loadPromises);
442
- if (changed) updateSectionColors();
 
 
 
 
443
  } finally {
444
  _sectionLoadPending = false;
445
  }
@@ -561,7 +565,6 @@ function updateSectionColors() {
561
 
562
  function updateLegend(min, mid, max) {
563
  document.getElementById("legend-min").textContent = formatPrice(min);
564
- document.getElementById("legend-mid").textContent = formatPrice(mid);
565
  document.getElementById("legend-max").textContent = formatPrice(max);
566
  }
567
 
 
439
  }
440
  }
441
  await Promise.all(loadPromises);
442
+ if (changed) {
443
+ updateSectionColors();
444
+ updateExploreList();
445
+ updateDynamicStat();
446
+ }
447
  } finally {
448
  _sectionLoadPending = false;
449
  }
 
565
 
566
  function updateLegend(min, mid, max) {
567
  document.getElementById("legend-min").textContent = formatPrice(min);
 
568
  document.getElementById("legend-max").textContent = formatPrice(max);
569
  }
570
 
static/index.html CHANGED
@@ -19,16 +19,7 @@
19
  <button class="theme-toggle" id="theme-toggle" title="Toggle light/dark mode">&#9790;</button>
20
  </div>
21
 
22
- <!-- Dynamic average (updates per level/selection) -->
23
- <div class="panel-section">
24
- <div class="country-stat">
25
- <span id="stat-label" class="country-label">National Average</span>
26
- <span id="stat-price" class="country-price">&mdash;</span>
27
- <span id="stat-detail" class="stat-detail"></span>
28
- </div>
29
- </div>
30
-
31
- <!-- Map level (radio buttons) -->
32
  <div class="panel-section">
33
  <span class="section-label">Map Level</span>
34
  <div class="level-radios">
@@ -70,7 +61,7 @@
70
  </div>
71
  </div>
72
 
73
- <!-- Explore: search + dynamic top 10 -->
74
  <div class="panel-section explore-section">
75
  <div class="explore-header">
76
  <span class="section-label" id="explore-title">Top Cities</span>
@@ -91,14 +82,19 @@
91
 
92
  <!-- Map -->
93
  <div id="map">
94
- <!-- Floating legend overlay -->
95
- <div id="legend" class="map-legend">
96
- <span class="legend-title">Color Scale</span>
97
- <div class="legend-bar"></div>
98
- <div class="legend-labels">
99
- <span id="legend-min">&mdash;</span>
100
- <span id="legend-mid">&mdash;</span>
101
- <span id="legend-max">&mdash;</span>
 
 
 
 
 
102
  </div>
103
  </div>
104
  </div>
 
19
  <button class="theme-toggle" id="theme-toggle" title="Toggle light/dark mode">&#9790;</button>
20
  </div>
21
 
22
+ <!-- Map level (radio buttons 3x2 grid) -->
 
 
 
 
 
 
 
 
 
23
  <div class="panel-section">
24
  <span class="section-label">Map Level</span>
25
  <div class="level-radios">
 
61
  </div>
62
  </div>
63
 
64
+ <!-- Explore: search + dynamic top list -->
65
  <div class="panel-section explore-section">
66
  <div class="explore-header">
67
  <span class="section-label" id="explore-title">Top Cities</span>
 
82
 
83
  <!-- Map -->
84
  <div id="map">
85
+ <!-- Floating overlay: stat + legend -->
86
+ <div id="map-overlay" class="map-overlay">
87
+ <div class="country-stat">
88
+ <span id="stat-label" class="country-label">National Average</span>
89
+ <span id="stat-price" class="country-price">&mdash;</span>
90
+ <span id="stat-detail" class="stat-detail"></span>
91
+ </div>
92
+ <div id="legend">
93
+ <div class="legend-bar"></div>
94
+ <div class="legend-labels">
95
+ <span id="legend-min">&mdash;</span>
96
+ <span id="legend-max">&mdash;</span>
97
+ </div>
98
  </div>
99
  </div>
100
  </div>
static/style.css CHANGED
@@ -30,15 +30,15 @@ body {
30
 
31
  /* ---- Left Panel ---- */
32
  #panel {
33
- width: 300px;
34
- min-width: 300px;
35
  height: 100vh;
36
  overflow-y: auto;
37
  background: white;
38
- padding: 16px;
39
  display: flex;
40
  flex-direction: column;
41
- gap: 12px;
42
  border-right: 1px solid #d2d2d7;
43
  }
44
 
@@ -92,19 +92,19 @@ body {
92
  gap: 4px;
93
  }
94
 
95
- /* ---- Level Radio Buttons ---- */
96
  .level-radios {
97
- display: flex;
98
- flex-direction: column;
99
- gap: 2px;
100
  }
101
 
102
  .level-radio {
103
  display: flex;
104
  align-items: center;
105
- gap: 8px;
106
- padding: 6px 10px;
107
- border-radius: 8px;
108
  cursor: pointer;
109
  font-size: 0.8rem;
110
  font-weight: 500;
@@ -395,8 +395,8 @@ body {
395
  }
396
 
397
  /* ---- Legend ---- */
398
- /* ---- Floating Map Legend ---- */
399
- .map-legend {
400
  position: absolute;
401
  top: 12px;
402
  left: 12px;
@@ -404,33 +404,51 @@ body {
404
  background: rgba(255, 255, 255, 0.92);
405
  backdrop-filter: blur(8px);
406
  border-radius: 10px;
407
- padding: 10px 14px;
408
- min-width: 180px;
409
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
 
 
 
410
  }
411
 
412
- .legend-title {
413
- font-size: 0.68rem;
414
- font-weight: 700;
 
 
 
 
 
 
415
  text-transform: uppercase;
416
  letter-spacing: 0.5px;
417
  color: #86868b;
418
- display: block;
419
- margin-bottom: 6px;
 
 
 
 
 
 
 
 
 
420
  }
421
 
422
  .legend-bar {
423
- height: 10px;
424
- border-radius: 5px;
425
  background: linear-gradient(to right, #028758, #FFF64E, #CC000A);
426
  }
427
 
428
  .legend-labels {
429
  display: flex;
430
  justify-content: space-between;
431
- font-size: 0.68rem;
432
  color: #86868b;
433
- margin-top: 3px;
434
  }
435
 
436
  /* ---- Country Stat ---- */
@@ -775,19 +793,19 @@ body.dark-mode .cb-item-price {
775
 
776
  /* Dark mode stat */
777
  body.dark-mode .country-stat {
778
- background: #2a2a2a;
779
  }
780
 
781
  body.dark-mode .country-label {
782
- color: #888;
783
  }
784
 
785
- body.dark-mode #country-price {
786
  color: #ffffff;
787
  }
788
 
789
  body.dark-mode .stat-detail {
790
- color: #888;
791
  }
792
 
793
  /* Dark mode price inputs */
@@ -818,18 +836,18 @@ body.dark-mode .range-container input[type="range"]::-moz-range-thumb {
818
  border-color: #2a2a2a;
819
  }
820
 
821
- /* Dark mode legend */
822
- body.dark-mode .map-legend {
823
  background: rgba(36, 36, 36, 0.92);
824
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
825
  }
826
 
827
- body.dark-mode .legend-title {
828
- color: #888;
829
  }
830
 
831
  body.dark-mode .legend-labels {
832
- color: #888;
833
  }
834
 
835
  /* Dark mode count pills */
 
30
 
31
  /* ---- Left Panel ---- */
32
  #panel {
33
+ width: 340px;
34
+ min-width: 340px;
35
  height: 100vh;
36
  overflow-y: auto;
37
  background: white;
38
+ padding: 14px 16px;
39
  display: flex;
40
  flex-direction: column;
41
+ gap: 8px;
42
  border-right: 1px solid #d2d2d7;
43
  }
44
 
 
92
  gap: 4px;
93
  }
94
 
95
+ /* ---- Level Radio Buttons (3x2 grid) ---- */
96
  .level-radios {
97
+ display: grid;
98
+ grid-template-columns: repeat(3, 1fr);
99
+ gap: 2px 6px;
100
  }
101
 
102
  .level-radio {
103
  display: flex;
104
  align-items: center;
105
+ gap: 6px;
106
+ padding: 5px 6px;
107
+ border-radius: 6px;
108
  cursor: pointer;
109
  font-size: 0.8rem;
110
  font-weight: 500;
 
395
  }
396
 
397
  /* ---- Legend ---- */
398
+ /* ---- Floating Map Overlay (stat + legend) ---- */
399
+ .map-overlay {
400
  position: absolute;
401
  top: 12px;
402
  left: 12px;
 
404
  background: rgba(255, 255, 255, 0.92);
405
  backdrop-filter: blur(8px);
406
  border-radius: 10px;
407
+ padding: 12px 16px;
408
+ min-width: 200px;
409
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
410
+ display: flex;
411
+ flex-direction: column;
412
+ gap: 8px;
413
  }
414
 
415
+ .map-overlay .country-stat {
416
+ background: none;
417
+ border-radius: 0;
418
+ padding: 0;
419
+ text-align: left;
420
+ }
421
+
422
+ .map-overlay .country-label {
423
+ font-size: 0.65rem;
424
  text-transform: uppercase;
425
  letter-spacing: 0.5px;
426
  color: #86868b;
427
+ }
428
+
429
+ .map-overlay .country-price {
430
+ font-size: 1.3rem;
431
+ font-weight: 700;
432
+ color: #1d1d1f;
433
+ }
434
+
435
+ .map-overlay .stat-detail {
436
+ font-size: 0.65rem;
437
+ color: #86868b;
438
  }
439
 
440
  .legend-bar {
441
+ height: 8px;
442
+ border-radius: 4px;
443
  background: linear-gradient(to right, #028758, #FFF64E, #CC000A);
444
  }
445
 
446
  .legend-labels {
447
  display: flex;
448
  justify-content: space-between;
449
+ font-size: 0.65rem;
450
  color: #86868b;
451
+ margin-top: 2px;
452
  }
453
 
454
  /* ---- Country Stat ---- */
 
793
 
794
  /* Dark mode stat */
795
  body.dark-mode .country-stat {
796
+ background: none;
797
  }
798
 
799
  body.dark-mode .country-label {
800
+ color: #999;
801
  }
802
 
803
+ body.dark-mode .country-price {
804
  color: #ffffff;
805
  }
806
 
807
  body.dark-mode .stat-detail {
808
+ color: #999;
809
  }
810
 
811
  /* Dark mode price inputs */
 
836
  border-color: #2a2a2a;
837
  }
838
 
839
+ /* Dark mode map overlay */
840
+ body.dark-mode .map-overlay {
841
  background: rgba(36, 36, 36, 0.92);
842
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
843
  }
844
 
845
+ body.dark-mode .map-overlay .country-price {
846
+ color: #ffffff;
847
  }
848
 
849
  body.dark-mode .legend-labels {
850
+ color: #999;
851
  }
852
 
853
  /* Dark mode count pills */