224 lines
10 KiB
PHP
224 lines
10 KiB
PHP
@extends('publik.layouts.app')
|
||
@section('title', 'Peta Sebaran Penerima BLT')
|
||
|
||
@section('content')
|
||
<div class="container-fluid px-0">
|
||
|
||
{{-- Header --}}
|
||
<div class="py-4 px-4 mb-0" style="background:linear-gradient(135deg,#1a3c2e,#2d7a4f);">
|
||
<div class="container">
|
||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
|
||
<div>
|
||
<h4 class="mb-1 fw-bold text-white">
|
||
<i class="bi bi-map-fill me-2"></i>Peta Sebaran Penerima BLT Dana Desa
|
||
</h4>
|
||
<p class="mb-0 small" style="color:rgba(255,255,255,0.75);">
|
||
Visualisasi distribusi geografis penerima bantuan per wilayah RW
|
||
</p>
|
||
</div>
|
||
|
||
{{-- Filter Periode --}}
|
||
@if($periodeList->isNotEmpty())
|
||
<form method="GET" action="{{ route('publik.peta') }}" class="d-flex align-items-center gap-2">
|
||
<label class="text-white fw-semibold" style="font-size:0.82rem;white-space:nowrap;">
|
||
<i class="bi bi-funnel me-1"></i>Periode:
|
||
</label>
|
||
<select name="periode_id" class="form-select form-select-sm" style="min-width:200px;" onchange="this.form.submit()">
|
||
@foreach($periodeList as $p)
|
||
<option value="{{ $p->id }}" {{ $periodeAktif && $periodeAktif->id == $p->id ? 'selected' : '' }}>
|
||
{{ $p->nama }}
|
||
</option>
|
||
@endforeach
|
||
</select>
|
||
</form>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Info Bar --}}
|
||
<div class="bg-white border-bottom shadow-sm">
|
||
<div class="container py-3">
|
||
<div class="row g-3 text-center">
|
||
<div class="col-6 col-md-3">
|
||
<div class="fw-bold fs-4 text-success" id="statPenerima">{{ $totalPenerima }}</div>
|
||
<div class="text-muted small">Total Penerima</div>
|
||
</div>
|
||
<div class="col-6 col-md-3">
|
||
<div class="fw-bold fs-4 text-primary" id="statWilayah">{{ $totalWilayah }}</div>
|
||
<div class="text-muted small">RW Terdampak</div>
|
||
</div>
|
||
<div class="col-6 col-md-3">
|
||
<div class="fw-bold fs-4 text-warning">
|
||
{{ $markers->pluck('dusun')->unique()->count() }}
|
||
</div>
|
||
<div class="text-muted small">Dusun</div>
|
||
</div>
|
||
<div class="col-6 col-md-3">
|
||
<div class="fw-bold fs-4 text-info">{{ $markers->count() }}</div>
|
||
<div class="text-muted small">RW</div>
|
||
</div>
|
||
</div>
|
||
@if($periodeAktif)
|
||
<div class="text-center mt-2">
|
||
<span class="badge" style="background:#e0f2e9;color:#2d7a4f;font-size:0.78rem;">
|
||
<i class="bi bi-calendar3 me-1"></i>{{ $periodeAktif->nama }}
|
||
•
|
||
{{ \Carbon\Carbon::parse($periodeAktif->tanggal_mulai)->format('d/m/Y') }}
|
||
–
|
||
{{ \Carbon\Carbon::parse($periodeAktif->tanggal_selesai)->format('d/m/Y') }}
|
||
</span>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Peta --}}
|
||
<div class="position-relative">
|
||
<div id="map" style="height: 500px; width: 100%;"></div>
|
||
|
||
{{-- Legend --}}
|
||
<div class="position-absolute bottom-0 start-0 m-3 bg-white rounded shadow-sm p-3" style="z-index: 999; min-width: 170px;">
|
||
<div class="fw-semibold small mb-2"><i class="bi bi-info-circle me-1"></i>Keterangan</div>
|
||
<div class="d-flex align-items-center gap-2 mb-1">
|
||
<div style="width:14px;height:14px;border-radius:50%;background:#15803d;border:2px solid white;box-shadow:0 0 3px rgba(0,0,0,0.3)"></div>
|
||
<small>Banyak penerima (≥3)</small>
|
||
</div>
|
||
<div class="d-flex align-items-center gap-2 mb-1">
|
||
<div style="width:14px;height:14px;border-radius:50%;background:#4ade80;border:2px solid white;box-shadow:0 0 3px rgba(0,0,0,0.3)"></div>
|
||
<small>2–3 penerima</small>
|
||
</div>
|
||
<div class="d-flex align-items-center gap-2 mb-1">
|
||
<div style="width:14px;height:14px;border-radius:50%;background:#86efac;border:2px solid white;box-shadow:0 0 3px rgba(0,0,0,0.3)"></div>
|
||
<small>1 penerima</small>
|
||
</div>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<div style="width:14px;height:14px;border-radius:50%;background:#6c757d;border:2px solid white;box-shadow:0 0 3px rgba(0,0,0,0.3)"></div>
|
||
<small>Belum ada penerima</small>
|
||
</div>
|
||
<hr class="my-2">
|
||
<small class="text-muted" style="font-size:10px;">
|
||
📍 Klik marker untuk detail<br>Titik = pusat wilayah RW
|
||
</small>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Tabel Ringkasan Per Wilayah --}}
|
||
<div class="container my-4">
|
||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||
<h6 class="fw-bold mb-0">
|
||
<i class="bi bi-table me-2 text-success"></i>Ringkasan Per Wilayah
|
||
</h6>
|
||
@if($periodeAktif)
|
||
<a href="{{ route('publik.penerima', ['periode_id' => $periodeAktif->id]) }}"
|
||
class="btn btn-sm btn-outline-success">
|
||
<i class="bi bi-list-check me-1"></i>Lihat Daftar Lengkap
|
||
</a>
|
||
@endif
|
||
</div>
|
||
|
||
@if($markers->isEmpty())
|
||
<div class="alert alert-info">
|
||
<i class="bi bi-info-circle me-2"></i>
|
||
Belum ada data penerima yang memiliki koordinat wilayah.
|
||
</div>
|
||
@else
|
||
<div class="table-responsive">
|
||
<table class="table table-hover table-bordered align-middle">
|
||
<thead class="table-success">
|
||
<tr>
|
||
<th>Dusun</th>
|
||
<th>RW</th>
|
||
<th class="text-center">Jumlah Penerima</th>
|
||
<th class="text-center">Rata-rata Skor SAW</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach($markers->sortByDesc('jumlah_penerima') as $m)
|
||
<tr>
|
||
<td><i class="bi bi-geo-alt-fill text-success me-1"></i>{{ $m['dusun'] }}</td>
|
||
<td>RW {{ $m['rw'] }}</td>
|
||
<td class="text-center">
|
||
@if($m['jumlah_penerima'] > 0)
|
||
<span class="badge bg-success rounded-pill">{{ $m['jumlah_penerima'] }} orang</span>
|
||
@else
|
||
<span class="text-muted">—</span>
|
||
@endif
|
||
</td>
|
||
<td class="text-center font-monospace">
|
||
{{ $m['avg_skor'] > 0 ? $m['avg_skor'] : '—' }}
|
||
</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
|
||
</div>
|
||
@endsection
|
||
|
||
@push('scripts')
|
||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||
<script>
|
||
var map = L.map('map', {
|
||
center: [-7.529855, 112.578704],
|
||
zoom: 14,
|
||
zoomControl: true,
|
||
});
|
||
|
||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
attribution: '© <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors',
|
||
maxZoom: 19,
|
||
}).addTo(map);
|
||
|
||
var markers = JSON.parse('{!! addslashes(json_encode($markers->values())) !!}');
|
||
|
||
function warna(jumlah) {
|
||
if (jumlah === 0) return '#6c757d';
|
||
if (jumlah === 1) return '#86efac';
|
||
if (jumlah <= 2) return '#4ade80';
|
||
return '#15803d';
|
||
}
|
||
|
||
function buatIcon(jumlah) {
|
||
var c = warna(jumlah);
|
||
return L.divIcon({
|
||
className: '',
|
||
html: `<div style="background:${c};width:36px;height:36px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);border:3px solid white;box-shadow:0 2px 8px rgba(0,0,0,0.3);display:flex;align-items:center;justify-content:center;">
|
||
<span style="transform:rotate(45deg);color:white;font-weight:bold;font-size:12px;">${jumlah}</span>
|
||
</div>`,
|
||
iconSize: [36, 36],
|
||
iconAnchor: [18, 36],
|
||
popupAnchor: [0, -38],
|
||
});
|
||
}
|
||
|
||
markers.forEach(function(item) {
|
||
var marker = L.marker([item.latitude, item.longitude], { icon: buatIcon(item.jumlah_penerima) });
|
||
marker.bindPopup(`
|
||
<div style="min-width:200px;font-family:sans-serif;">
|
||
<div style="background:#2d7a4f;color:white;padding:8px 12px;margin:-14px -20px 10px;border-radius:4px 4px 0 0;">
|
||
<strong>📍 ${item.label}</strong>
|
||
</div>
|
||
<table style="width:100%;font-size:13px;">
|
||
<tr><td style="color:#666;padding:3px 0;">Dusun</td><td><strong>${item.dusun}</strong></td></tr>
|
||
<tr><td style="color:#666;padding:3px 0;">RW</td><td><strong>${item.rw}</strong></td></tr>
|
||
<tr><td style="color:#666;padding:3px 0;">Penerima BLT</td>
|
||
<td><strong style="color:${item.jumlah_penerima > 0 ? '#198754' : '#9ca3af'};">
|
||
${item.jumlah_penerima} orang</strong></td></tr>
|
||
${item.jumlah_penerima > 0 ? `<tr><td style="color:#666;padding:3px 0;">Rata-rata Skor</td><td><strong>${item.avg_skor}</strong></td></tr>` : ''}
|
||
</table>
|
||
</div>
|
||
`, { maxWidth: 260 });
|
||
marker.addTo(map);
|
||
});
|
||
|
||
if (markers.length > 0) {
|
||
var bounds = markers.map(m => [m.latitude, m.longitude]);
|
||
map.fitBounds(bounds, { padding: [80, 80], maxZoom: 13 });
|
||
}
|
||
</script>
|
||
@endpush |