778 lines
44 KiB
HTML
778 lines
44 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
|
<title>WebGIS Dashboard — Manajemen Data</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/css/style.css">
|
|
<style>
|
|
/* ── Inline component styles not yet in style.css ── */
|
|
|
|
/* Dependent entry */
|
|
.dependent-entry {
|
|
background:var(--surface-2); border:1px solid var(--border-subtle);
|
|
border-radius:var(--r); padding:10px 12px; margin-bottom:8px; position:relative;
|
|
}
|
|
.dependent-entry .dependent-number {
|
|
font-size:9px; font-weight:700; text-transform:uppercase;
|
|
letter-spacing:0.05em; color:var(--accent); margin-bottom:8px;
|
|
}
|
|
.dependent-entry .btn-remove-dependent {
|
|
position:absolute; top:8px; right:8px;
|
|
width:26px; height:26px; border-radius:50%;
|
|
border:1px solid var(--danger); background:#fff;
|
|
color:var(--danger); cursor:pointer; font-size:10px;
|
|
display:flex; align-items:center; justify-content:center;
|
|
transition:all 0.15s; touch-action:manipulation;
|
|
}
|
|
.dependent-entry .btn-remove-dependent:hover { background:#fff4f4; }
|
|
.dependent-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
|
|
.dependent-grid .form-group { margin-bottom:6px; }
|
|
.dependent-grid .form-group label { font-size:9.5px; margin-bottom:2px; }
|
|
.dependent-grid .form-group input,
|
|
.dependent-grid .form-group select { padding:7px 8px; font-size:14px; min-height:38px; }
|
|
.dependent-grid .form-group-full { grid-column:1/-1; }
|
|
#dependentsContainer { max-height:260px; overflow-y:auto; padding-right:4px; -webkit-overflow-scrolling:touch; }
|
|
#dependentsContainer::-webkit-scrollbar { width:3px; }
|
|
#dependentsContainer::-webkit-scrollbar-thumb { background:var(--border); border-radius:4px; }
|
|
|
|
/* Family member list */
|
|
.family-members-section { margin-top:14px; border-top:1px solid var(--border-subtle); padding-top:12px; }
|
|
.family-members-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; }
|
|
.family-members-header h4 { font-size:11px; font-weight:700; text-transform:uppercase; color:var(--text-secondary); }
|
|
.btn-add-member { padding:6px 12px; font-size:11px; background:var(--success); color:white; border:none; border-radius:20px; cursor:pointer; min-height:32px; touch-action:manipulation; }
|
|
.family-member-list { max-height:190px; overflow-y:auto; -webkit-overflow-scrolling:touch; }
|
|
.family-member-item { padding:9px 10px; border-bottom:1px solid var(--border-subtle); display:flex; justify-content:space-between; align-items:center; min-height:44px; }
|
|
.family-member-item:last-child { border-bottom:none; }
|
|
.family-member-info { flex:1; }
|
|
.family-member-name { font-weight:600; font-size:12px; }
|
|
.family-member-relation { font-size:10px; color:var(--text-muted); background:var(--surface-2); padding:2px 6px; border-radius:12px; margin-left:6px; }
|
|
.family-member-job, .family-member-study { font-size:9px; color:var(--text-muted); margin-left:6px; }
|
|
.family-member-actions { display:flex; gap:5px; }
|
|
.btn-edit-member, .btn-delete-member { background:none; border:none; cursor:pointer; font-size:12px; padding:5px 8px; border-radius:5px; min-height:32px; touch-action:manipulation; }
|
|
.btn-edit-member { color:var(--warning); }
|
|
.btn-delete-member { color:var(--danger); }
|
|
|
|
/* Pending badge */
|
|
.pending-badge { background:var(--danger); color:white; font-size:9px; font-weight:700; padding:1px 5px; border-radius:10px; margin-left:4px; display:inline-block; vertical-align:middle; }
|
|
.pending-badge:empty { display:none; }
|
|
|
|
/* Popup */
|
|
.popup-info { padding:14px 16px; }
|
|
.popup-info .popup-name { font-size:14px; font-weight:700; color:var(--text-primary); margin-bottom:2px; line-height:1.3; }
|
|
.popup-info .popup-hint { font-size:9.5px; color:var(--text-muted); margin-bottom:10px; }
|
|
.popup-info .popup-badges { display:flex; gap:5px; flex-wrap:wrap; margin-bottom:10px; padding-bottom:10px; border-bottom:1px solid var(--border-subtle); }
|
|
.popup-info .popup-badge { padding:3px 9px; border-radius:20px; font-size:9.5px; font-weight:700; white-space:nowrap; }
|
|
.popup-info .popup-row { display:flex; align-items:flex-start; gap:8px; margin-bottom:6px; font-size:12px; color:var(--text-secondary); }
|
|
.popup-info .popup-row i { font-size:10px; color:var(--text-muted); margin-top:2px; flex-shrink:0; width:12px; }
|
|
.popup-info .popup-row strong { color:var(--text-primary); font-weight:600; }
|
|
.popup-info .popup-section { margin-top:10px; padding:9px 11px; background:var(--surface-2); border-radius:var(--r-sm); border:1px solid var(--border-subtle); }
|
|
.popup-info .popup-section-label { font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:0.06em; color:var(--text-muted); margin-bottom:6px; }
|
|
.popup-actions { display:flex; gap:5px; margin-top:12px; padding-top:10px; border-top:1px solid var(--border-subtle); flex-wrap:wrap; }
|
|
.popup-actions .btn { margin:0; font-size:11px; padding:7px 10px; min-height:36px; }
|
|
|
|
/* Admin */
|
|
.admin-tab-panel.active { display:block; }
|
|
.admin-tab-panel { display:none; }
|
|
.btn-approve { background:var(--success); color:white; }
|
|
.btn-approve:hover { filter:brightness(0.92); }
|
|
.btn-reject { background:var(--danger); color:white; }
|
|
.btn-reject:hover { filter:brightness(0.92); }
|
|
|
|
/* Mobile sidebar toggle button */
|
|
.sidebar-toggle {
|
|
position:absolute; top:14px; left:14px; z-index:1001;
|
|
width:42px; height:42px; border-radius:var(--r);
|
|
background:var(--surface); border:1px solid var(--border);
|
|
box-shadow:var(--shadow-md); cursor:pointer;
|
|
display:none; align-items:center; justify-content:center;
|
|
color:var(--accent); font-size:17px;
|
|
transition:all 0.15s; touch-action:manipulation;
|
|
}
|
|
.sidebar-toggle:active { transform:scale(0.94); }
|
|
@media (max-width:768px) { .sidebar-toggle { display:flex; } }
|
|
|
|
/* Sidebar backdrop */
|
|
.sidebar-backdrop {
|
|
display:none; position:fixed; inset:0;
|
|
background:rgba(10,15,28,0.45); z-index:999;
|
|
backdrop-filter:blur(2px); -webkit-backdrop-filter:blur(2px);
|
|
}
|
|
.sidebar-backdrop.active { display:block; }
|
|
|
|
/* Dashboard modal mobile close area */
|
|
#dashboardModal .modal-close-mobile {
|
|
display:none;
|
|
}
|
|
|
|
/* Legend expand toggle on mobile */
|
|
.legend-expand-btn {
|
|
background:none; border:none; cursor:pointer;
|
|
color:var(--text-muted); font-size:10px; padding:0;
|
|
margin-left:6px; touch-action:manipulation;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ===== MAP ===== -->
|
|
<div id="map"></div>
|
|
|
|
<!-- ===== MOBILE SIDEBAR TOGGLE ===== -->
|
|
<button class="sidebar-toggle" id="sidebarToggle" onclick="toggleMobileSidebar()" aria-label="Menu">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
|
|
<!-- Sidebar backdrop for mobile -->
|
|
<div class="sidebar-backdrop" id="sidebarBackdrop" onclick="closeMobileSidebar()"></div>
|
|
|
|
<!-- ===== SIDEBAR ===== -->
|
|
<div class="sidebar" id="sidebar">
|
|
<div class="sidebar-header">
|
|
<div class="sidebar-logo"><i class="fas fa-map-marked-alt"></i></div>
|
|
<div class="sidebar-title">
|
|
<h1>Dashboard</h1>
|
|
<p>Poverty Mapping</p>
|
|
</div>
|
|
<div style="margin-left:auto; display:flex; align-items:center; gap:2px;">
|
|
<button class="btn-admin-panel" onclick="openAdminPanel()" style="margin:0;padding:6px 10px;font-size:11px;min-height:36px;">
|
|
<i class="fas fa-cog"></i> <span class="hide-xs">Laporan</span>
|
|
</button>
|
|
<button class="logout-btn" onclick="logout()" title="Logout">
|
|
<i class="fas fa-sign-out-alt"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sidebar-content">
|
|
<div class="nav-tabs">
|
|
<div class="nav-tab active" data-tab="overview"><i class="fas fa-eye"></i> <span class="tab-label">Ringkasan</span></div>
|
|
<div class="nav-tab" data-tab="centers"><i class="fas fa-place-of-worship"></i> <span class="tab-label">Ibadah</span></div>
|
|
<div class="nav-tab" data-tab="houses"><i class="fas fa-home"></i> <span class="tab-label">Rumah</span></div>
|
|
<div class="nav-tab" data-tab="dashboard"><i class="fas fa-chart-bar"></i> <span class="tab-label">Chart</span></div>
|
|
</div>
|
|
|
|
<div class="stats-grid">
|
|
<div class="stat-card purple">
|
|
<div class="stat-icon"><i class="fas fa-place-of-worship"></i></div>
|
|
<div class="stat-value" id="statCenters">0</div>
|
|
<div class="stat-label">Tempat Ibadah</div>
|
|
</div>
|
|
<div class="stat-card green">
|
|
<div class="stat-icon"><i class="fas fa-home"></i></div>
|
|
<div class="stat-value" id="statHouses">0</div>
|
|
<div class="stat-label">Rumah</div>
|
|
</div>
|
|
<div class="stat-card orange">
|
|
<div class="stat-icon"><i class="fas fa-users"></i></div>
|
|
<div class="stat-value" id="statPopulation">0</div>
|
|
<div class="stat-label">Tanggungan</div>
|
|
</div>
|
|
<div class="stat-card teal">
|
|
<div class="stat-icon"><i class="fas fa-hand-holding-heart"></i></div>
|
|
<div class="stat-value" id="statAided">0</div>
|
|
<div class="stat-label">Terima Bantuan</div>
|
|
</div>
|
|
<div class="stat-card red" id="cardPending">
|
|
<div class="stat-icon"><i class="fas fa-flag"></i></div>
|
|
<div class="stat-value" id="statPending">0</div>
|
|
<div class="stat-label">Laporan Publik</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="search-box">
|
|
<i class="fas fa-search"></i>
|
|
<input type="text" id="searchInput" placeholder="Cari nama, alamat, NIK...">
|
|
</div>
|
|
|
|
<div class="filter-section">
|
|
<div class="filter-title">Filter Tampilan</div>
|
|
<div class="filter-buttons">
|
|
<button class="filter-btn active" data-filter="all">Semua</button>
|
|
<button class="filter-btn" data-filter="centers">Ibadah</button>
|
|
<button class="filter-btn" data-filter="houses">Rumah</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="dataListsContainer">
|
|
<div class="data-section" id="centersListSection">
|
|
<div class="section-title">
|
|
<span><i class="fas fa-place-of-worship"></i> Tempat Ibadah</span>
|
|
<span class="count-badge" id="centerCount">0</span>
|
|
</div>
|
|
<div class="data-list" id="centersList">
|
|
<div class="empty-state"><i class="fas fa-place-of-worship"></i><p>Belum ada data</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="data-section" id="housesListSection">
|
|
<div class="section-title">
|
|
<span><i class="fas fa-home"></i> Rumah</span>
|
|
<span class="count-badge" id="houseCount">0</span>
|
|
</div>
|
|
<div class="data-list" id="housesList">
|
|
<div class="empty-state"><i class="fas fa-home"></i><p>Belum ada data</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ===== LEGEND (collapsible on mobile) ===== -->
|
|
<div class="legend" id="legend">
|
|
<h4 onclick="toggleLegend()">
|
|
Keterangan
|
|
<button class="legend-expand-btn" title="Toggle legend">
|
|
<i class="fas fa-chevron-up" id="legendChevron"></i>
|
|
</button>
|
|
</h4>
|
|
<div class="legend-content" id="legendContent">
|
|
<div class="legend-section-label">Tempat Ibadah</div>
|
|
<div class="legend-item"><div class="legend-icon" style="background:#1d6fa4;"><i class="fas fa-mosque"></i></div><span>Masjid</span></div>
|
|
<div class="legend-item"><div class="legend-icon" style="background:#7c3aed;"><i class="fas fa-church"></i></div><span>Gereja</span></div>
|
|
<div class="legend-item"><div class="legend-icon" style="background:#b45309;"><i class="fas fa-torii-gate"></i></div><span>Klenteng</span></div>
|
|
<div class="legend-item"><div class="legend-icon" style="background:#0e7f6e;"><i class="fas fa-om"></i></div><span>Pura</span></div>
|
|
<div class="legend-item"><div class="legend-icon" style="background:#a16207;"><i class="fas fa-dharmachakra"></i></div><span>Vihara</span></div>
|
|
<div class="legend-section-label" style="margin-top:8px;">Kategori Kemiskinan</div>
|
|
<div class="legend-poverty-item"><div class="legend-poverty-dot" style="background:#d63230;"></div><span>Sangat Miskin</span></div>
|
|
<div class="legend-poverty-item"><div class="legend-poverty-dot" style="background:#f76707;"></div><span>Miskin</span></div>
|
|
<div class="legend-poverty-item"><div class="legend-poverty-dot" style="background:#f59e0b;"></div><span>Rentan Miskin</span></div>
|
|
<div class="legend-poverty-item"><div class="legend-poverty-dot" style="background:#0b9e73;"></div><span>Terdata</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ===== LAYER CONTROL ===== -->
|
|
<div class="custom-layer-control">
|
|
<h4><i class="fas fa-layer-group"></i> <span>Layer</span></h4>
|
|
<div class="custom-layer-item" onclick="toggleLayer('centers')">
|
|
<input type="checkbox" id="layerCenters" checked>
|
|
<i class="fas fa-place-of-worship layer-icon layer-icon-center"></i>
|
|
<span>Tempat Ibadah</span>
|
|
<small id="layerCenterCount">0</small>
|
|
</div>
|
|
<div class="custom-layer-item" onclick="toggleLayer('houses')">
|
|
<input type="checkbox" id="layerHouses" checked>
|
|
<i class="fas fa-home layer-icon layer-icon-house"></i>
|
|
<span>Rumah</span>
|
|
<small id="layerHouseCount">0</small>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ===== LOADING ===== -->
|
|
<div class="loading" id="loading"><i class="fas fa-circle-notch fa-spin"></i><span>Memproses...</span></div>
|
|
<div class="toast" id="toast"></div>
|
|
<button class="help-btn" id="helpBtn" title="Panduan Pengguna"><i class="fas fa-question-circle"></i></button>
|
|
|
|
<!-- ================================================================
|
|
MODAL: Religious Center
|
|
================================================================ -->
|
|
<div class="modal-overlay" id="centerModal">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<h2 id="centerModalTitle">Tambah Tempat Ibadah</h2>
|
|
<span class="modal-close" onclick="closeModal('centerModal')">×</span>
|
|
</div>
|
|
<form id="centerForm" novalidate>
|
|
<input type="hidden" id="centerId">
|
|
<input type="hidden" id="centerLat">
|
|
<input type="hidden" id="centerLng">
|
|
<div class="form-group">
|
|
<label>Nama *</label>
|
|
<input type="text" id="centerName" required placeholder="Contoh: Masjid Al-Ikhlas">
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Jenis Ibadah</label>
|
|
<select id="centerWorshipType">
|
|
<option value="masjid">Masjid</option><option value="gereja">Gereja</option>
|
|
<option value="klenteng">Klenteng</option><option value="pura">Pura</option><option value="vihara">Vihara</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Radius (m)</label>
|
|
<input type="number" id="centerRadius" min="50" max="5000" value="300" step="10">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Slider Radius</label>
|
|
<div class="slider-container">
|
|
<input type="range" id="centerRadiusSlider" min="50" max="5000" value="300" step="10">
|
|
<span class="slider-value" id="centerRadiusValue">300m</span>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Kontak Person</label><input type="text" id="centerContactPerson" placeholder="Nama penanggung jawab"></div>
|
|
<div class="form-group"><label>Nomor Telepon</label><input type="text" id="centerContactPhone" placeholder="08xx-xxxx-xxxx"></div>
|
|
</div>
|
|
<div class="form-group"><label>Catatan</label><textarea id="centerNotes" rows="2" placeholder="Informasi tambahan..."></textarea></div>
|
|
<div class="form-group"><label>Alamat</label><input type="text" id="centerAddress" readonly placeholder="Terisi otomatis dari peta"></div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Latitude</label><input type="text" id="centerLatDisplay" readonly></div>
|
|
<div class="form-group"><label>Longitude</label><input type="text" id="centerLngDisplay" readonly></div>
|
|
</div>
|
|
<div class="modal-actions">
|
|
<button type="submit" class="btn btn-primary"><i class="fas fa-save"></i> Simpan</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('centerModal')">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================================================================
|
|
MODAL: Household
|
|
================================================================ -->
|
|
<div class="modal-overlay" id="houseModal">
|
|
<div class="modal" style="max-width:560px;">
|
|
<div class="modal-header">
|
|
<h2 id="houseModalTitle">Tambah Rumah Tangga</h2>
|
|
<span class="modal-close" onclick="closeModal('houseModal')">×</span>
|
|
</div>
|
|
<form id="houseForm" novalidate>
|
|
<input type="hidden" id="houseId">
|
|
<input type="hidden" id="houseLat">
|
|
<input type="hidden" id="houseLng">
|
|
<input type="hidden" id="familyMembersData" value="[]">
|
|
|
|
<div class="poverty-preview" id="povertyPreview">
|
|
<div class="poverty-score-ring" id="povertyRing"><i id="povertyIcon" class="fas fa-circle" style="font-size:16px;"></i></div>
|
|
<div style="flex:1;">
|
|
<div class="poverty-status-label" id="povertyStatusLabel">Belum dihitung</div>
|
|
<div class="poverty-indicators" id="povertyIndicators" style="font-size:9px;color:#5a6478;margin-top:4px;padding-left:0;list-style:none;max-height:70px;overflow-y:auto;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Alamat -->
|
|
<div class="form-section" style="margin-bottom:14px;">
|
|
<div class="section-title" style="margin-bottom:8px;">Informasi Alamat</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>RT</label><input type="text" id="houseRt" maxlength="5" placeholder="01"></div>
|
|
<div class="form-group"><label>RW</label><input type="text" id="houseRw" maxlength="5" placeholder="02"></div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Kelurahan</label><input type="text" id="houseKelurahan" readonly></div>
|
|
<div class="form-group"><label>Kecamatan</label><input type="text" id="houseKecamatan" readonly></div>
|
|
</div>
|
|
<div class="form-group"><label>Alamat Lengkap</label><textarea id="houseFullAddress" rows="2" placeholder="Alamat lengkap (dapat diedit manual)" style="background: var(--surface);"></textarea></div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Pusat Pengelola</label><input type="text" id="managingCenterName" readonly placeholder="Otomatis terdeteksi"><input type="hidden" id="managingCenterId"></div>
|
|
<div class="form-group"><label>Kondisi Rumah</label><select id="houseCondition"><option value="layak">Layak</option><option value="tidak_layak">Tidak Layak</option></select></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Anggota Keluarga -->
|
|
<div class="form-section" style="margin-bottom:14px;">
|
|
<div class="section-title" style="margin-bottom:8px;">
|
|
<span>Anggota Keluarga</span>
|
|
<button type="button" class="btn-add-member" onclick="openFamilyMemberModal()"><i class="fas fa-plus"></i> Tambah</button>
|
|
</div>
|
|
<div id="familyMembersList" class="family-member-list">
|
|
<div class="empty-state" style="padding:16px;text-align:center;"><i class="fas fa-users"></i><p>Belum ada anggota keluarga</p></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form tabs -->
|
|
<div class="form-tabs">
|
|
<button type="button" class="form-tab active" data-ftab="identity">Identitas KK</button>
|
|
<button type="button" class="form-tab" data-ftab="economic">Ekonomi</button>
|
|
<button type="button" class="form-tab" data-ftab="aid">Bantuan</button>
|
|
</div>
|
|
|
|
<div class="form-tab-panel active" id="ftab-identity">
|
|
<div class="form-group"><label>Nama Kepala Keluarga <span style="color:red;">*</span></label><input type="text" id="houseHeadName" required placeholder="Nama lengkap"></div>
|
|
<div class="field-error" id="errHouseHeadName" style="display: none; font-size: 11px; color: var(--danger); margin-top: 4px;">
|
|
<i class="fas fa-exclamation-circle"></i> Nama Kepala Keluarga wajib diisi.
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>NIK Kepala Keluarga <span style="color:red;">*</span></label><input type="text" id="houseNIK" maxlength="16" placeholder="16 digit NIK"></div>
|
|
<div class="field-error" id="errHouseNIK" style="display: none; font-size: 11px; color: var(--danger); margin-top: 4px;">
|
|
<i class="fas fa-exclamation-circle"></i> NIK Kepala Keluarga wajib diisi.
|
|
</div>
|
|
<div class="form-group"><label>Jenis Kelamin <span style="color:red;">*</span></label><select id="houseGender" required><option value="male">Laki-laki</option><option value="female">Perempuan</option></select></div>
|
|
<div class="field-error" id="errHouseGender" style="display: none; font-size: 11px; color: var(--danger); margin-top: 4px;">
|
|
<i class="fas fa-exclamation-circle"></i> Jenis Kelamin wajib diisi.
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Tanggal Lahir Kepala Keluarga <span style="color:red;">*</span></label><input type="date" id="houseDOB" required></div>
|
|
<div class="field-error" id="errHouseDOB" style="display: none; font-size: 11px; color: var(--danger); margin-top: 4px;">
|
|
<i class="fas fa-exclamation-circle"></i> Tanggal Lahir Kepala Keluarga wajib diisi.
|
|
</div>
|
|
<div class="form-group"><label>Pendidikan Kepala Keluarga <span style="color:red;">*</span></label>
|
|
<select id="houseEducation" onchange="recalcPoverty()">
|
|
<option value="tidak_sekolah">Tidak Sekolah</option><option value="sd" selected>SD</option><option value="smp">SMP</option>
|
|
<option value="sma">SMA</option><option value="diploma">Diploma</option><option value="sarjana">Sarjana</option><option value="pascasarjana">Pascasarjana</option>
|
|
</select>
|
|
</div>
|
|
<div class="field-error" id="errHouseEducation" style="display: none; font-size: 11px; color: var(--danger); margin-top: 4px;">
|
|
<i class="fas fa-exclamation-circle"></i> Pendidikan Kepala Keluarga wajib diisi.
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Status Pekerjaan <span style="color:red;">*</span></label>
|
|
<select id="houseEmploymentStatus" onchange="toggleHouseEmploymentFields()">
|
|
<option value="unemployed">Tidak Bekerja / Menganggur</option>
|
|
<option value="working">Bekerja</option>
|
|
<option value="studying">Sekolah / Kuliah</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Field untuk bekerja -->
|
|
<div class="form-group" id="houseJobGroup" style="display:none;">
|
|
<label>Nama Pekerjaan</label>
|
|
<input type="text" id="houseJob" placeholder="Contoh: Buruh Harian">
|
|
</div>
|
|
|
|
<!-- Field untuk sekolah -->
|
|
<div class="form-group" id="houseInstitutionGroup" style="display:none;">
|
|
<label>Nama Sekolah / Universitas</label>
|
|
<input type="text" id="houseInstitutionName" placeholder="Contoh: SMA Negeri 1">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-tab-panel" id="ftab-economic">
|
|
<div class="form-group"><label>Pendapatan/Bulan (Rp)</label><input type="number" id="houseIncome" min="0" value="0" onchange="recalcPoverty()"></div>
|
|
<div class="form-group"><label>Kepemilikan Lahan</label><select id="houseLandOwnership"><option value="milik">Milik Sendiri</option><option value="sewa">Sewa</option><option value="numpang">Numpang</option><option value="lainnya">Lainnya</option></select></div>
|
|
</div>
|
|
|
|
<div class="form-tab-panel" id="ftab-aid">
|
|
<div class="form-group"><label>Status Bantuan</label><select id="houseAidStatus"><option value="not_yet">Belum Terima Bantuan</option><option value="received">Sudah Terima Bantuan</option></select></div>
|
|
<div id="aidHistoryPanel" style="margin-top:12px;">
|
|
<div class="section-title" style="margin-bottom:8px;">
|
|
<span>Riwayat Bantuan</span>
|
|
<button type="button" class="btn btn-success btn-sm" id="addAidBtn" style="display:none;padding:5px 9px;font-size:10px;"><i class="fas fa-plus"></i> Catat</button>
|
|
</div>
|
|
<div id="aidHistoryList"><div class="empty-state" style="padding:14px;"><i class="fas fa-gift"></i><p>Belum ada riwayat bantuan</p></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group"><label>Keterangan</label><textarea id="houseDescription" rows="2" placeholder="Informasi tambahan..."></textarea></div>
|
|
<!-- Foto Rumah -->
|
|
<div class="form-group">
|
|
<label>Foto Rumah <span style="font-weight:400;font-size:10.5px;color:var(--text-muted);">(maks. 5 foto · 5 MB)</span></label>
|
|
<div class="photo-upload-zone" id="housePhotoZone" onclick="document.getElementById('housePhotos').click()">
|
|
<i class="fas fa-camera puz-icon"></i>
|
|
<span class="puz-label">Klik atau seret foto ke sini · JPG / PNG</span>
|
|
<input type="file" id="housePhotos" accept=".jpg,.jpeg,.png" multiple>
|
|
</div>
|
|
<div class="photo-strip" id="housePhotoStrip"></div>
|
|
<div class="photo-strip" id="houseSavedPhotoStrip"></div>
|
|
<div class="photo-error-msg" id="housePhotoError"></div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Latitude</label><input type="text" id="houseLatDisplay" readonly></div>
|
|
<div class="form-group"><label>Longitude</label><input type="text" id="houseLngDisplay" readonly></div>
|
|
</div>
|
|
|
|
<div class="modal-actions">
|
|
<button type="submit" class="btn btn-primary"><i class="fas fa-save"></i> Simpan</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('houseModal')">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Family Member -->
|
|
<div class="modal-overlay" id="familyMemberModal">
|
|
<div class="modal" style="max-width:500px;">
|
|
<div class="modal-header">
|
|
<h2 id="familyMemberModalTitle">Tambah Anggota Keluarga</h2>
|
|
<span class="modal-close" onclick="closeModal('familyMemberModal')">×</span>
|
|
</div>
|
|
<form id="memberForm" novalidate>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Nama Lengkap <span style="color:red;">*</span></label><input type="text" id="memberName" required></div>
|
|
<div class="form-group"><label>NIK</label><input type="text" id="memberNik" maxlength="16" placeholder="16 digit NIK"></div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Jenis Kelamin</label><select id="memberGender"><option value="male">Laki-laki</option><option value="female">Perempuan</option></select></div>
|
|
<div class="form-group"><label>Tanggal Lahir</label><input type="date" id="memberDob"></div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Pendidikan</label><select id="memberEducation">
|
|
<option value="tidak_sekolah">Tidak Sekolah</option><option value="sd">SD</option><option value="smp">SMP</option>
|
|
<option value="sma">SMA</option><option value="diploma">Diploma</option><option value="sarjana">Sarjana</option><option value="pascasarjana">Pascasarjana</option>
|
|
</select></div>
|
|
<div class="form-group"><label>Hubungan Keluarga</label><select id="memberRelationship">
|
|
<option value="ayah">Ayah</option><option value="ibu">Ibu</option><option value="istri">Istri</option><option value="anak">Anak</option>
|
|
<option value="kakek">Kakek</option><option value="nenek">Nenek</option><option value="paman">Paman</option>
|
|
<option value="bibi">Bibi</option><option value="sepupu">Sepupu</option><option value="keponakan">Keponakan</option><option value="lainnya">Lainnya</option>
|
|
</select></div>
|
|
</div>
|
|
<div class="form-group"><label>Status Pekerjaan</label>
|
|
<select id="memberEmploymentStatus" onchange="toggleMemberEmploymentFields()">
|
|
<option value="unemployed">Tidak Bekerja / Menganggur</option>
|
|
<option value="studying">Sekolah / Kuliah</option>
|
|
<option value="working">Bekerja</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group" id="memberJobGroup" style="display:none;"><label>Nama Pekerjaan</label><input type="text" id="memberJobName" placeholder="Contoh: Buruh Harian"></div>
|
|
<div class="form-group" id="memberInstitutionGroup" style="display:none;"><label>Nama Sekolah / Universitas</label><input type="text" id="memberInstitutionName" placeholder="Contoh: SMA Negeri 1"></div>
|
|
<div class="form-group"><label>Perkiraan Pendapatan (Rp)</label><input type="number" id="memberIncome" min="0" value="0"><small style="color:var(--text-muted);">Isi 0 jika tidak bekerja atau masih sekolah</small></div>
|
|
<div class="modal-actions">
|
|
<button type="button" class="btn btn-primary" onclick="saveFamilyMember()"><i class="fas fa-save"></i> Simpan</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('familyMemberModal')">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Aid Record -->
|
|
<div class="modal-overlay" id="aidModal">
|
|
<div class="modal" style="max-width:380px;">
|
|
<div class="modal-header"><h2>Catat Bantuan</h2><span class="modal-close" onclick="closeModal('aidModal')">×</span></div>
|
|
<form id="aidForm" novalidate>
|
|
<input type="hidden" id="aidHouseholdId">
|
|
<div class="form-group"><label>Jenis Bantuan *</label><select id="aidType">
|
|
<option value="sembako">Sembako</option><option value="pendanaan">Pendanaan</option><option value="pelatihan">Pelatihan</option>
|
|
<option value="sembako_pendanaan">Sembako + Pendanaan</option><option value="sembako_pelatihan">Sembako + Pelatihan</option>
|
|
<option value="pendanaan_pelatihan">Pendanaan + Pelatihan</option><option value="lengkap">Lengkap (Semua)</option>
|
|
</select></div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Tanggal *</label><input type="date" id="aidDate" required></div>
|
|
<div class="form-group"><label>Jumlah (Rp)</label><input type="number" id="aidAmount" min="0" value="0"></div>
|
|
</div>
|
|
<div class="form-group"><label>Catatan</label><textarea id="aidNotes" rows="2" placeholder="Catatan tambahan..."></textarea></div>
|
|
<div class="modal-actions">
|
|
<button type="submit" class="btn btn-primary"><i class="fas fa-save"></i> Simpan</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('aidModal')">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Admin Panel -->
|
|
<div class="modal-overlay" id="adminModal">
|
|
<div class="modal" style="max-width:750px;">
|
|
<div class="modal-header">
|
|
<h2><i class="fas fa-cog"></i> Laporan Publik</h2>
|
|
<span class="modal-close" onclick="closeModal('adminModal')">×</span>
|
|
</div>
|
|
<div class="admin-tabs"><button class="admin-tab active" data-atab="pending"><i class="fas fa-flag"></i> Laporan Publik<span class="pending-badge" id="pendingBadge"></span></button></div>
|
|
<div class="admin-tab-panel active" id="atab-pending">
|
|
<div class="admin-toolbar">
|
|
<select id="pendingStatusFilter" class="admin-search" style="max-width:150px;">
|
|
<option value="pending">Menunggu</option>
|
|
<option value="approved">Disetujui</option>
|
|
<option value="rejected">Ditolak</option>
|
|
<option value="">Semua Status</option>
|
|
</select>
|
|
<button class="btn btn-secondary btn-sm" onclick="loadPendingReports()"><i class="fas fa-sync"></i> Refresh</button>
|
|
</div>
|
|
<div class="admin-table-wrap">
|
|
<table class="admin-table" id="pendingTable">
|
|
<thead><tr><th>Waktu</th><th>Nama Warga</th><th>Alamat</th><th>Deskripsi</th><th>Status</th><th>Aksi</th></tr></thead>
|
|
<tbody id="pendingTbody"><tr><td colspan="6" class="text-center">Klik Refresh untuk memuat.</td></tr></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Approve -->
|
|
<div class="modal-overlay" id="approveModal">
|
|
<div class="modal" style="max-width:420px;">
|
|
<div class="modal-header">
|
|
<h2><i class="fas fa-check-circle" style="color:var(--success);"></i> Setujui Laporan</h2>
|
|
<span class="modal-close" onclick="closeModal('approveModal')">×</span>
|
|
</div>
|
|
<div id="approveReportPreview" style="background:var(--surface-2);border-radius:var(--r);padding:12px;margin-bottom:14px;font-size:12px;"></div>
|
|
<div class="photo-strip" id="approvePhotoPreview" style="margin-top:8px;"></div>
|
|
<form id="approveForm" novalidate>
|
|
<input type="hidden" id="approveReportId">
|
|
<p style="font-size:12px;color:var(--text-secondary);margin-bottom:12px;">Data rumah tangga akan dibuat dengan nilai default. Petugas dapat mengedit lengkap setelah data masuk ke peta.</p>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Perkiraan Pendapatan/Bln</label><input type="number" id="approveIncome" min="0" value="0"></div>
|
|
<div class="form-group"><label>Jumlah Anggota</label><input type="number" id="approveDependents" min="1" value="1"></div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>Kondisi Rumah</label><select id="approveCondition"><option value="tidak_layak" selected>Tidak Layak</option><option value="layak">Layak</option></select></div>
|
|
<div class="form-group"><label>Pendidikan KK</label><select id="approveEducation"><option value="tidak_sekolah">Tidak Sekolah</option><option value="sd" selected>SD</option><option value="smp">SMP</option><option value="sma">SMA</option><option value="sarjana">Sarjana</option></select></div>
|
|
</div>
|
|
<div class="form-group"><label>Catatan Admin (opsional)</label><textarea id="approveNotes" rows="2" placeholder="Catatan untuk laporan ini..."></textarea></div>
|
|
<div class="modal-actions">
|
|
<button type="submit" class="btn btn-approve"><i class="fas fa-check"></i> Setujui & Tambah ke Peta</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Reject -->
|
|
<div class="modal-overlay" id="rejectModal">
|
|
<div class="modal" style="max-width:380px;">
|
|
<div class="modal-header">
|
|
<h2><i class="fas fa-times-circle" style="color:var(--danger);"></i> Tolak Laporan</h2>
|
|
<span class="modal-close" onclick="closeModal('rejectModal')">×</span>
|
|
</div>
|
|
<form id="rejectForm" novalidate>
|
|
<input type="hidden" id="rejectReportId">
|
|
<div class="form-group"><label>Alasan Penolakan (opsional)</label><textarea id="rejectNotes" rows="3" placeholder="Contoh: Data duplikat, alamat tidak valid..."></textarea></div>
|
|
<div class="modal-actions">
|
|
<button type="submit" class="btn btn-reject"><i class="fas fa-times"></i> Tolak Laporan</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dashboard Modal -->
|
|
<div class="modal-overlay" id="dashboardModal">
|
|
<div class="modal" style="max-width:820px;max-height:90vh;">
|
|
<div class="modal-header">
|
|
<h2><i class="fas fa-chart-bar"></i> Dashboard Analitik</h2>
|
|
<span class="modal-close" onclick="closeModal('dashboardModal')">×</span>
|
|
</div>
|
|
<div class="dashboard-scroll">
|
|
<div class="dashboard-grid" id="dashboardGrid">
|
|
<div class="chart-card chart-card-sm"><div class="chart-card-header"><h3><i class="fas fa-chart-pie"></i> Distribusi Kemiskinan</h3></div><div class="chart-canvas-wrap"><canvas id="chartPoverty"></canvas></div></div>
|
|
<div class="chart-card chart-card-sm"><div class="chart-card-header"><h3><i class="fas fa-chart-line"></i> Tren Pendataan</h3><span class="chart-card-badge">12 Bulan</span></div><div class="chart-canvas-wrap"><canvas id="chartTrend"></canvas></div></div>
|
|
<div class="chart-card chart-card-sm"><div class="chart-card-header"><h3><i class="fas fa-user-clock"></i> Distribusi Usia</h3></div><div class="chart-canvas-wrap"><canvas id="chartAge"></canvas></div></div>
|
|
<div class="chart-card chart-card-sm"><div class="chart-card-header"><h3><i class="fas fa-hand-holding-heart"></i> Distribusi Bantuan</h3></div><div class="chart-canvas-wrap"><canvas id="chartAid"></canvas></div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Help Modal -->
|
|
<div class="modal-overlay" id="helpModal">
|
|
<div class="modal" style="max-width:500px;">
|
|
<div class="modal-header">
|
|
<h2><i class="fas fa-question-circle"></i> Panduan Pengguna</h2>
|
|
<span class="modal-close" onclick="closeModal('helpModal')">×</span>
|
|
</div>
|
|
<div class="help-steps" id="helpSteps">
|
|
<div class="help-step active" data-step="1"><div class="help-step-icon"><i class="fas fa-map-marked-alt"></i></div><h3>Selamat Datang di WebGIS Admin</h3><p>Halaman admin untuk mengelola data rumah tangga, tempat ibadah, dan memverifikasi laporan dari masyarakat.</p></div>
|
|
<div class="help-step" data-step="2"><div class="help-step-icon"><i class="fas fa-place-of-worship"></i></div><h3>Menambah Tempat Ibadah</h3><p>Klik tab <strong>"Ibadah"</strong> di sidebar, lalu klik lokasi pada peta. Form akan muncul untuk mengisi detail.</p></div>
|
|
<div class="help-step" data-step="3"><div class="help-step-icon"><i class="fas fa-home"></i></div><h3>Menambah Rumah Tangga</h3><p>Klik tab <strong>"Rumah"</strong>, lalu klik lokasi pada peta. Skor kemiskinan dihitung <em>otomatis</em> berdasarkan data yang diisi.</p></div>
|
|
<div class="help-step" data-step="4"><div class="help-step-icon"><i class="fas fa-flag"></i></div><h3>Verifikasi Laporan Publik</h3><p>Klik <strong>Panel Admin → Laporan Publik</strong> untuk melihat laporan dari masyarakat. Setujui untuk langsung menambah data ke peta.</p></div>
|
|
<div class="help-step" data-step="5"><div class="help-step-icon"><i class="fas fa-chart-bar"></i></div><h3>Dashboard & Laporan</h3><p>Klik tab <strong>"Chart"</strong> untuk grafik analitik. Marker dapat diseret untuk memindahkan posisi. Radius dapat diubah langsung dari popup.</p></div>
|
|
</div>
|
|
<div class="help-nav">
|
|
<button class="btn btn-secondary btn-sm" id="helpPrev" onclick="helpNav(-1)" disabled>← Sebelumnya</button>
|
|
<span id="helpProgress">1 / 5</span>
|
|
<button class="btn btn-primary btn-sm" id="helpNext" onclick="helpNav(1)">Berikutnya →</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
|
<script src="assets/js/config.js"></script>
|
|
<script src="assets/js/api.js"></script>
|
|
<script src="assets/js/auth.js"></script>
|
|
<script src="assets/js/map.js"></script>
|
|
<script src="assets/js/markers.js"></script>
|
|
<script src="assets/js/forms.js"></script>
|
|
<script src="assets/js/dashboard.js"></script>
|
|
<script src="assets/js/admin.js"></script>
|
|
<script src="assets/js/public-reports.js"></script>
|
|
<script src="assets/js/photo-upload.js"></script>
|
|
<script src="assets/js/app.js"></script>
|
|
<script>
|
|
'use strict';
|
|
|
|
// ================================================================
|
|
// iOS 100vh fix
|
|
// ================================================================
|
|
function setVH() {
|
|
const vh = window.innerHeight * 0.01;
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
}
|
|
setVH();
|
|
window.addEventListener('resize', () => {
|
|
setVH();
|
|
if (typeof MAP !== 'undefined' && MAP) setTimeout(() => MAP.invalidateSize(), 150);
|
|
});
|
|
window.addEventListener('orientationchange', () => {
|
|
setTimeout(() => { setVH(); if (typeof MAP !== 'undefined' && MAP) MAP.invalidateSize(); }, 300);
|
|
});
|
|
|
|
// ================================================================
|
|
// Legend Toggle - SATU FUNGSI UNTUK SEMUA (desktop + mobile)
|
|
// ================================================================
|
|
function toggleLegend() {
|
|
const legend = document.getElementById('legend');
|
|
const chevron = document.getElementById('legendChevron');
|
|
if (!legend) return;
|
|
|
|
legend.classList.toggle('collapsed');
|
|
|
|
if (chevron) {
|
|
chevron.className = legend.classList.contains('collapsed')
|
|
? 'fas fa-chevron-down'
|
|
: 'fas fa-chevron-up';
|
|
}
|
|
}
|
|
|
|
// Set legend default: collapsed on mobile, EXPANDED on desktop
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const legend = document.getElementById('legend');
|
|
if (legend) {
|
|
if (window.innerWidth <= 768) {
|
|
legend.classList.add('collapsed'); // mobile: collapsed
|
|
} else {
|
|
legend.classList.remove('collapsed'); // desktop: expanded
|
|
}
|
|
}
|
|
});
|
|
|
|
// ================================================================
|
|
// Mobile sidebar toggle
|
|
// ================================================================
|
|
function toggleMobileSidebar() {
|
|
const sidebar = document.getElementById('sidebar');
|
|
const backdrop = document.getElementById('sidebarBackdrop');
|
|
const isOpen = sidebar.classList.contains('mobile-open');
|
|
if (isOpen) {
|
|
closeMobileSidebar();
|
|
} else {
|
|
sidebar.classList.add('mobile-open');
|
|
backdrop.classList.add('active');
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
}
|
|
|
|
function closeMobileSidebar() {
|
|
const sidebar = document.getElementById('sidebar');
|
|
const backdrop = document.getElementById('sidebarBackdrop');
|
|
sidebar.classList.remove('mobile-open');
|
|
backdrop.classList.remove('active');
|
|
document.body.style.overflow = '';
|
|
}
|
|
|
|
// Close sidebar on nav/data-item click (mobile)
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
document.querySelectorAll('.nav-tab').forEach(tab => {
|
|
tab.addEventListener('click', () => {
|
|
if (window.innerWidth <= 768) setTimeout(closeMobileSidebar, 120);
|
|
});
|
|
});
|
|
const sidebar = document.getElementById('sidebar');
|
|
if (sidebar) {
|
|
sidebar.addEventListener('click', (e) => {
|
|
if (e.target.closest('.data-item') && window.innerWidth <= 768) setTimeout(closeMobileSidebar, 80);
|
|
});
|
|
}
|
|
const backdrop = document.getElementById('sidebarBackdrop');
|
|
if (backdrop) backdrop.addEventListener('click', closeMobileSidebar);
|
|
});
|
|
|
|
// Override closeModal to refresh Leaflet map
|
|
const _origCloseModal = window.closeModal;
|
|
if (typeof _origCloseModal === 'function') {
|
|
window.closeModal = function(id) {
|
|
_origCloseModal(id);
|
|
if (id === 'dashboardModal' && typeof MAP !== 'undefined' && MAP) {
|
|
setTimeout(() => MAP.invalidateSize(), 100);
|
|
}
|
|
};
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |