refactor (landing): map section

using leaflet
main
Yuri Dimas 2025-12-02 00:47:21 +07:00
parent b242848f10
commit 4f71b05c28
No known key found for this signature in database
GPG Key ID: 9FD7E44BC294C68C
2 changed files with 266 additions and 50 deletions

View File

@ -413,62 +413,75 @@
</section> </section>
<!-- Location Map Section --> <!-- Location Map Section -->
<section class="p-4 lg:p-28 bg-gray-100"> <section id="location" class="pt-24 bg-white">
<div class="max-w-[1280px] mx-auto flex flex-col justify-start items-start gap-10"> <div class="flex flex-col w-full gap-4">
<div class="flex flex-col justify-start items-start gap-8 w-full"> <div class="flex flex-col gap-2 w-full max-w-7xl mx-auto px-4 lg:px-0 justify-start">
<div class="flex flex-col justify-start items-start gap-4 w-full"> <h5 class="text-green-600">Titik Lokasi</h5>
<!-- Badge --> <h2 class="text-gray-900 text-3xl lg:text-4xl font-bold font-jakarta leading-10">Lokasi Bank Sampah</h2>
<div class="px-4 py-2 bg-gray-300 rounded-3xl flex justify-center items-center gap-2">
<div class="w-4 h-4 relative">
<div class="w-3 h-3 absolute top-[1.5px] left-[1.5px] bg-green-800 rounded-full"></div>
</div>
<div class="text-green-800 text-base font-bold font-jakarta">Bank Sampah</div>
</div>
<h2 class="text-gray-900 text-3xl lg:text-4xl font-bold font-jakarta leading-10">Lokasi Bank Sampah</h2>
</div>
</div> </div>
<!-- Map Container --> <div class="w-full flex flex-col gap-6 mx-auto items-center p-6 bg-gray-100">
<div class="relative h-[400px] lg:h-[624px] w-full flex justify-center items-start gap-4"> <div class="grid grid-cols-1 md:grid-cols-5 gap-4 w-full max-w-7xl">
<div class="flex-1 h-full p-6 bg-white rounded-2xl border border-gray-200 flex flex-col justify-start items-start gap-6"> <div class="flex flex-col gap-2">
<!-- Map placeholder with markers --> <label class="text-sm font-semibold text-gray-700">Jenis Bank Sampah</label>
<div class="w-full flex-1 relative bg-gray-200 rounded-lg overflow-hidden"> <select class="select select-bordered w-full" data-bank-filter="type">
<img class="w-full h-full object-cover" src="/images/maps.png" alt="Jakarta Map" /> <option value="all">Semua Jenis</option>
<option value="BSI">Bank Sampah Induk (BSI)</option>
<!-- Map Markers --> <option value="BSU">Bank Sampah Unit (BSU)</option>
<div class="absolute inset-0"> </select>
<!-- Sample markers positioned across Jakarta --> </div>
<div class="absolute top-[30%] left-[15%] p-2 bg-green-800 rounded-full map-marker"> <div class="flex flex-col gap-2">
<svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 24 24"> <label class="text-sm font-semibold text-gray-700">Kota</label>
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> <select class="select select-bordered w-full" data-bank-filter="kota">
</svg> <option value="all">Semua Kota</option>
</div> <option value="Jakarta Pusat">Jakarta Pusat</option>
<div class="absolute top-[25%] left-[35%] p-2 bg-green-800 rounded-full map-marker"> <option value="Jakarta Barat">Jakarta Barat</option>
<svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 24 24"> <option value="Jakarta Selatan">Jakarta Selatan</option>
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> <option value="Jakarta Timur">Jakarta Timur</option>
</svg> <option value="Jakarta Utara">Jakarta Utara</option>
</div> <option value="Kepulauan Seribu">Kepulauan Seribu</option>
<div class="absolute top-[40%] left-[50%] p-2 bg-green-800 rounded-full map-marker"> </select>
<svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 24 24"> </div>
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> <div class="flex flex-col gap-2">
</svg> <label class="text-sm font-semibold text-gray-700">Kecamatan</label>
</div> <select class="select select-bordered w-full" data-bank-filter="kecamatan">
<div class="absolute top-[55%] left-[25%] p-2 bg-green-800 rounded-full map-marker"> <option value="all">Semua Kecamatan</option>
<svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 24 24"> <option value="Kemayoran">Kemayoran</option>
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> <option value="Palmerah">Palmerah</option>
</svg> <option value="Mampang Prapatan">Mampang Prapatan</option>
</div> <option value="Cipayung">Cipayung</option>
<div class="absolute top-[35%] left-[70%] p-2 bg-green-800 rounded-full map-marker"> <option value="Pademangan">Pademangan</option>
<svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 24 24"> <option value="Kepulauan Seribu Selatan">Kepulauan Seribu Selatan</option>
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> </select>
</svg> </div>
</div> <div class="flex flex-col gap-2">
<!-- More markers can be added here --> <label class="text-sm font-semibold text-gray-700">Kelurahan</label>
</div> <select class="select select-bordered w-full" data-bank-filter="kelurahan">
<option value="all">Semua Kelurahan</option>
<option value="Cempaka Baru">Cempaka Baru</option>
<option value="Slipi">Slipi</option>
<option value="Tegal Parang">Tegal Parang</option>
<option value="Cilangkap">Cilangkap</option>
<option value="Pademangan Timur">Pademangan Timur</option>
<option value="Pulau Tidung">Pulau Tidung</option>
</select>
</div>
<div class="flex flex-col gap-2">
<label class="text-sm font-semibold text-gray-700">RW (Rukun Warga)</label>
<select class="select select-bordered w-full" data-bank-filter="rw">
<option value="all">Semua RW</option>
<option value="RW 05">RW 05</option>
<option value="RW 03">RW 03</option>
<option value="RW 07">RW 07</option>
<option value="RW 10">RW 10</option>
<option value="RW 12">RW 12</option>
<option value="RW 02">RW 02</option>
</select>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div id="jakartaMap" class="w-full h-[600px] overflow-hidden"></div>
</section> </section>
<!-- Help Desk Section --> <!-- Help Desk Section -->
@ -613,8 +626,178 @@
</div> </div>
</section> </section>
@section Styles {
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
}
@section Scripts { @section Scripts {
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script> <script>
// Leaflet map configuration for DKI Jakarta
(function () {
if (typeof L === 'undefined') return;
const mapContainer = document.getElementById('jakartaMap');
if (!mapContainer) return;
const map = L.map('jakartaMap', {
center: [-6.2, 106.816666],
zoom: 11,
scrollWheelZoom: false
});
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors'
}).addTo(map);
const bankSampahData = [
{
name: 'Bank Sampah Induk Cempaka',
type: 'BSI',
kota: 'Jakarta Pusat',
kecamatan: 'Kemayoran',
kelurahan: 'Cempaka Baru',
rw: 'RW 05',
address: 'Jl. Cempaka Baru No. 8, Kemayoran, Jakarta Pusat',
phone: '+62 812-3456-7890',
coords: [-6.1725, 106.8653],
rates: {
kardus: 'Rp 2.800/kg',
botolBersih: 'Rp 3.200/kg',
botolKotor: 'Rp 2.100/kg'
}
},
{
name: 'Bank Sampah Unit Slipi Hijau',
type: 'BSU',
kota: 'Jakarta Barat',
kecamatan: 'Palmerah',
kelurahan: 'Slipi',
rw: 'RW 03',
address: 'Jl. KS Tubun II C No. 15, Slipi, Jakarta Barat',
phone: '+62 813-8899-2211',
coords: [-6.1973, 106.8029],
rates: {
kardus: 'Rp 2.600/kg',
botolBersih: 'Rp 3.000/kg',
botolKotor: 'Rp 2.000/kg'
}
},
{
name: 'Bank Sampah Mandiri Tegal Parang',
type: 'BSU',
kota: 'Jakarta Selatan',
kecamatan: 'Mampang Prapatan',
kelurahan: 'Tegal Parang',
rw: 'RW 07',
address: 'Jl. Mampang Prapatan VI No. 3, Jakarta Selatan',
phone: '+62 821-9090-4545',
coords: [-6.2482, 106.8181],
rates: {
kardus: 'Rp 2.500/kg',
botolBersih: 'Rp 2.900/kg',
botolKotor: 'Rp 1.900/kg'
}
},
{
name: 'Bank Sampah Cilangkap Berdaya',
type: 'BSU',
kota: 'Jakarta Timur',
kecamatan: 'Cipayung',
kelurahan: 'Cilangkap',
rw: 'RW 10',
address: 'Jl. Cilangkap Raya No. 2, Cipayung, Jakarta Timur',
phone: '+62 877-4567-1122',
coords: [-6.3194, 106.9004],
rates: {
kardus: 'Rp 2.400/kg',
botolBersih: 'Rp 2.800/kg',
botolKotor: 'Rp 1.850/kg'
}
},
{
name: 'Bank Sampah Laut Pulau Tidung',
type: 'BSI',
kota: 'Kepulauan Seribu',
kecamatan: 'Kepulauan Seribu Selatan',
kelurahan: 'Pulau Tidung',
rw: 'RW 02',
address: 'Pulau Tidung Besar, Kepulauan Seribu',
phone: '+62 857-8899-7788',
coords: [-5.7987, 106.5244],
rates: {
kardus: 'Rp 3.000/kg',
botolBersih: 'Rp 3.400/kg',
botolKotor: 'Rp 2.200/kg'
}
}
];
const markersLayer = L.layerGroup().addTo(map);
const filters = {
type: 'all',
kota: 'all',
kecamatan: 'all',
kelurahan: 'all',
rw: 'all'
};
const filterControls = document.querySelectorAll('[data-bank-filter]');
filterControls.forEach(select => {
select.addEventListener('change', () => {
filters[select.dataset.bankFilter] = select.value;
renderMarkers();
});
});
const popupTemplate = (data) =>
`<div class="card w-72 bg-base-100 shadow-xl border border-gray-200 rounded-2xl overflow-hidden">` +
`<div class="bg-neutral text-neutral-content px-4 py-3">` +
`<h3 class="text-lg font-semibold">` + data.name + `</h3>` +
`</div>` +
`<div class="card-body p-4 text-sm text-gray-700">` +
`<div class="flex place-items-center gap-3">` +
`<span class="text-primary"><i class="ph ph-house-line"></i></span>` +
`<p>` + data.address + `</p>` +
`</div>` +
`<div class="flex items-center gap-3">` +
`<span class="text-primary"><i class="ph ph-phone"></i></span>` +
`<p class="font-medium">` + data.phone + `</p>` +
`</div>` +
`<div class="divider my-0 py-0"></div>` +
`<p class="text-xs font-semibold tracking-wide text-gray-500 mb-2">Kurs Sampah Daur Ulang</p>` +
`<div class="space-y-1 text-gray-900">` +
`<div class="flex items-center justify-between"><span>Kardus</span><span class="font-semibold">` + data.rates.kardus + `</span></div>` +
`<div class="flex items-center justify-between"><span>Botol Bersih</span><span class="font-semibold">` + data.rates.botolBersih + `</span></div>` +
`<div class="flex items-center justify-between"><span>Botol Kotor</span><span class="font-semibold">` + data.rates.botolKotor + `</span></div>` +
`</div>` +
`</div>` +
`</div>`;
function renderMarkers() {
markersLayer.clearLayers();
bankSampahData
.filter(item => {
return Object.entries(filters).every(([key, value]) => value === 'all' || item[key] === value);
})
.forEach(item => {
const markerIcon = L.divIcon({
className: '',
html: '<div class="bank-map-marker"><i class="ph-fill ph-map-pin"></i></div>',
iconSize: [32, 32],
iconAnchor: [16, 32]
});
L.marker(item.coords, { icon: markerIcon })
.bindPopup(popupTemplate(item))
.addTo(markersLayer);
});
}
renderMarkers();
})();
// Smooth scrolling untuk anchor links // Smooth scrolling untuk anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => { document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) { anchor.addEventListener('click', function (e) {

View File

@ -212,3 +212,36 @@
div.dt-scroll-body thead { div.dt-scroll-body thead {
visibility: collapse !important; visibility: collapse !important;
} }
@layer components {
/* Icon Marker - leaflet map */
.bank-map-marker {
width: 32px;
height: 32px;
border-radius: 9999px;
background: linear-gradient(135deg, #ff5a5f, #ff2e63);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(255, 46, 99, 0.4);
}
}
/* Popup modal detail Pin Point - leaflet map */
#jakartaMap .leaflet-popup-content-wrapper {
background: transparent;
box-shadow: none;
border-radius: 0;
padding: 0;
}
#jakartaMap .leaflet-popup-content {
margin: 0;
line-height: inherit;
}
#jakartaMap .leaflet-popup-tip-container {
display: none;
}