From 4e73e17656939c0e371a0eca46e86ad48a76fec9 Mon Sep 17 00:00:00 2001 From: z0rayy Date: Thu, 11 Jun 2026 05:28:31 +0700 Subject: [PATCH] feat: implement responsive UI layouts and collapsible control panels across application pages --- admin.html | 126 +++++++++++++++++++++++++++++++++++-- index.php | 20 ++++-- jalan-parsil.html | 155 +++++++++++++++++++++++++++++++++------------- js/app.js | 2 + login.html | 10 ++- poverty.html | 98 ++++++++++++++++++++++++----- spbu.html | 107 ++++++++++++++++++++++++++++---- 7 files changed, 435 insertions(+), 83 deletions(-) diff --git a/admin.html b/admin.html index ff83ae8..ecfdcd2 100644 --- a/admin.html +++ b/admin.html @@ -1099,6 +1099,67 @@ } } + /* ---- Floating Panels Toggle ---- */ + .map-floating-panel { + transition: width 0.3s ease, height 0.3s ease, background 0.3s ease; + overflow: hidden; + } + .map-floating-panel .panel-icon, + .map-floating-panel .panel-close-btn { + display: none; + } + .map-floating-panel .panel-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + } + + @media (max-width: 900px) { + .map-floating-panel.collapsed { + width: 44px !important; + height: 44px !important; + min-height: 44px !important; + padding: 0 !important; + display: flex !important; + align-items: center; + justify-content: center; + cursor: pointer; + } + .map-floating-panel.collapsed:hover { + background: rgba(59, 130, 246, 0.2) !important; + border-color: rgba(59, 130, 246, 0.5) !important; + } + .map-floating-panel.collapsed > *:not(.panel-icon) { + display: none !important; + } + .map-floating-panel .panel-icon { + display: none; + font-size: 20px; + line-height: 1; + } + .map-floating-panel.collapsed .panel-icon { + display: block; + } + .map-floating-panel .panel-close-btn { + display: flex; + background: none; + border: none; + color: var(--clr-muted); + cursor: pointer; + font-size: 18px; + line-height: 1; + padding: 4px; + border-radius: 4px; + align-items: center; + justify-content: center; + } + .map-floating-panel .panel-close-btn:hover { + color: var(--clr-text); + background: rgba(255,255,255,0.1); + } + } + /* ---- Custom Marker ---- */ .custom-marker { display: flex; justify-content: center; align-items: center; @@ -1163,6 +1224,46 @@ } .routing-panel h3 { font-size: 12px; font-weight: 700; color: #f1f5f9; margin-bottom: 12px; border-bottom: 1px solid #334155; padding-bottom: 8px; text-transform: uppercase; margin-top:0; } + @media (max-width: 900px) { + .app-wrapper { height: 100dvh; } + header { height: auto; min-height: 64px; padding: 10px 14px; gap: 10px; flex-wrap: wrap; } + .header-title h1 { font-size: 16px; } + .header-actions { width: 100%; justify-content: flex-start; flex-wrap: wrap; } + .content-panel-header { align-items: flex-start; flex-direction: column; gap: 10px; } + .content-panel-header .btn-group { width: 100%; flex-wrap: wrap; } + .content-panel-header .btn-group .btn { flex: 1; min-width: 130px; } + .table { min-width: 680px; } + .modal { width: calc(100vw - 24px); max-height: calc(100dvh - 24px); } + .modal-footer { flex-wrap: wrap; } + .modal-footer .btn { flex: 1; min-width: 120px; } + .search-panel { left: 82px; right: 12px; top: 12px; width: auto; margin-left: 0; transform: none; } + .routing-panel { top: auto; right: 12px; left: 82px; bottom: 12px; width: auto; } + } + + @media (max-width: 560px) { + .sidebar { width: 56px; } + .sidebar-header { padding: 12px 8px; justify-content: center; } + .sidebar-logo-icon { width: 34px; height: 34px; font-size: 14px; } + .sidebar-toggle, + .sidebar-logo-text, + .sidebar-item-text, + .sidebar-item-badge, + .sidebar-section-title { display: none !important; } + .sidebar-nav { padding: 10px 0; } + .sidebar-section { padding: 8px 0; } + .sidebar-item { padding: 12px 14px; justify-content: center; } + .content-panel-body { padding: 12px; } + .search-box input, + .form-group input, + .form-group select, + .form-group textarea { font-size: 16px; } + .search-panel { left: 68px; right: 8px; top: 8px; padding: 10px; } + .search-results { max-height: 135px; } + .routing-panel { left: 68px; right: 8px; bottom: 8px; padding: 10px; } + .routing-panel h3, + .search-panel h3 { font-size: 11px; margin-bottom: 8px; } + } + @@ -1272,8 +1373,12 @@
-
-

🔍 Pencarian Global

+
+
🔍
+
+

🔍 Pencarian Global

+ +
@@ -1295,14 +1400,18 @@
--> -
-
⊕ Tambah Data
+
⊕
+
+
⊕ Tambah Data
+ +
📍 Titik
-
-
SPBU
+
+
📋
+
+
Legenda
+ +
+
SPBU
Beroperasi 24 Jam diff --git a/index.php b/index.php index 50793cf..95cd5cb 100644 --- a/index.php +++ b/index.php @@ -14,9 +14,9 @@ .bg-pattern { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-image: radial-gradient(#334155 1px, transparent 1px); background-size: 40px 40px; opacity: 0.3; z-index: -1; } .glow { position: absolute; width: 600px; height: 600px; background: radial-gradient(circle, rgba(59,130,246,0.15) 0%, rgba(15,23,42,0) 70%); top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: -1; pointer-events: none; } - header { text-align: center; margin-bottom: 60px; z-index: 10; } - header h1 { font-size: 42px; font-weight: 800; background: linear-gradient(135deg, #60a5fa, #a855f7); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 16px; } - header p { font-size: 18px; color: #cbd5e1; max-width: 600px; margin: 0 auto; line-height: 1.6; } + header { text-align: center; margin-bottom: 48px; z-index: 10; padding: 0 20px; } + header h1 { font-size: clamp(32px, 5vw, 42px); font-weight: 800; background: linear-gradient(135deg, #60a5fa, #a855f7); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 16px; } + header p { font-size: clamp(15px, 2.4vw, 18px); color: #cbd5e1; max-width: 640px; margin: 0 auto; line-height: 1.6; } .cards-container { display: flex; gap: 28px; max-width: 1160px; width: 100%; padding: 0 20px; z-index: 10; flex-wrap: wrap; justify-content: center; } @@ -48,9 +48,17 @@ .admin-link:hover { color: #f8fafc; } @media (max-width: 768px) { - body { justify-content: flex-start; padding-top: 32px; } - .choice-card { width: 100%; } - header h1 { font-size: 32px; } + body { justify-content: flex-start; padding: 32px 0 86px; } + header { margin-bottom: 28px; } + .cards-container { gap: 18px; padding: 0 14px; } + .choice-card { width: 100%; min-width: 0; max-width: 430px; padding: 28px 22px; } + .choice-card .icon-box { width: 68px; height: 68px; font-size: 30px; margin-bottom: 18px; } + .choice-card h2 { font-size: 21px; } + .admin-link { bottom: 18px; } + } + + @media (min-width: 769px) and (max-width: 1100px) { + .choice-card { width: calc(50% - 18px); } } diff --git a/jalan-parsil.html b/jalan-parsil.html index a98eea7..03778d5 100644 --- a/jalan-parsil.html +++ b/jalan-parsil.html @@ -112,6 +112,14 @@ .legend-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; color: var(--clr-text); font-size: 12px; } .legend-line { width: 24px; height: 0; border-top: 4px solid; border-radius: 999px; flex-shrink: 0; } .legend-swatch { width: 14px; height: 14px; border-radius: 4px; flex-shrink: 0; border: 1px solid rgba(255,255,255,.3); } + .panel-toggle { + width: 100%; display: none; align-items: center; justify-content: space-between; gap: 10px; + background: transparent; border: none; color: var(--clr-text); cursor: pointer; + font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; padding: 0; + } + .panel-toggle .toggle-icon { color: var(--clr-muted); transition: transform var(--transition); } + .panel-collapsed .panel-body { display: none; } + .panel-collapsed .toggle-icon { transform: rotate(-90deg); } .popup-title { font-weight: 700; color: #0f172a; margin-bottom: 4px; } .popup-row { font-size: 12px; line-height: 1.5; } @@ -119,15 +127,51 @@ @media (max-width: 900px) { .sidebar { width: var(--sidebar-collapsed); } .sidebar-logo-text, .sidebar-item-text, .sidebar-section-title { display: none; } + .sidebar-header { padding: 16px 14px; } header { align-items: flex-start; flex-direction: column; padding: 10px 14px; } + .header-title h1 { font-size: 16px; } + .header-breadcrumb { font-size: 12px; } .search-panel, .filter-panel, .stats-panel, .legend-panel { left: 12px; right: 12px; width: auto; } .search-panel { top: 12px; } .filter-panel { top: 190px; } - .stats-panel { display: none; } + .stats-panel { bottom: 58px; } .legend-panel { bottom: 12px; } } + + @media (max-width: 760px) { + .app-wrapper { height: 100dvh; } + .sidebar { width: 56px; } + .sidebar-header { padding: 12px 8px; justify-content: center; } + .sidebar-logo-icon { width: 34px; height: 34px; font-size: 12px; } + .sidebar-toggle { display: none; } + .sidebar-nav { padding: 10px 0; } + .sidebar-item { padding: 12px 14px; justify-content: center; } + .header-actions { width: 100%; justify-content: space-between; } + .search-panel { top: 10px; padding: 10px; } + .search-results { max-height: 112px; } + .filter-panel { top: 58px; padding: 10px; } + .panel-toggle { display: flex; } + .search-panel h3, + .filter-panel h3, + .stats-panel h3, + .legend-panel h3 { display: none; } + .panel-body { margin-top: 10px; } + .mode-grid { gap: 6px; margin-bottom: 8px; } + .mode-btn { padding: 7px; font-size: 11px; } + .field-label { margin: 7px 0 4px; } + .ctrl-input, .ctrl-select { padding: 8px 10px; font-size: 12px; } + .analysis-box { margin-top: 8px; padding-top: 8px; max-height: 74px; overflow-y: auto; } + .legend-panel { bottom: 10px; padding: 10px; } + .legend-row { font-size: 11px; margin-bottom: 5px; } + } + + @media (max-width: 420px) { + .header-breadcrumb { display: none; } + .count-pill, .refresh-btn { font-size: 12px; padding: 5px 9px; } + .filter-panel { top: 56px; } + } @@ -176,67 +220,79 @@
+

Pencarian

- -
+
+ +
+
+

Filter & Analisis

-
- - - - -
+
+
+ + + + +
- - + + - - + + - - + + -
- Klik satu parsil untuk melihat jalan terdekat dan estimasi jaraknya. +
+ Klik satu parsil untuk melihat jalan terdekat dan estimasi jaraknya. +
+

Statistik Data

-
-
0
Total jalan tampil
-
0
Total parsil tampil
-
0 km
Akumulasi panjang jalan
-
0 m2
Akumulasi luas parsil
+
+
+
0
Total jalan tampil
+
0
Total parsil tampil
+
0 km
Akumulasi panjang jalan
+
0 m2
Akumulasi luas parsil
+
+

Legenda

-
Jalan Nasional
-
Jalan Provinsi
-
Jalan Kabupaten
-
Parsil SHM
-
Parsil HGB/HGU/HP
+
+
Jalan Nasional
+
Jalan Provinsi
+
Jalan Kabupaten
+
Parsil SHM
+
Parsil HGB/HGU/HP
+
@@ -249,6 +305,19 @@ document.getElementById('sidebar').classList.toggle('collapsed'); }); + function setupCollapsiblePanels() { + document.querySelectorAll('[data-panel-toggle]').forEach(btn => { + const panel = btn.closest('.panel'); + btn.addEventListener('click', () => panel.classList.toggle('panel-collapsed')); + }); + if (window.matchMedia('(max-width: 760px)').matches) { + document.querySelectorAll('.search-panel, .filter-panel, .stats-panel, .legend-panel').forEach(panel => { + panel.classList.add('panel-collapsed'); + }); + } + } + setupCollapsiblePanels(); + const map = L.map('map').setView([-0.026, 109.342], 13); const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap', maxZoom: 19 }); const dark = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', { maxZoom: 19 }); diff --git a/js/app.js b/js/app.js index 4f06d42..5c1066f 100644 --- a/js/app.js +++ b/js/app.js @@ -894,6 +894,7 @@ function initMap() { L.control.layers(baseMaps).addTo(map); // Initialize Geoman Controls (only if Geoman library is loaded) + /* if (map.pm && typeof map.pm.addControls === 'function') { map.pm.addControls({ position: 'topleft', @@ -906,6 +907,7 @@ function initMap() { removalMode: false }); } + */ // ALWAYS set mapInstance — regardless of whether Geoman loaded window.appState.mapInstance = map; diff --git a/login.html b/login.html index bfa88a3..3569b46 100644 --- a/login.html +++ b/login.html @@ -7,7 +7,7 @@ diff --git a/poverty.html b/poverty.html index fdc2121..9a86b85 100644 --- a/poverty.html +++ b/poverty.html @@ -135,6 +135,14 @@ .legend-panel h3 { font-size: 11px; font-weight: 700; color: var(--clr-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; } .legend-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; color: var(--clr-text); font-size: 12px; } .legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; } + .panel-toggle { + width: 100%; display: none; align-items: center; justify-content: space-between; gap: 10px; + background: transparent; border: none; color: var(--clr-text); cursor: pointer; + font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; padding: 0; + } + .panel-toggle .toggle-icon { color: var(--clr-muted); transition: transform var(--transition); } + .panel-collapsed .panel-body { display: none; } + .panel-collapsed .toggle-icon { transform: rotate(-90deg); } /* ---- Popup Slider ---- */ .popup-slider-wrap { margin-top: 10px; } @@ -172,6 +180,48 @@ 0% { transform: scale(0.5); opacity: 1; } 100% { transform: scale(1.5); opacity: 0; } } + + @media (max-width: 1024px) { + .sidebar { width: var(--sidebar-collapsed); } + .sidebar-logo-text, + .sidebar-item-text, + .sidebar-section-title, + .sidebar-item-user { display: none; } + .sidebar-header { padding: 16px 14px; } + header { height: auto; min-height: 64px; padding: 10px 14px; } + .header-title h1 { font-size: 16px; } + .header-breadcrumb { font-size: 12px; } + } + + @media (max-width: 760px) { + .app-wrapper { height: 100dvh; } + .sidebar { width: 56px; } + .sidebar-header { padding: 12px 8px; justify-content: center; } + .sidebar-logo-icon { width: 34px; height: 34px; font-size: 12px; } + .sidebar-toggle { display: none; } + .sidebar-nav { padding: 10px 0; } + .sidebar-item { padding: 12px 14px; justify-content: center; } + .search-panel, + .legend-panel { + left: 10px; right: 10px; width: auto; + } + .search-panel { top: 10px; padding: 10px; } + .search-results { max-height: 105px; } + .search-panel h3 { font-size: 11px; margin-bottom: 8px; } + .panel-toggle { display: flex; } + .search-panel h3, + .legend-panel h3 { display: none; } + .panel-body { margin-top: 10px; } + .legend-panel { bottom: 10px; padding: 10px; } + .legend-panel h3 { margin-bottom: 7px; } + .legend-row { font-size: 11px; margin-bottom: 5px; } + } + + @media (max-width: 420px) { + .header-breadcrumb { display: none; } + .search-panel { top: 8px; } + .ctrl-input { padding: 8px 10px; font-size: 12px; } + } @@ -222,28 +272,33 @@
+

Pencarian

- -
RUMAH IBADAH
-
- -
-
+
+
RUMAH IBADAH
+
+ +
+
-
PENDUDUK MISKIN
-
- +
PENDUDUK MISKIN
+
+ +
+
-
+

Legenda

-
Rumah Ibadah
-
Penduduk Miskin (Dalam Radius)
-
Penduduk Miskin (Luar Radius)
-
-
💡 Klik Rumah Ibadah untuk atur radius jangkauan
+
+
Rumah Ibadah
+
Penduduk Miskin (Dalam Radius)
+
Penduduk Miskin (Luar Radius)
+
+
💡 Klik Rumah Ibadah untuk atur radius jangkauan
+
@@ -257,6 +312,19 @@ document.getElementById('sidebar').classList.toggle('collapsed'); }); + function setupCollapsiblePanels() { + document.querySelectorAll('[data-panel-toggle]').forEach(btn => { + const panel = btn.closest('.search-panel, .legend-panel'); + btn.addEventListener('click', () => panel.classList.toggle('panel-collapsed')); + }); + if (window.matchMedia('(max-width: 760px)').matches) { + document.querySelectorAll('.search-panel, .legend-panel').forEach(panel => { + panel.classList.add('panel-collapsed'); + }); + } + } + setupCollapsiblePanels(); + // Global state let ibadahData = [], miskinData = []; let ibadahLayer, miskinLayer, map; diff --git a/spbu.html b/spbu.html index 3d1e252..3386948 100644 --- a/spbu.html +++ b/spbu.html @@ -147,6 +147,14 @@ .legend-panel h3 { font-size: 11px; font-weight: 700; color: var(--clr-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; } .legend-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; color: var(--clr-text); font-size: 12px; } .legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; } + .panel-toggle { + width: 100%; display: none; align-items: center; justify-content: space-between; gap: 10px; + background: transparent; border: none; color: var(--clr-text); cursor: pointer; + font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; padding: 0; + } + .panel-toggle .toggle-icon { color: var(--clr-muted); transition: transform var(--transition); } + .panel-collapsed .panel-body { display: none; } + .panel-collapsed .toggle-icon { transform: rotate(-90deg); } /* ---- Custom Marker ---- */ .custom-marker { @@ -175,6 +183,59 @@ 0% { transform: scale(0.5); opacity: 1; } 100% { transform: scale(1.5); opacity: 0; } } + + @media (max-width: 1024px) { + .sidebar { width: var(--sidebar-collapsed); } + .sidebar-logo-text, + .sidebar-item-text, + .sidebar-section-title { display: none; } + .sidebar-header { padding: 16px 14px; } + header { height: auto; min-height: 64px; padding: 10px 14px; gap: 10px; flex-wrap: wrap; } + .header-title h1 { font-size: 16px; } + .header-breadcrumb { font-size: 12px; } + } + + @media (max-width: 760px) { + .app-wrapper { height: 100dvh; } + .sidebar { width: 56px; } + .sidebar-header { padding: 12px 8px; justify-content: center; } + .sidebar-logo-icon { width: 34px; height: 34px; font-size: 12px; } + .sidebar-toggle { display: none; } + .sidebar-nav { padding: 10px 0; } + .sidebar-item { padding: 12px 14px; justify-content: center; } + header { align-items: flex-start; } + header > div:last-child { width: 100%; justify-content: space-between; } + .content-area { min-height: 0; } + .search-panel, + .controls-panel, + .legend-panel { + left: 10px; right: 10px; width: auto; + } + .search-panel { top: 10px; padding: 10px; } + .search-results { max-height: 130px; } + .controls-panel { top: 142px; padding: 10px; } + .controls-panel h3, + .search-panel h3 { font-size: 11px; margin-bottom: 8px; } + .panel-toggle { display: flex; } + .search-panel h3, + .controls-panel h3, + .legend-panel h3 { display: none; } + .search-panel, + .controls-panel, + .legend-panel { padding: 10px; } + .panel-body { margin-top: 10px; } + .ctrl-btn { padding: 9px; font-size: 12px; } + .legend-panel { bottom: 10px; padding: 10px; } + .legend-panel h3 { margin-bottom: 7px; } + .legend-row { font-size: 11px; margin-bottom: 5px; } + } + + @media (max-width: 420px) { + .search-panel { top: 8px; } + .controls-panel { top: 136px; } + .header-breadcrumb { display: none; } + #data-count, #btn-refresh { font-size: 12px !important; padding: 5px 9px !important; } + } @@ -228,29 +289,38 @@
+

Cari SPBU

-
- +
+
+ +
+
-
+

📍 Lokasi & Rute

- - -
- SPBU Terdekat:
- -
- Jarak: - km +
+ + +
+ SPBU Terdekat:
+ -
+ Jarak: - km +
+

Legenda

-
SPBU 24 Jam
-
SPBU Tidak 24 Jam
-
Lokasi Anda
+
+
SPBU 24 Jam
+
SPBU Tidak 24 Jam
+
Lokasi Anda
+
@@ -264,6 +334,19 @@ document.getElementById('sidebar').classList.toggle('collapsed'); }); + function setupCollapsiblePanels() { + document.querySelectorAll('[data-panel-toggle]').forEach(btn => { + const panel = btn.closest('.search-panel, .controls-panel, .legend-panel'); + btn.addEventListener('click', () => panel.classList.toggle('panel-collapsed')); + }); + if (window.matchMedia('(max-width: 760px)').matches) { + document.querySelectorAll('.search-panel, .controls-panel, .legend-panel').forEach(panel => { + panel.classList.add('panel-collapsed'); + }); + } + } + setupCollapsiblePanels(); + // Init Map const map = L.map('map').setView([-0.026, 109.342], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {