diff --git a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php index 2aa64d7..9f4a55c 100644 --- a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php +++ b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php @@ -15,6 +15,7 @@ use App\Models\Pertanian\PraktikBudidaya; use App\Models\Pertanian\Produksi; use App\Models\Pertanian\SkorPetani; use App\Models\Pertanian\SosialEkonomi; +use App\Models\Pertanian\SurveyProduktivitas; use App\Models\Wilayah\DesaKelurahan; use App\Models\Wilayah\KabupatenKota; use App\Models\Wilayah\Kecamatan; @@ -120,6 +121,12 @@ class IndikatorPertanianController extends Controller 'keparahanSerangan' => $this->keparahanSeranganChart($initialFilters), 'statusHakKelolaLahan' => $this->statusHakKelolaLahanChart($initialFilters), 'praktikPemupukan' => $this->praktikPemupukanChart($initialFilters), + 'produksiPerKomoditas' => $this->produksiPerKomoditasChart($initialFilters), + 'produktivitasPerKomoditas' => $this->produktivitasPerKomoditasChart($initialFilters), + 'luasPanenPerKomoditas' => $this->luasPanenPerKomoditasChart($initialFilters), + 'statusPanen' => $this->statusPanenChart($initialFilters), + 'surveyProduktivitasHa' => $this->surveyProduktivitasByUnitChart($initialFilters, 'ha_tahun'), + 'surveyProduktivitasPohon' => $this->surveyProduktivitasByUnitChart($initialFilters, 'pohon_tahun'), ], ]); } @@ -410,6 +417,123 @@ class IndikatorPertanianController extends Controller ); } + private function produksiPerKomoditasChart(array $filters): array + { + $rows = $this->applyProduksiFilters(Produksi::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'produksi.komoditas_id') + ->whereNotNull('jumlah_panen') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('produksi.jumlah_panen') + ->selectRaw('produksi.satuan') + ->get() + ->groupBy('label') + ->map(fn ($items) => round($items->sum( + fn (Produksi $produksi) => $this->toKilograms( + (float) $produksi->jumlah_panen, + (string) $produksi->satuan + ) + ), 2)) + ->filter(fn ($total) => $total > 0) + ->sortDesc(); + + return [ + 'labels' => $rows->keys()->values()->all(), + 'series' => $rows->values()->map(fn ($value) => round((float) $value, 2))->values()->all(), + ]; + } + + private function produktivitasPerKomoditasChart(array $filters): array + { + $rows = $this->applyProduksiFilters(Produksi::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'produksi.komoditas_id') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('produksi.jumlah_panen') + ->selectRaw('produksi.satuan') + ->selectRaw('produksi.luas_panen') + ->selectRaw('produksi.produktivitas') + ->get() + ->groupBy('label') + ->map(function ($items) { + $storedAverage = $items + ->pluck('produktivitas') + ->filter(fn ($value) => (float) $value > 0) + ->avg(); + + if ($storedAverage > 0) { + return round((float) $storedAverage, 2); + } + + $totalProduksiKg = $items->sum( + fn (Produksi $produksi) => $this->toKilograms( + (float) $produksi->jumlah_panen, + (string) $produksi->satuan + ) + ); + $totalLuasPanen = $items->sum(fn (Produksi $produksi) => (float) $produksi->luas_panen); + + return $totalLuasPanen > 0 + ? round($totalProduksiKg / $totalLuasPanen, 2) + : 0; + }) + ->filter(fn ($total) => $total > 0) + ->sortDesc(); + + return [ + 'labels' => $rows->keys()->values()->all(), + 'series' => $rows->values()->map(fn ($value) => round((float) $value, 2))->values()->all(), + ]; + } + + private function luasPanenPerKomoditasChart(array $filters): array + { + $rows = $this->applyProduksiFilters(Produksi::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'produksi.komoditas_id') + ->whereNotNull('luas_panen') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('SUM(produksi.luas_panen) as total') + ->groupBy('k.id', 'k.nama') + ->havingRaw('SUM(produksi.luas_panen) > 0') + ->orderByDesc('total') + ->get(); + + return [ + 'labels' => $rows->pluck('label')->values()->all(), + 'series' => $rows->pluck('total')->map(fn ($value) => round((float) $value, 2))->values()->all(), + ]; + } + + private function statusPanenChart(array $filters): array + { + $rows = $this->applyProduksiFilters(Produksi::query(), $filters) + ->whereNotNull('status_panen') + ->selectRaw("COALESCE(status_panen, 'Belum ditentukan') as label") + ->selectRaw('COUNT(produksi.id) as total') + ->groupBy('status_panen') + ->orderByDesc('total') + ->get(); + + return $this->chartFromRows($rows, fn ($label) => $this->shortEnumLabel((string) $label)); + } + + private function surveyProduktivitasByUnitChart(array $filters, string $unit): array + { + $rows = $this->applySurveyProduktivitasFilters(SurveyProduktivitas::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'survey_produktivitas.komoditas_id') + ->where('satuan', $unit) + ->whereNotNull('kuantitas') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('AVG(survey_produktivitas.kuantitas) as total') + ->groupBy('k.id', 'k.nama') + ->havingRaw('AVG(survey_produktivitas.kuantitas) > 0') + ->orderByDesc('total') + ->get(); + + return [ + 'labels' => $rows->pluck('label')->values()->all(), + 'series' => $rows->pluck('total')->map(fn ($value) => round((float) $value, 2))->values()->all(), + ]; + } + private function chartFromRows($rows, callable $labelResolver): array { return [ @@ -505,6 +629,15 @@ class IndikatorPertanianController extends Controller }); } + private function applySurveyProduktivitasFilters($query, array $filters) + { + return $query + ->whereHas('petani', function ($petani) use ($filters) { + $this->applyPetaniFilters($petani, $filters); + }) + ->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('komoditas_id', $filters['komoditas'])); + } + private function applyTanamanTableFilters($query, array $filters) { return $query diff --git a/resources/views/dashboard/indikator-pertanian.blade.php b/resources/views/dashboard/indikator-pertanian.blade.php index 9d0af4b..6046602 100644 --- a/resources/views/dashboard/indikator-pertanian.blade.php +++ b/resources/views/dashboard/indikator-pertanian.blade.php @@ -146,7 +146,13 @@ #chart-penyakit-tanaman .apexcharts-tooltip, #chart-keparahan-serangan .apexcharts-tooltip, #chart-status-hak-kelola-lahan .apexcharts-tooltip, - #chart-praktik-pemupukan .apexcharts-tooltip { + #chart-praktik-pemupukan .apexcharts-tooltip, + #chart-produksi-komoditas .apexcharts-tooltip, + #chart-produktivitas-komoditas .apexcharts-tooltip, + #chart-luas-panen-komoditas .apexcharts-tooltip, + #chart-status-panen .apexcharts-tooltip, + #chart-survey-produktivitas-ha .apexcharts-tooltip, + #chart-survey-produktivitas-pohon .apexcharts-tooltip { background: transparent !important; border: none !important; box-shadow: none !important; @@ -531,12 +537,100 @@ +
+
+
+
+
+
+
Total Produksi per Komoditas
+ Akumulasi hasil panen aktual +
+
+
+
+
+
+
+ +
+
+
+
+
Produktivitas Aktual
+ Rata-rata kg/ha per komoditas +
+
+
+
+
+
+
+ +
+
+
+
+
Luas Panen per Komoditas
+ Akumulasi luas panen terdata +
+
+
+
+
+
+
+ +
+
+
+
+
Status Panen
+ Jumlah catatan produksi per status +
+
+
+
+
+
+
+ +
+
+
+
+
Produktivitas Survey (ha/tahun)
+ Rata-rata produktivitas per komoditas +
+
+
+
+
+
+
+ +
+
+
+
+
Produktivitas Survey (pohon/tahun)
+ Rata-rata produktivitas per komoditas +
+
+
+
+
+
+
+
+
+ @foreach ([ - 'indicator-tab-produksi' => 'Produksi dan Produktivitas', 'indicator-tab-input-produksi' => 'Input Produksi', 'indicator-tab-panen' => 'Panen dan Pascapanen', 'indicator-tab-akses-pasar' => 'Akses Pasar', ] as $tabId => $tabLabel) +
@@ -1154,6 +1248,84 @@ labelWidth: 180, valueDigits: 0, }); + + let productionChartsRendered = false; + + function renderProductionCharts() { + if (productionChartsRendered) { + return; + } + + productionChartsRendered = true; + + renderBar('#chart-produksi-komoditas', chartData.produksiPerKomoditas, { + name: 'Produksi', + suffix: 'kg', + colors: colorsFor(0), + height: 330, + horizontal: true, + labelWidth: 150, + valueDigits: 0, + }); + + renderBar('#chart-produktivitas-komoditas', chartData.produktivitasPerKomoditas, { + name: 'Produktivitas', + suffix: 'kg/ha', + colors: colorsFor(2), + height: 330, + horizontal: true, + labelWidth: 150, + valueDigits: 2, + }); + + renderBar('#chart-luas-panen-komoditas', chartData.luasPanenPerKomoditas, { + name: 'Luas panen', + suffix: 'ha', + colors: colorsFor(4), + height: 330, + horizontal: true, + labelWidth: 150, + valueDigits: 2, + }); + + renderDonut( + '#chart-status-panen', + chartData.statusPanen, + colorsFor(6), + { + totalLabel: 'Catatan', + valueDigits: 0, + } + ); + + renderBar('#chart-survey-produktivitas-ha', chartData.surveyProduktivitasHa, { + name: 'Produktivitas', + suffix: 'ha/tahun', + colors: colorsFor(1), + height: 330, + horizontal: true, + labelWidth: 150, + valueDigits: 2, + }); + + renderBar('#chart-survey-produktivitas-pohon', chartData.surveyProduktivitasPohon, { + name: 'Produktivitas', + suffix: 'pohon/tahun', + colors: colorsFor(3), + height: 330, + horizontal: true, + labelWidth: 150, + valueDigits: 2, + }); + } + + document + .querySelector('[data-bs-target="#indicator-tab-produksi"]') + ?.addEventListener('shown.bs.tab', renderProductionCharts); + + if (document.querySelector('#indicator-tab-produksi')?.classList.contains('active')) { + renderProductionCharts(); + } }); @endpush