dashboard indeks petani

This commit is contained in:
2026-08-07 12:59:25 +07:00
parent d4c6b64ba6
commit 8b21fab8b8
3 changed files with 288 additions and 9 deletions
@@ -1,5 +1,11 @@
@extends('layout.main')
@push('style')
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
@endpush
@section('content')
@php
$segments = [
@@ -33,6 +39,7 @@ $colors = collect($segments)
->pluck('color')
->map(fn($c) => "var(--bs-{$c})")
->values();
$segmentStyles = collect($segments)->keyBy('name');
$countSegmentasi = $countSegmentasi->keyBy('segmen');
$seriesSegmentasi = collect($segments)->map(function ($segment) use ($countSegmentasi) {
@@ -55,6 +62,34 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
];
})->values();
$segmenDominan = $mapSegmentasi
->groupBy('desa_kelurahan_id')
->map(function ($items) {
return $items->sortByDesc('total')->first();
});
$mapAvgSkorSegmentasi->each(function ($item) use ($segmenDominan) {
$dominan = $segmenDominan->get($item->desa_kelurahan_id);
$item->segmen_dominan = $dominan?->segmen;
$item->jumlah_dominan = $dominan?->total;
});
$segmentasiByDesa = $mapAvgSkorSegmentasi->keyBy('desa_kelurahan_id');
$desaLookup = $desaKelurahan->keyBy('desa_kelurahan_id');
$mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use ($desaLookup) {
$desa = $desaLookup->get($desaId);
if (!$desa) {
return null;
}
$desa->segmentasi = $segmentasi;
return $desa;
})->filter()->values();
@endphp
<div class="container-xxl flex-grow-1 container-p-y">
<div class="row g-6">
@@ -203,7 +238,7 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
<div class="row g-6 py-4">
<div class="col-lg-6 col-sm-12">
<div class="card h-100">
<div class="card card-border-shadow-info h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="card-title mb-0">
<h5 class="m-0 me-2">Rata-rata Dimensi Kesiapan Adopsi</h5>
@@ -227,7 +262,7 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
</div>
</div>
<div class="col-lg-6 col-sm-12">
<div class="card h-100">
<div class="card card-border-shadow-warning h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="card-title mb-0">
<h5 class="m-0 me-2">Rata-rata Komponen Kesiapan Adopsi</h5>
@@ -260,12 +295,124 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
</div>
</div>
</div>
<div class="row g-6 py-4">
<div class="col-lg-6 col-sm-12">
<div class="card card-border-shadow-danger h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="card-title mb-0">
<h5 class="m-0 me-2">Sebaran Segmentasi Petani</h5>
<p class="card-subtitle">berdasarkan sebaran wilayah untuk semua komoditas</p>
</div>
</div>
<div class="card-body">
<div id="map-sebaran-petani" style="height: 380px;"></div>
<span class="small text-muted">*klik pada desa untuk menampilkan detail informasi dan menyaring daftar petani</span>
</div>
</div>
</div>
<div class="col-lg-6 col-sm-12">
<div class="card card-border-shadow-success h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="card-title mb-0">
<h5 class="m-0 me-2">Distribusi Segmentasi Petani</h5>
<p class="card-subtitle">berdasarkan sebaran wilayah untuk semua komoditas</p>
</div>
</div>
<div class="card-body">
<table id="table-desa" class="table card-table table-border-top-0 table-border-bottom-0">
<thead>
<tr>
<th class="pe-0">Desa/Kelurahan</th>
<th class="text-end pe-0">Petani</th>
<th class="pe-0">Segmen Rata-rata</th>
<th class="pe-0">Segmen Dominan</th>
</tr>
</thead>
<tbody>
@foreach ($mapDesaSegmentasi as $desa)
@php
$style = $segmentStyles[$desa->segmentasi->segmen] ?? null;
$styleDominan = $segmentStyles[$desa->segmentasi->segmen_dominan] ?? null;
@endphp
<tr>
<td class="pe-0">{{ $desa->desa_kelurahan }}</td>
<td class="text-end pe-0">{{ number_format($desa->segmentasi->jumlah_petani) }}</td>
<td class="pe-0">
<span class="badge bg-{{ $style['color'] ?? 'secondary' }}">
{{ $desa->segmentasi->segmen }}
</span>
({{ number_format($desa->segmentasi->skor, 2, ',', '.') }})
</td>
<td class="pe-0">
<span class="badge bg-{{ $styleDominan['color'] ?? 'secondary' }}">
{{ $desa->segmentasi->segmen_dominan }}
</span>
({{ number_format($desa->segmentasi->jumlah_dominan) }} petani)
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row g-6 py-4">
<div class="col-lg-12 col-sm-12">
<div class="card card-border-shadow-primary h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="card-title mb-0">
<h5 class="m-0 me-2">Daftar Petani</h5>
<p class="card-subtitle">untuk semua komoditas</p>
</div>
</div>
<div class="card-body">
<table id="table-petani" class="table card-table table-border-top-0 table-border-bottom-0">
<thead>
<tr>
<th class="pe-0">Nama Petani</th>
<th class="pe-0">Komoditas</th>
<th class="text-end pe-0">Luas Lahan (ha)</th>
<th class="text-end pe-0">Indeks Kesiapan Adopsi</th>
<th class="pe-0">Segmen</th>
</tr>
</thead>
<tbody>
@foreach ($daftarPetani as $item)
@php
$style = $segmentStyles[$item->segmen()] ?? null;
@endphp
<tr data-desa="{{ $item->desa_kelurahan_id }}">
<td class="pe-0">{{ $item->nama }}</td>
<td class="pe-0">{{ $item->komoditas?->nama }}</td>
<td class="text-end pe-0">{{ number_format($item->lahans?->sum('luas_lahan'), 2, ',', '.') }}</td>
<td class="text-end pe-0">{{ $item->skor ? number_format($item->skor?->skor_kesiapan_adopsi, 2, ',', '.') : '' }}</td>
<td class="pe-0">
@if ($item->skor)
<span class="badge bg-{{ $style['color'] ?? 'secondary' }}">
{{ $item->segmen() }}
</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<script>
$('.data-table').DataTable({
@@ -279,6 +426,29 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
"scrollX": true
});
var tablePetani = $('#table-petani').DataTable({
"paging": true,
"lengthChange": true,
"searching": true,
"ordering": true,
"info": true,
"autoWidth": false,
"responsive": false,
"scrollX": true
});
let selectedDesa = null;
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
if (!selectedDesa) return true;
if (settings.nTable.id === 'table-petani') {
const row = tablePetani.row(dataIndex).node();
return $(row).data('desa') == selectedDesa;
}
return true;
});
// Chart Segmentasi Petani
var optionsSegmentasiPetani = {
series: @json($seriesSegmentasi),
@@ -315,7 +485,7 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
},
responsive: [
{
breakpoint: 480,
breakpoint: 360,
options: {
chart: {
width: 240,
@@ -390,7 +560,7 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
var radarDimensi = new ApexCharts($("#chart-dimensi")[0],
options = {
chart: {
height: 340,
height: 240,
type: 'radar',
toolbar: {
show: false
@@ -483,7 +653,7 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
var radarKomponen = new ApexCharts($("#chart-komponen")[0],
options = {
chart: {
height: 340,
height: 240,
type: 'radar',
toolbar: {
show: false
@@ -576,5 +746,57 @@ $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($c
]
});
radarKomponen.render();
// Map Sebaran Petani
var map = L.map('map-sebaran-petani').setView([-0.789, 113.921], 5);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
const desaData = @json($mapDesaSegmentasi);
const warnaSegmen = {
@foreach($segments as $segment)
"{{ $segment['name'] }}": "var(--bs-{{ $segment['color'] }})",
@endforeach
};
const group = L.featureGroup().addTo(map);
desaData.forEach(desa => {
if (!desa.path) return;
const coordinates = JSON.parse(desa.path);
const polygon = L.polygon(coordinates, {
color: '#666',
weight: 1,
fillColor: warnaSegmen[desa.segmentasi.segmen] || '#ccc',
fillOpacity: 0.7
});
polygon.desaId = desa.desa_kelurahan_id;
polygon.bindPopup(`
<b>Desa/Kel.: ${desa.desa_kelurahan}</b><br>
Kec.: ${desa.kecamatan}<br>
Kab.: ${desa.kabupaten}<br>
<hr>
Petani: ${desa.segmentasi.jumlah_petani}<br>
Indeks: ${Number(desa.segmentasi.skor).toFixed(2)}<br>
Segmen: <b>${desa.segmentasi.segmen}</b><br>
Segmen Dominan: <b>${desa.segmentasi.segmen_dominan}</b> (${desa.segmentasi.jumlah_dominan} petani)
`);
polygon.on('click', function () {
selectedDesa = desa.desa_kelurahan_id;
tablePetani.draw();
});
polygon.addTo(group);
});
if (group.getLayers().length > 0) {
map.fitBounds(group.getBounds(), {
padding: [20, 20]
});
}
</script>
@endpush