feat(ui): unify Decision Dashboard & Simulation Predictions into single seamless command center
Browse files- frontend/app.js +11 -35
- frontend/index.html +91 -153
- frontend/style.css +3 -3
frontend/app.js
CHANGED
|
@@ -173,32 +173,27 @@ function switchPage(pageId) {
|
|
| 173 |
loadAlertsFeed();
|
| 174 |
} else if (pageId === "page-autopilot") {
|
| 175 |
loadAutopilotFeed();
|
| 176 |
-
} else if (pageId === "page-
|
|
|
|
| 177 |
if (lastPredictionData) {
|
| 178 |
updateDecisionDashboard(lastPredictionData, selectedLocation);
|
| 179 |
-
} else {
|
| 180 |
-
runPrediction();
|
| 181 |
}
|
| 182 |
-
} else if (pageId === "page-predictor" && map) {
|
| 183 |
-
setTimeout(() => { map.invalidateSize(); }, 200);
|
| 184 |
}
|
| 185 |
}
|
| 186 |
|
| 187 |
window.switchPage = switchPage;
|
| 188 |
|
| 189 |
-
// Dynamically Populate
|
| 190 |
function populateLocationDropdown() {
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
selectEl.appendChild(opt);
|
| 199 |
-
});
|
| 200 |
-
selectEl.value = selectedLocation;
|
| 201 |
});
|
|
|
|
| 202 |
}
|
| 203 |
|
| 204 |
// Calculate Haversine Distance between two coordinate arrays [lat, lon]
|
|
@@ -245,25 +240,6 @@ if (eventOverride) {
|
|
| 245 |
if (locationSelect) {
|
| 246 |
locationSelect.addEventListener("change", (e) => {
|
| 247 |
selectedLocation = e.target.value;
|
| 248 |
-
if (decLocationSelect) decLocationSelect.value = selectedLocation;
|
| 249 |
-
const pop = KECAMATAN_DATABASE[selectedLocation]?.population_jiwa || 100000;
|
| 250 |
-
if (eventOverride) {
|
| 251 |
-
eventOverride.value = pop;
|
| 252 |
-
}
|
| 253 |
-
if (eventOverrideVal) {
|
| 254 |
-
eventOverrideVal.textContent = `${pop.toLocaleString()} Jiwa (BPS)`;
|
| 255 |
-
}
|
| 256 |
-
updateActiveMapMarker(selectedLocation);
|
| 257 |
-
panToLocation(selectedLocation);
|
| 258 |
-
fetchLiveWeather(selectedLocation);
|
| 259 |
-
runPrediction();
|
| 260 |
-
});
|
| 261 |
-
}
|
| 262 |
-
|
| 263 |
-
if (decLocationSelect) {
|
| 264 |
-
decLocationSelect.addEventListener("change", (e) => {
|
| 265 |
-
selectedLocation = e.target.value;
|
| 266 |
-
if (locationSelect) locationSelect.value = selectedLocation;
|
| 267 |
const pop = KECAMATAN_DATABASE[selectedLocation]?.population_jiwa || 100000;
|
| 268 |
if (eventOverride) {
|
| 269 |
eventOverride.value = pop;
|
|
|
|
| 173 |
loadAlertsFeed();
|
| 174 |
} else if (pageId === "page-autopilot") {
|
| 175 |
loadAutopilotFeed();
|
| 176 |
+
} else if (pageId === "page-predictor") {
|
| 177 |
+
if (map) setTimeout(() => { map.invalidateSize(); }, 200);
|
| 178 |
if (lastPredictionData) {
|
| 179 |
updateDecisionDashboard(lastPredictionData, selectedLocation);
|
|
|
|
|
|
|
| 180 |
}
|
|
|
|
|
|
|
| 181 |
}
|
| 182 |
}
|
| 183 |
|
| 184 |
window.switchPage = switchPage;
|
| 185 |
|
| 186 |
+
// Dynamically Populate Dropdown on Startup
|
| 187 |
function populateLocationDropdown() {
|
| 188 |
+
if (!locationSelect) return;
|
| 189 |
+
locationSelect.innerHTML = "";
|
| 190 |
+
Object.keys(KECAMATAN_DATABASE).forEach(loc => {
|
| 191 |
+
const opt = document.createElement("option");
|
| 192 |
+
opt.value = loc;
|
| 193 |
+
opt.textContent = `${loc} (${KECAMATAN_DATABASE[loc].city})`;
|
| 194 |
+
locationSelect.appendChild(opt);
|
|
|
|
|
|
|
|
|
|
| 195 |
});
|
| 196 |
+
locationSelect.value = selectedLocation;
|
| 197 |
}
|
| 198 |
|
| 199 |
// Calculate Haversine Distance between two coordinate arrays [lat, lon]
|
|
|
|
| 240 |
if (locationSelect) {
|
| 241 |
locationSelect.addEventListener("change", (e) => {
|
| 242 |
selectedLocation = e.target.value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
const pop = KECAMATAN_DATABASE[selectedLocation]?.population_jiwa || 100000;
|
| 244 |
if (eventOverride) {
|
| 245 |
eventOverride.value = pop;
|
frontend/index.html
CHANGED
|
@@ -140,9 +140,8 @@
|
|
| 140 |
</div>
|
| 141 |
<nav class="nav-links">
|
| 142 |
<button class="nav-btn active" data-target="page-home">HOME</button>
|
| 143 |
-
<button class="nav-btn" data-target="page-decision">DASHBOARD KEPUTUSAN</button>
|
| 144 |
<button class="nav-btn" data-target="page-autopilot">AI AUTOPILOT</button>
|
| 145 |
-
<button class="nav-btn" data-target="page-predictor">SIMULATION TOOL</button>
|
| 146 |
<button class="nav-btn" data-target="page-news">NEWS FEED</button>
|
| 147 |
<button class="nav-btn" data-target="page-alerts">REGIONAL ALERTS</button>
|
| 148 |
<button class="nav-btn" data-target="page-education">WASTE EDUCATION</button>
|
|
@@ -382,8 +381,9 @@
|
|
| 382 |
</section>
|
| 383 |
</div>
|
| 384 |
|
| 385 |
-
<!--
|
| 386 |
-
<div id="page-
|
|
|
|
| 387 |
<section class="container decision-header-section">
|
| 388 |
<div class="decision-header-top">
|
| 389 |
<div class="decision-title-group">
|
|
@@ -391,17 +391,11 @@
|
|
| 391 |
<svg class="decision-icon" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#00F0FF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
| 392 |
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
|
| 393 |
</svg>
|
| 394 |
-
Dashboard Keputusan
|
| 395 |
</h2>
|
| 396 |
-
<p class="decision-subtitle">
|
| 397 |
</div>
|
| 398 |
<div class="decision-controls">
|
| 399 |
-
<div class="decision-control-item">
|
| 400 |
-
<label for="dec-location-select">WILAYAH TARGET:</label>
|
| 401 |
-
<select id="dec-location-select" class="form-control dec-select">
|
| 402 |
-
<!-- Populated dynamically -->
|
| 403 |
-
</select>
|
| 404 |
-
</div>
|
| 405 |
<button class="action-btn weather-modal-trigger-btn" onclick="openWeatherModal()">
|
| 406 |
<span class="btn-text">🌦️ Prakiraan Cuaca 7 Hari</span>
|
| 407 |
<span class="btn-glow"></span>
|
|
@@ -446,147 +440,6 @@
|
|
| 446 |
</div>
|
| 447 |
</div>
|
| 448 |
</section>
|
| 449 |
-
|
| 450 |
-
<!-- Decision Body (Daily Workload Map + Fleet & Critical Action) -->
|
| 451 |
-
<section class="container decision-body-grid">
|
| 452 |
-
<!-- Left: Peta Beban Kerja Harian (7 Hari) -->
|
| 453 |
-
<div class="panel dec-workload-panel">
|
| 454 |
-
<div class="dec-panel-header">
|
| 455 |
-
<h3 class="dec-panel-title">
|
| 456 |
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#00F0FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 457 |
-
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
|
| 458 |
-
<line x1="16" y1="2" x2="16" y2="6"></line>
|
| 459 |
-
<line x1="8" y1="2" x2="8" y2="6"></line>
|
| 460 |
-
<line x1="3" y1="10" x2="21" y2="10"></line>
|
| 461 |
-
</svg>
|
| 462 |
-
Peta Beban Kerja Harian
|
| 463 |
-
</h3>
|
| 464 |
-
<span class="dec-panel-badge">Jadwal Shift & Disposisi Armada</span>
|
| 465 |
-
</div>
|
| 466 |
-
|
| 467 |
-
<div id="dec-workload-grid" class="dec-workload-grid">
|
| 468 |
-
<!-- Populated dynamically with 7 day cards -->
|
| 469 |
-
</div>
|
| 470 |
-
</div>
|
| 471 |
-
|
| 472 |
-
<!-- Right: Alokasi Armada Spesifik & Rencana Aksi Kritis -->
|
| 473 |
-
<div class="dec-sidebar-col">
|
| 474 |
-
<!-- Alokasi Armada Spesifik -->
|
| 475 |
-
<div class="panel dec-fleet-panel">
|
| 476 |
-
<h3 class="dec-panel-title">Alokasi Armada Spesifik</h3>
|
| 477 |
-
<div class="dec-fleet-list">
|
| 478 |
-
<!-- Truk Besar Dump Truck -->
|
| 479 |
-
<div class="dec-fleet-card dump-truck">
|
| 480 |
-
<div class="fleet-icon-box blue-box">
|
| 481 |
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 482 |
-
<rect x="1" y="3" width="15" height="13"></rect>
|
| 483 |
-
<polygon points="16 8 20 8 23 11 23 16 16 16 16 8"></polygon>
|
| 484 |
-
<circle cx="5.5" cy="18.5" r="2.5"></circle>
|
| 485 |
-
<circle cx="18.5" cy="18.5" r="2.5"></circle>
|
| 486 |
-
</svg>
|
| 487 |
-
</div>
|
| 488 |
-
<div class="fleet-info">
|
| 489 |
-
<div class="fleet-unit-count"><span id="dec-truck-large">125</span> Unit</div>
|
| 490 |
-
<div class="fleet-unit-type">Truk Besar (Dump Truck)</div>
|
| 491 |
-
</div>
|
| 492 |
-
</div>
|
| 493 |
-
|
| 494 |
-
<!-- Armada Kecil Pick-up -->
|
| 495 |
-
<div class="dec-fleet-card pickup-truck">
|
| 496 |
-
<div class="fleet-icon-box amber-box">
|
| 497 |
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 498 |
-
<rect x="1" y="3" width="12" height="13"></rect>
|
| 499 |
-
<polygon points="13 8 17 8 20 11 20 16 13 16 13 8"></polygon>
|
| 500 |
-
<circle cx="4.5" cy="18.5" r="2.5"></circle>
|
| 501 |
-
<circle cx="16.5" cy="18.5" r="2.5"></circle>
|
| 502 |
-
</svg>
|
| 503 |
-
</div>
|
| 504 |
-
<div class="fleet-info">
|
| 505 |
-
<div class="fleet-unit-count"><span id="dec-truck-small">84</span> Unit</div>
|
| 506 |
-
<div class="fleet-unit-type">Armada Kecil (Pick-up)</div>
|
| 507 |
-
</div>
|
| 508 |
-
</div>
|
| 509 |
-
</div>
|
| 510 |
-
</div>
|
| 511 |
-
|
| 512 |
-
<!-- Rencana Aksi Kritis -->
|
| 513 |
-
<div class="panel dec-action-panel">
|
| 514 |
-
<h3 class="dec-panel-title action-title">
|
| 515 |
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 516 |
-
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
| 517 |
-
<line x1="12" y1="9" x2="12" y2="13"></line>
|
| 518 |
-
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
| 519 |
-
</svg>
|
| 520 |
-
Rencana Aksi Kritis
|
| 521 |
-
</h3>
|
| 522 |
-
<div class="dec-critical-box" id="dec-critical-box">
|
| 523 |
-
<div class="dec-critical-header">
|
| 524 |
-
<span class="critical-pulse-dot"></span>
|
| 525 |
-
<span id="dec-critical-title" class="dec-critical-title">AKSI HARI JUM (HUJAN LEBAT & BEBAN PUNCAK)</span>
|
| 526 |
-
</div>
|
| 527 |
-
<ul id="dec-critical-list" class="dec-critical-list">
|
| 528 |
-
<!-- Populated dynamically with SOP actions -->
|
| 529 |
-
</ul>
|
| 530 |
-
</div>
|
| 531 |
-
</div>
|
| 532 |
-
</div>
|
| 533 |
-
</section>
|
| 534 |
-
</div>
|
| 535 |
-
|
| 536 |
-
<!-- AI AUTOPILOT PAGE -->
|
| 537 |
-
<div id="page-autopilot" class="page-container">
|
| 538 |
-
<section class="container page-header-section">
|
| 539 |
-
<h2 class="section-title">AETERNA AI AUTOPILOT FORECASTER</h2>
|
| 540 |
-
<p class="section-subtitle">Sistem peramalan otonom DKI Jakarta. AI berjalan mandiri memprediksi volume
|
| 541 |
-
harian dan mengoordinasikan logistik tanpa campur tangan pengguna.</p>
|
| 542 |
-
</section>
|
| 543 |
-
|
| 544 |
-
<!-- Live Metrics Summary -->
|
| 545 |
-
<section class="container autopilot-grid"
|
| 546 |
-
style="display:grid; grid-template-columns: 1.2fr 0.8fr; gap:1.5rem; margin-top:1.5rem;">
|
| 547 |
-
<!-- Panel Ringkasan Otonom -->
|
| 548 |
-
<div class="panel autopilot-summary-panel">
|
| 549 |
-
<h3 class="panel-title">LIVE CITY-WIDE FORECAST (TODAY)</h3>
|
| 550 |
-
<div class="stats-row"
|
| 551 |
-
style="display:grid; grid-template-columns: 1fr 1fr; gap:1rem; margin-bottom:1.5rem; width:100%;">
|
| 552 |
-
<div class="panel stat-card text-glow"
|
| 553 |
-
style="background: rgba(0, 0, 0, 0.02); display:flex; flex-direction:column; padding:1.2rem; border-radius:8px;">
|
| 554 |
-
<span class="card-label">TOTAL DKI JAKARTA VOLUME</span>
|
| 555 |
-
<span id="auto-total-volume" class="card-value"
|
| 556 |
-
style="font-size:1.8rem; font-weight:800; color:var(--cyan);">Calculating...</span>
|
| 557 |
-
<span class="card-meta">Autonomous prediction summation</span>
|
| 558 |
-
</div>
|
| 559 |
-
<div class="panel stat-card"
|
| 560 |
-
style="background: rgba(0, 0, 0, 0.02); display:flex; flex-direction:column; padding:1.2rem; border-radius:8px;">
|
| 561 |
-
<span class="card-label">TOTAL DISPATCHED TRUCKS</span>
|
| 562 |
-
<span id="auto-total-trucks" class="card-value"
|
| 563 |
-
style="font-size:1.8rem; font-weight:800; color:var(--text-main);">Calculating...</span>
|
| 564 |
-
<span class="card-meta">Fleet size for all 44 kecamatan</span>
|
| 565 |
-
</div>
|
| 566 |
-
</div>
|
| 567 |
-
|
| 568 |
-
<h4
|
| 569 |
-
style="color:var(--cyan); margin-bottom:0.8rem; font-family:var(--font-display); font-size:0.95rem; border-left:3px solid var(--cyan); padding-left:8px; text-transform:uppercase;">
|
| 570 |
-
Top 5 High-Risk Kecamatan Today:</h4>
|
| 571 |
-
<div id="auto-risk-list" class="auto-risk-list"
|
| 572 |
-
style="display:flex; flex-direction:column; gap:0.8rem;">
|
| 573 |
-
<!-- Dynamically populated Top 5 -->
|
| 574 |
-
</div>
|
| 575 |
-
</div>
|
| 576 |
-
|
| 577 |
-
<!-- Konsol Berpikir AI -->
|
| 578 |
-
<div class="panel autopilot-console-panel" style="display:flex; flex-direction:column; height:100%;">
|
| 579 |
-
<h3 class="panel-title">AI THINKING CONSOLE</h3>
|
| 580 |
-
<div id="autopilot-log"
|
| 581 |
-
style="flex:1; background:#0B1310; border:1px solid var(--border-color); border-radius:8px; padding:1.2rem; font-family:var(--font-mono); font-size:0.8rem; color:#22C55E; overflow-y:auto; min-height:260px; line-height:1.6; box-shadow:inset 0 0 10px rgba(0,0,0,0.5);">
|
| 582 |
-
<!-- Dynamic logs -->
|
| 583 |
-
</div>
|
| 584 |
-
</div>
|
| 585 |
-
</section>
|
| 586 |
-
</div>
|
| 587 |
-
|
| 588 |
-
<!-- PREDICTOR PAGE -->
|
| 589 |
-
<div id="page-predictor" class="page-container">
|
| 590 |
<main class="dashboard-grid">
|
| 591 |
<!-- Panel Kontrol (Sidebar) -->
|
| 592 |
<section class="panel control-panel">
|
|
@@ -784,6 +637,91 @@
|
|
| 784 |
</section>
|
| 785 |
</main>
|
| 786 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 787 |
<!-- Timeline Harian -->
|
| 788 |
<section class="container timeline-container">
|
| 789 |
<div class="panel timeline-panel">
|
|
|
|
| 140 |
</div>
|
| 141 |
<nav class="nav-links">
|
| 142 |
<button class="nav-btn active" data-target="page-home">HOME</button>
|
|
|
|
| 143 |
<button class="nav-btn" data-target="page-autopilot">AI AUTOPILOT</button>
|
| 144 |
+
<button class="nav-btn" data-target="page-predictor">SIMULATION & DECISION TOOL</button>
|
| 145 |
<button class="nav-btn" data-target="page-news">NEWS FEED</button>
|
| 146 |
<button class="nav-btn" data-target="page-alerts">REGIONAL ALERTS</button>
|
| 147 |
<button class="nav-btn" data-target="page-education">WASTE EDUCATION</button>
|
|
|
|
| 381 |
</section>
|
| 382 |
</div>
|
| 383 |
|
| 384 |
+
<!-- PREDICTOR & DECISION DASHBOARD PAGE -->
|
| 385 |
+
<div id="page-predictor" class="page-container">
|
| 386 |
+
<!-- Top Executive Decision KPIs Header -->
|
| 387 |
<section class="container decision-header-section">
|
| 388 |
<div class="decision-header-top">
|
| 389 |
<div class="decision-title-group">
|
|
|
|
| 391 |
<svg class="decision-icon" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#00F0FF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
| 392 |
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
|
| 393 |
</svg>
|
| 394 |
+
Dashboard Keputusan & AI Simulator
|
| 395 |
</h2>
|
| 396 |
+
<p class="decision-subtitle">Spatial-temporal forecasting engine & decision support system untuk optimalisasi logistik, alokasi armada hulu-hilir, dan efisiensi anggaran sampah DKI Jakarta.</p>
|
| 397 |
</div>
|
| 398 |
<div class="decision-controls">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 399 |
<button class="action-btn weather-modal-trigger-btn" onclick="openWeatherModal()">
|
| 400 |
<span class="btn-text">🌦️ Prakiraan Cuaca 7 Hari</span>
|
| 401 |
<span class="btn-glow"></span>
|
|
|
|
| 440 |
</div>
|
| 441 |
</div>
|
| 442 |
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
<main class="dashboard-grid">
|
| 444 |
<!-- Panel Kontrol (Sidebar) -->
|
| 445 |
<section class="panel control-panel">
|
|
|
|
| 637 |
</section>
|
| 638 |
</main>
|
| 639 |
|
| 640 |
+
<!-- Section: Peta Beban Kerja Harian, Alokasi Armada Spesifik, & Rencana Aksi Kritis -->
|
| 641 |
+
<section class="container decision-body-grid" style="margin-top: 1.5rem; margin-bottom: 1.5rem;">
|
| 642 |
+
<!-- Left: Peta Beban Kerja Harian (7 Hari) -->
|
| 643 |
+
<div class="panel dec-workload-panel">
|
| 644 |
+
<div class="dec-panel-header">
|
| 645 |
+
<h3 class="dec-panel-title">
|
| 646 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#00F0FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 647 |
+
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
|
| 648 |
+
<line x1="16" y1="2" x2="16" y2="6"></line>
|
| 649 |
+
<line x1="8" y1="2" x2="8" y2="6"></line>
|
| 650 |
+
<line x1="3" y1="10" x2="21" y2="10"></line>
|
| 651 |
+
</svg>
|
| 652 |
+
Peta Beban Kerja Harian
|
| 653 |
+
</h3>
|
| 654 |
+
<span class="dec-panel-badge">Jadwal Shift & Disposisi Armada</span>
|
| 655 |
+
</div>
|
| 656 |
+
|
| 657 |
+
<div id="dec-workload-grid" class="dec-workload-grid">
|
| 658 |
+
<!-- Populated dynamically with 7 day cards -->
|
| 659 |
+
</div>
|
| 660 |
+
</div>
|
| 661 |
+
|
| 662 |
+
<!-- Right: Alokasi Armada Spesifik & Rencana Aksi Kritis -->
|
| 663 |
+
<div class="dec-sidebar-col">
|
| 664 |
+
<!-- Alokasi Armada Spesifik -->
|
| 665 |
+
<div class="panel dec-fleet-panel">
|
| 666 |
+
<h3 class="dec-panel-title">Alokasi Armada Spesifik</h3>
|
| 667 |
+
<div class="dec-fleet-list">
|
| 668 |
+
<!-- Truk Besar Dump Truck -->
|
| 669 |
+
<div class="dec-fleet-card dump-truck">
|
| 670 |
+
<div class="fleet-icon-box blue-box">
|
| 671 |
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 672 |
+
<rect x="1" y="3" width="15" height="13"></rect>
|
| 673 |
+
<polygon points="16 8 20 8 23 11 23 16 16 16 8"></polygon>
|
| 674 |
+
<circle cx="5.5" cy="18.5" r="2.5"></circle>
|
| 675 |
+
<circle cx="18.5" cy="18.5" r="2.5"></circle>
|
| 676 |
+
</svg>
|
| 677 |
+
</div>
|
| 678 |
+
<div class="fleet-info">
|
| 679 |
+
<div class="fleet-unit-count"><span id="dec-truck-large">125</span> Unit</div>
|
| 680 |
+
<div class="fleet-unit-type">Truk Besar (Dump Truck)</div>
|
| 681 |
+
</div>
|
| 682 |
+
</div>
|
| 683 |
+
|
| 684 |
+
<!-- Armada Kecil Pick-up -->
|
| 685 |
+
<div class="dec-fleet-card pickup-truck">
|
| 686 |
+
<div class="fleet-icon-box amber-box">
|
| 687 |
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 688 |
+
<rect x="1" y="3" width="12" height="13"></rect>
|
| 689 |
+
<polygon points="13 8 17 8 20 11 20 16 13 16 13 8"></polygon>
|
| 690 |
+
<circle cx="4.5" cy="18.5" r="2.5"></circle>
|
| 691 |
+
<circle cx="16.5" cy="18.5" r="2.5"></circle>
|
| 692 |
+
</svg>
|
| 693 |
+
</div>
|
| 694 |
+
<div class="fleet-info">
|
| 695 |
+
<div class="fleet-unit-count"><span id="dec-truck-small">84</span> Unit</div>
|
| 696 |
+
<div class="fleet-unit-type">Armada Kecil (Pick-up)</div>
|
| 697 |
+
</div>
|
| 698 |
+
</div>
|
| 699 |
+
</div>
|
| 700 |
+
</div>
|
| 701 |
+
|
| 702 |
+
<!-- Rencana Aksi Kritis -->
|
| 703 |
+
<div class="panel dec-action-panel">
|
| 704 |
+
<h3 class="dec-panel-title action-title">
|
| 705 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
| 706 |
+
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
| 707 |
+
<line x1="12" y1="9" x2="12" y2="13"></line>
|
| 708 |
+
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
| 709 |
+
</svg>
|
| 710 |
+
Rencana Aksi Kritis
|
| 711 |
+
</h3>
|
| 712 |
+
<div class="dec-critical-box" id="dec-critical-box">
|
| 713 |
+
<div class="dec-critical-header">
|
| 714 |
+
<span class="critical-pulse-dot"></span>
|
| 715 |
+
<span id="dec-critical-title" class="dec-critical-title">AKSI HARI JUM (HUJAN LEBAT & BEBAN PUNCAK)</span>
|
| 716 |
+
</div>
|
| 717 |
+
<ul id="dec-critical-list" class="dec-critical-list">
|
| 718 |
+
<!-- Populated dynamically with SOP actions -->
|
| 719 |
+
</ul>
|
| 720 |
+
</div>
|
| 721 |
+
</div>
|
| 722 |
+
</div>
|
| 723 |
+
</section>
|
| 724 |
+
|
| 725 |
<!-- Timeline Harian -->
|
| 726 |
<section class="container timeline-container">
|
| 727 |
<div class="panel timeline-panel">
|
frontend/style.css
CHANGED
|
@@ -130,7 +130,7 @@ header {
|
|
| 130 |
display: grid;
|
| 131 |
grid-template-columns: 320px 1fr 340px;
|
| 132 |
gap: 1.5rem;
|
| 133 |
-
padding: 1.
|
| 134 |
flex: 1;
|
| 135 |
z-index: 5;
|
| 136 |
position: relative;
|
|
@@ -656,7 +656,7 @@ header {
|
|
| 656 |
/* Timeline Container */
|
| 657 |
.timeline-container {
|
| 658 |
margin-top: 1.5rem;
|
| 659 |
-
padding: 0
|
| 660 |
z-index: 5;
|
| 661 |
position: relative;
|
| 662 |
}
|
|
@@ -725,7 +725,7 @@ header {
|
|
| 725 |
/* Hourly Breakdown Container */
|
| 726 |
.hourly-container {
|
| 727 |
margin-top: 1.5rem;
|
| 728 |
-
padding: 0
|
| 729 |
z-index: 5;
|
| 730 |
position: relative;
|
| 731 |
margin-bottom: 2rem;
|
|
|
|
| 130 |
display: grid;
|
| 131 |
grid-template-columns: 320px 1fr 340px;
|
| 132 |
gap: 1.5rem;
|
| 133 |
+
padding: 1.2rem 0;
|
| 134 |
flex: 1;
|
| 135 |
z-index: 5;
|
| 136 |
position: relative;
|
|
|
|
| 656 |
/* Timeline Container */
|
| 657 |
.timeline-container {
|
| 658 |
margin-top: 1.5rem;
|
| 659 |
+
padding: 0;
|
| 660 |
z-index: 5;
|
| 661 |
position: relative;
|
| 662 |
}
|
|
|
|
| 725 |
/* Hourly Breakdown Container */
|
| 726 |
.hourly-container {
|
| 727 |
margin-top: 1.5rem;
|
| 728 |
+
padding: 0;
|
| 729 |
z-index: 5;
|
| 730 |
position: relative;
|
| 731 |
margin-bottom: 2rem;
|