MIF_E31231754/resources/views/publik/peta.blade.php

224 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@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 }}
&bull;
{{ \Carbon\Carbon::parse($periodeAktif->tanggal_mulai)->format('d/m/Y') }}
&ndash;
{{ \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>23 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