diff --git a/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php b/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php index 4fbe6e3..a7ec362 100644 --- a/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php @@ -6,6 +6,9 @@ use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Auth; +use Illuminate\Http\RedirectResponse; +use Illuminate\Http\JsonResponse; use App\Models\Pertanian\Petani; use App\Models\Pertanian\Komoditas; @@ -13,41 +16,181 @@ use App\Models\Pertanian\Lahan; use App\Models\Pertanian\Tanaman; use App\Models\Pertanian\SkorPetani; +use App\Models\Wilayah\Provinsi; +use App\Models\Wilayah\KabupatenKota; +use App\Models\Wilayah\Kecamatan; +use App\Models\Wilayah\DesaKelurahan; + class IndeksPetaniController extends Controller { - public function index() + + private function filters(Request $request): array + { + return [ + 'desaKelurahan_id' => $request->desaKelurahan_id, + 'kecamatan_id' => $request->kecamatan_id, + 'kabupatenKota_id' => $request->kabupatenKota_id, + 'provinsi_id' => $request->provinsi_id, + 'komoditas_id' => $request->komoditas_id, + 'segmen' => $request->segmen, + ]; + } + + private function petaniQuery(array $filters): \Illuminate\Database\Eloquent\Builder + { + $petaniQuery = Petani::query() + ->join('master_desa_kelurahan', 'petani.desa_kelurahan_id', '=', 'master_desa_kelurahan.id') + ->join('master_kecamatan', 'master_desa_kelurahan.kecamatan_id', '=', 'master_kecamatan.id') + ->join('master_kabupaten_kota', 'master_kecamatan.kabupaten_kota_id', '=', 'master_kabupaten_kota.id') + ->join('master_provinsi', 'master_kabupaten_kota.provinsi_id', '=', 'master_provinsi.id') + ->whereNull('petani.deleted_at') + ->when($filters['provinsi_id'], fn($q, $id) => $q->where('master_kabupaten_kota.provinsi_id', $id)) + ->when($filters['kabupatenKota_id'], fn($q, $id) => $q->where('master_kecamatan.kabupaten_kota_id', $id)) + ->when($filters['kecamatan_id'], fn($q, $id) => $q->where('master_desa_kelurahan.kecamatan_id', $id)) + ->when($filters['desaKelurahan_id'], fn($q, $id) => $q->where('petani.desa_kelurahan_id', $id)) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('petani.komoditas_id', $id)); + + return $petaniQuery; + } + + private function skorPetaniQuery(array $filters, array $komoditas): \Illuminate\Database\Eloquent\Builder + { + $skor = SkorPetani::query() + ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') + ->join('master_desa_kelurahan', 'petani.desa_kelurahan_id', '=', 'master_desa_kelurahan.id') + ->join('master_kecamatan', 'master_desa_kelurahan.kecamatan_id', '=', 'master_kecamatan.id') + ->join('master_kabupaten_kota', 'master_kecamatan.kabupaten_kota_id', '=', 'master_kabupaten_kota.id') + ->join('master_provinsi', 'master_kabupaten_kota.provinsi_id', '=', 'master_provinsi.id') + ->whereNull('petani.deleted_at') + ->when($filters['provinsi_id'], fn($q, $id) => $q->where('master_kabupaten_kota.provinsi_id', $id)) + ->when($filters['kabupatenKota_id'], fn($q, $id) => $q->where('master_kecamatan.kabupaten_kota_id', $id)) + ->when($filters['kecamatan_id'], fn($q, $id) => $q->where('master_desa_kelurahan.kecamatan_id', $id)) + ->when($filters['desaKelurahan_id'], fn($q, $id) => $q->where('petani.desa_kelurahan_id', $id)) + ->whereIn('petani.komoditas_id', $komoditas); + + if ($filters['segmen']) { + $skor->where(function ($q) use ($filters) { + match ($filters['segmen']) { + 'Penggerak' => $q->where('skor_kesiapan_adopsi', '>=', 4), + 'Perintis' => $q->where(function($q) { + $q->where('skor_kesiapan_adopsi', '>=', 3) + ->where('skor_kesiapan_adopsi', '<', 4); + }), + 'Pemerhati' => $q->where(function($q) { + $q->where('skor_kesiapan_adopsi', '>=', 2) + ->where('skor_kesiapan_adopsi', '<', 3); + }), + 'Pemula' => $q->where(function($q) { + $q->where('skor_kesiapan_adopsi', '>=', 1) + ->where('skor_kesiapan_adopsi', '<', 2); + }), + 'Belum Lengkap' => $q->where(function ($q) { + $q->whereNull('skor_kesiapan_adopsi') + ->orWhere('skor_kesiapan_adopsi', '<', 1); + }), + + default => null, + }; + }); + } + + return $skor; + } + + public function index(Request $request) { if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { abort(403); } + $filters = $this->filters($request); + $title = 'Dashboard Profil Petani'; $komoditas = Komoditas::where('is_utama', true)->get(); + $petaniQuery = $this->petaniQuery($filters); - $petani = Petani::pluck('id'); - $lahan = Lahan::has('petani')->get(); + $desaKelurahan = $petaniQuery->clone() + ->selectRaw(" + master_desa_kelurahan.id as desa_kelurahan_id, + master_desa_kelurahan.nama as desa_kelurahan, + master_desa_kelurahan.path as path, + master_kecamatan.id as kecamatan_id, + master_kecamatan.nama as kecamatan, + master_kabupaten_kota.id as kabupaten_id, + master_kabupaten_kota.nama as kabupaten, + master_provinsi.id as provinsi_id, + master_provinsi.nama as provinsi + ") + ->distinct() + ->get(); - $case = " - CASE - WHEN skor_kesiapan_adopsi >= 4.0 THEN 'Penggerak' - WHEN skor_kesiapan_adopsi >= 3.0 THEN 'Perintis' - WHEN skor_kesiapan_adopsi >= 2.0 THEN 'Pemerhati' - WHEN skor_kesiapan_adopsi >= 1.0 THEN 'Pemula' - ELSE 'Belum Lengkap' - END - "; + $wilayah = $desaKelurahan + ->groupBy('provinsi_id') + ->map(function ($provinsi) { + return [ + 'id' => $provinsi->first()->provinsi_id, + 'nama' => $provinsi->first()->provinsi, + 'kabupaten' => $provinsi + ->groupBy('kabupaten_id') + ->map(function ($kabupaten) { + return [ + 'id' => $kabupaten->first()->kabupaten_id, + 'nama' => $kabupaten->first()->kabupaten, + 'kecamatan' => $kabupaten + ->groupBy('kecamatan_id') + ->map(function ($kecamatan) { + return [ + 'id' => $kecamatan->first()->kecamatan_id, + 'nama' => $kecamatan->first()->kecamatan, + 'desa' => $kecamatan->map(function ($desa) { + return [ + 'id' => $desa->desa_kelurahan_id, + 'nama' => $desa->desa_kelurahan, + 'path' => $desa->path, + ]; + })->values(), + ]; + })->values(), + ]; + })->values(), + ]; + })->values(); - $countPetani = Petani::count(); - $countKomoditas = Petani::whereIn('komoditas_id', $komoditas->pluck('id'))->distinct()->count('komoditas_id'); - $sumLahan = Lahan::has('petani')->whereIn('komoditas_id', $komoditas->pluck('id'))->sum('luas_lahan'); - $avgLahan = Lahan::has('petani')->whereIn('komoditas_id', $komoditas->pluck('id'))->avg('luas_lahan'); + return view('dashboard.indeks-petani', array_merge($filters, + compact( + 'komoditas', + 'desaKelurahan', + 'wilayah', + ))); + } - $avgSkor = SkorPetani::query() - ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereNull('petani.deleted_at') - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) - ->avg('skor_kesiapan_adopsi'); + public function summary(Request $request): JsonResponse + { + $filters = $this->filters($request); + $petaniQuery = $this->petaniQuery($filters); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $countKomoditas = $petaniQuery->clone() + ->whereHas('komoditas', fn ($query) => $query->where('is_utama', true)) + ->distinct()->count('komoditas_id'); + + $filteredPetaniIds = $petaniQuery + ->clone() + ->select('petani.id') + ->distinct() + ->pluck('petani.id'); + + $sumLahan = Lahan::has('petani')->whereIn('petani_id', $filteredPetaniIds)->whereIn('komoditas_id', $komoditas->pluck('id'))->sum('luas_lahan'); + $avgLahan = Lahan::has('petani')->whereIn('petani_id', $filteredPetaniIds)->whereIn('komoditas_id', $komoditas->pluck('id'))->avg('luas_lahan'); + + $countDesa = $petaniQuery->clone()->whereIn('komoditas_id', $komoditas->pluck('id'))->distinct()->count('desa_kelurahan_id'); + $countKecamatan = $petaniQuery->clone()->whereIn('komoditas_id', $komoditas->pluck('id'))->distinct()->count('master_kecamatan.id'); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + $avgSkor = $skorQuery->clone()->avg('skor_kesiapan_adopsi'); if ($avgSkor >= 4.0) { $avgSegmen = 'Penggerak'; @@ -61,19 +204,120 @@ class IndeksPetaniController extends Controller $avgSegmen = 'Belum Lengkap'; } - $countDesa = Petani::whereIn('komoditas_id', $komoditas->pluck('id'))->distinct()->count('desa_kelurahan_id'); - $countKecamatan = Petani::query() - ->join('master_desa_kelurahan', 'petani.desa_kelurahan_id', '=', 'master_desa_kelurahan.id') - ->join('master_kecamatan', 'master_desa_kelurahan.kecamatan_id', '=', 'master_kecamatan.id') - ->whereIn('komoditas_id', $komoditas->pluck('id'))->distinct()->count('master_kecamatan.id'); + return response()->json([ + 'petani' => $petaniQuery->clone()->count(), + 'komoditas' => $countKomoditas, + 'sum_lahan' => $sumLahan, + 'avg_lahan' => $avgLahan, + 'desa' => $countDesa, + 'kecamatan' => $countKecamatan, + 'skor' => $avgSkor, + 'segmen' => $avgSegmen + ]); + } - $countSegmentasi = SkorPetani::selectRaw("$case AS segmen, COUNT(*) AS total") + private function segments(): array + { + $segments = [ + [ + 'name' => 'Penggerak', + 'range' => '4.0 - 5.0', + 'icon' => 'tabler-crown', + 'color' => 'success', + ], + [ + 'name' => 'Perintis', + 'range' => '3.0 - 3.9', + 'icon' => 'tabler-flag', + 'color' => 'info', + ], + [ + 'name' => 'Pemerhati', + 'range' => '2.0 - 2.9', + 'icon' => 'tabler-eye', + 'color' => 'warning', + ], + [ + 'name' => 'Pemula', + 'range' => '1.0 - 1.9', + 'icon' => 'tabler-seedling', + 'color' => 'danger', + ], + ]; + + return $segments; + } + + private function cases(): string + { + $case = " + CASE + WHEN skor_kesiapan_adopsi >= 4.0 THEN 'Penggerak' + WHEN skor_kesiapan_adopsi >= 3.0 THEN 'Perintis' + WHEN skor_kesiapan_adopsi >= 2.0 THEN 'Pemerhati' + WHEN skor_kesiapan_adopsi >= 1.0 THEN 'Pemula' + ELSE 'Belum Lengkap' + END + "; + + return $case; + } + public function segmen(Request $request): JsonResponse + { + $filters = $this->filters($request); + $segments = $this->segments(); + $case = $this->cases(); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + + $countSegmentasi = $skorQuery->clone() + ->selectRaw("$case AS segmen, COUNT(*) AS total") ->groupByRaw($case) ->get(); - $countSegmentasiByKomoditas = SkorPetani::query() - ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereNull('petani.deleted_at') + $series = collect($segments) + ->map(function ($segment) use ($countSegmentasi) { + return $countSegmentasi + ->where('segmen', $segment['name']) + ->sum('total'); + }) + ->values(); + + $countPetani = $series->sum(); + + $persentase = collect($segments) + ->map(function ($segment) use ($countSegmentasi, $countPetani) { + $total = $countSegmentasi + ->where('segmen', $segment['name']) + ->sum('total'); + + return $countPetani > 0 + ? ($total / $countPetani) * 100 + : 0; + }) + ->values(); + + return response()->json([ + 'series' => $series, + 'persentase' => $persentase, + ]); + } + + public function segmenByKomoditas(Request $request): JsonResponse + { + $filters = $this->filters($request); + $segments = $this->segments(); + $case = $this->cases(); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + + $countSegmentasiByKomoditas = $skorQuery->clone() ->selectRaw(" petani.komoditas_id, $case AS segmen, @@ -83,20 +327,64 @@ class IndeksPetaniController extends Controller ->groupByRaw($case) ->get(); - $avgDimensi = SkorPetani::query() - ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereNull('petani.deleted_at') - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + $seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($countSegmentasiByKomoditas, $komoditas) { + return [ + 'name' => $segment['name'], + 'data' => $komoditas->map(function ($item) use ($countSegmentasiByKomoditas, $segment) { + + return optional( + $countSegmentasiByKomoditas->first(function ($row) use ($item, $segment) { + return $row->komoditas_id == $item->id + && $row->segmen == $segment['name']; + }) + )->total ?? 0; + + })->values(), + ]; + })->values(); + + return response()->json([ + 'categories' => $komoditas->pluck('nama')->values(), + 'series' => $seriesSegmentasiKomoditas, + ]); + + } + + public function dimensi(Request $request): JsonResponse + { + $filters = $this->filters($request); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + + $avgDimensi = $skorQuery->clone() ->selectRaw(" avg(skor_d2_sistem_praktik_budidaya) as skor_d2_sistem_praktik_budidaya, avg(skor_d4_sosial_ekonomi) as skor_d4_sosial_ekonomi, avg(skor_d6_rantai_nilai_akses_pasar) as skor_d6_rantai_nilai_akses_pasar") ->first(); - $avgKomponen = SkorPetani::query() - ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereNull('petani.deleted_at') - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + return response()->json([ + 'radarDimensi' => [ + round($avgDimensi->skor_d2_sistem_praktik_budidaya, 2), + round($avgDimensi->skor_d4_sosial_ekonomi, 2), + round($avgDimensi->skor_d6_rantai_nilai_akses_pasar, 2), + ] + ]); + } + + public function komponen(Request $request): JsonResponse + { + $filters = $this->filters($request); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + + $avgKomponen = $skorQuery->clone() ->selectRaw("avg(skor_komp_1_d4_k3_motivasi_kapasitas_adopsi) as skor_komp_1_d4_k3_motivasi_kapasitas_adopsi, avg(skor_komp_2_d4_k2_ekonomi_rumah_tangga) as skor_komp_2_d4_k2_ekonomi_rumah_tangga, avg(skor_komp_3_d2_praktik_budidaya_gap) as skor_komp_3_d2_praktik_budidaya_gap, @@ -105,11 +393,34 @@ class IndeksPetaniController extends Controller avg(skor_komp_6_d6_k1_k4_k5_rantai_nilai_akses_pasar) as skor_komp_6_d6_k1_k4_k5_rantai_nilai_akses_pasar") ->first(); - $desaKelurahan = Petani::query() - ->join('master_desa_kelurahan', 'petani.desa_kelurahan_id', '=', 'master_desa_kelurahan.id') - ->join('master_kecamatan', 'master_desa_kelurahan.kecamatan_id', '=', 'master_kecamatan.id') - ->join('master_kabupaten_kota', 'master_kecamatan.kabupaten_kota_id', '=', 'master_kabupaten_kota.id') - ->join('master_provinsi', 'master_kabupaten_kota.provinsi_id', '=', 'master_provinsi.id') + return response()->json([ + 'radarKomponen' => [ + round($avgKomponen->skor_komp_1_d4_k3_motivasi_kapasitas_adopsi, 2), + round($avgKomponen->skor_komp_2_d4_k2_ekonomi_rumah_tangga, 2), + round($avgKomponen->skor_komp_3_d2_praktik_budidaya_gap, 2), + round($avgKomponen->skor_komp_4_d4_k4_keterlibatan_kelembagaan, 2), + round($avgKomponen->skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan, 2), + round($avgKomponen->skor_komp_6_d6_k1_k4_k5_rantai_nilai_akses_pasar, 2) + ] + ]); + } + + public function map(Request $request): JsonResponse + { + $filters = $this->filters($request); + $segments = $this->segments(); + + $colors = collect($segments) + ->pluck('color') + ->map(fn($c) => "var(--bs-{$c})") + ->values(); + $segmentStyles = collect($segments)->keyBy('name'); + + $case = $this->cases(); + + $petaniQuery = $this->petaniQuery($filters); + + $desaKelurahan = $petaniQuery->clone() ->selectRaw(" master_desa_kelurahan.id as desa_kelurahan_id, master_desa_kelurahan.nama as desa_kelurahan, @@ -121,13 +432,15 @@ class IndeksPetaniController extends Controller master_provinsi.id as provinsi_id, master_provinsi.nama as provinsi ") - ->whereIn('petani.id', $petani) ->distinct() ->get(); - $mapSegmentasi = SkorPetani::query() - ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereNull('petani.deleted_at') + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + + $mapSegmentasi = $skorQuery->clone() ->selectRaw("petani.desa_kelurahan_id, $case AS segmen, COUNT(petani.id) AS total @@ -136,9 +449,7 @@ class IndeksPetaniController extends Controller ->groupByRaw($case) ->get(); - $mapAvgSkorSegmentasi = SkorPetani::query() - ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereNull('petani.deleted_at') + $mapAvgSkorSegmentasi = $skorQuery->clone() ->selectRaw("petani.desa_kelurahan_id, COUNT(petani.id) AS jumlah_petani, avg(skor_kesiapan_adopsi) AS skor, @@ -153,28 +464,195 @@ class IndeksPetaniController extends Controller ->groupBy('petani.desa_kelurahan_id') ->get(); - $daftarPetani = Petani::query() + $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(); + + return response()->json($mapDesaSegmentasi); + } + + public function desa(Request $request): JsonResponse + { + $filters = $this->filters($request); + $segments = $this->segments(); + + $colors = collect($segments) + ->pluck('color') + ->map(fn($c) => "var(--bs-{$c})") + ->values(); + $segmentStyles = collect($segments)->keyBy('name'); + + $case = $this->cases(); + + $petaniQuery = $this->petaniQuery($filters); + + $desaKelurahan = $petaniQuery->clone() + ->selectRaw(" + master_desa_kelurahan.id as desa_kelurahan_id, + master_desa_kelurahan.nama as desa_kelurahan, + master_desa_kelurahan.path as path, + master_kecamatan.id as kecamatan_id, + master_kecamatan.nama as kecamatan, + master_kabupaten_kota.id as kabupaten_id, + master_kabupaten_kota.nama as kabupaten, + master_provinsi.id as provinsi_id, + master_provinsi.nama as provinsi + ") + ->distinct() + ->get(); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $skorQuery = $this->skorPetaniQuery($filters, $komoditas->pluck('id')->toArray()); + + $mapSegmentasi = $skorQuery->clone() + ->selectRaw("petani.desa_kelurahan_id, + $case AS segmen, + COUNT(petani.id) AS total + ") + ->groupBy('petani.desa_kelurahan_id') + ->groupByRaw($case) + ->get(); + + $mapAvgSkorSegmentasi = $skorQuery->clone() + ->selectRaw("petani.desa_kelurahan_id, + COUNT(petani.id) AS jumlah_petani, + avg(skor_kesiapan_adopsi) AS skor, + CASE + WHEN AVG(skor_kesiapan_adopsi) >= 4 THEN 'Penggerak' + WHEN AVG(skor_kesiapan_adopsi) >= 3 THEN 'Perintis' + WHEN AVG(skor_kesiapan_adopsi) >= 2 THEN 'Pemerhati' + WHEN AVG(skor_kesiapan_adopsi) >= 1 THEN 'Pemula' + ELSE 'Belum Lengkap' + END AS segmen + ") + ->groupBy('petani.desa_kelurahan_id') + ->get(); + + $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(); + + $rows = $mapDesaSegmentasi->map(function ($desa) use ($segmentStyles) { + + $style = $segmentStyles[$desa->segmentasi->segmen] ?? ['color' => 'secondary']; + $styleDominan = $segmentStyles[$desa->segmentasi->segmen_dominan] ?? ['color' => 'secondary']; + + return [ + 'desa' => $desa->desa_kelurahan, + 'jumlah_petani' => $desa->segmentasi->jumlah_petani, + 'segmen' => $desa->segmentasi->segmen, + 'skor' => $desa->segmentasi->skor, + 'segmen_dominan' => $desa->segmentasi->segmen_dominan, + 'jumlah_dominan' => $desa->segmentasi->jumlah_dominan, + 'color' => $style['color'], + 'color_dominan' => $styleDominan['color'], + ]; + }); + + return response()->json($rows); + } + + public function data(Request $request): JsonResponse + { + $filters = $this->filters($request); + $segments = $this->segments(); + + $colors = collect($segments) + ->pluck('color') + ->map(fn($c) => "var(--bs-{$c})") + ->values(); + $segmentStyles = collect($segments)->keyBy('name'); + + $petaniQuery = $this->petaniQuery($filters); + + $komoditas = Komoditas::where('is_utama', true) + ->when($filters['komoditas_id'], fn($q, $id) => $q->where('id', $id))->get(); + + $daftarPetani = $petaniQuery->clone() + ->select('petani.*') ->whereIn('komoditas_id', $komoditas->pluck('id')) ->get(); - return view('dashboard.indeks-petani', compact( - 'komoditas', - 'countPetani', - 'countKomoditas', - 'sumLahan', - 'avgLahan', - 'avgSkor', - 'avgSegmen', - 'countDesa', - 'countKecamatan', - 'countSegmentasi', - 'countSegmentasiByKomoditas', - 'avgDimensi', - 'avgKomponen', - 'desaKelurahan', - 'mapSegmentasi', - 'mapAvgSkorSegmentasi', - 'daftarPetani', - )); + $data = $daftarPetani + ->filter(function ($item) use ($filters) { + if (!$filters['segmen']) { + return true; + } + $segmen = $item->skor ? $item->segmen() : 'Belum Lengkap'; + return $segmen === $filters['segmen']; + }) + ->map(function ($item) use ($segmentStyles) { + $segmen = $item->skor + ? $item->segmen() + : null; + $style = $segmentStyles[$segmen] + ?? ['color' => 'secondary']; + + return [ + 'id' => $item->id, + 'nama' => $item->nama, + 'desa' => $item->desaKelurahan?->nama, + 'desa_kelurahan_id' => $item->desa_kelurahan_id, + 'komoditas' => $item->komoditas?->nama, + 'luas_lahan' => $item->lahans?->sum('luas_lahan') ?? 0, + 'skor' => $item->skor + ? $item->skor->skor_kesiapan_adopsi + : null, + 'segmen' => $segmen, + 'color' => $style['color'], + 'url' => route('dashboard.profil-petani', $item->id), + ]; + }) + ->values(); + + return response()->json($data); } } \ No newline at end of file diff --git a/app/Http/Controllers/Web/Produktivitas/ProfilPetaniController.php b/app/Http/Controllers/Web/Produktivitas/ProfilPetaniController.php index dfc4087..791fba0 100644 --- a/app/Http/Controllers/Web/Produktivitas/ProfilPetaniController.php +++ b/app/Http/Controllers/Web/Produktivitas/ProfilPetaniController.php @@ -13,6 +13,11 @@ use App\Models\Pertanian\Lahan; use App\Models\Pertanian\Tanaman; use App\Models\Pertanian\PraktikBudidaya; use App\Models\Pertanian\SurveyPanen; +use App\Models\Pertanian\SosialEkonomi; +use App\Models\Pertanian\SurveyPelatihan; +use App\Models\Pertanian\SurveySertifikasi; +use App\Models\Pertanian\AksesPasar; +use App\Models\Pertanian\HargaJualPanen; use App\Models\Pertanian\PendapatanKomoditas; use App\Models\Wilayah\DesaKelurahan; use App\Models\Profile; @@ -23,6 +28,15 @@ use App\Enums\PraktikBudidaya\MetodePenangananHamaPenyakit; use App\Enums\PraktikBudidaya\FrekuensiSanitasiLahan; use App\Enums\PraktikBudidaya\PenangananGulma; use App\Enums\PraktikBudidaya\KondisiPengelolaanAir; +use App\Enums\SosialEkonomi\SkorKecukupanPenghasilan; +use App\Enums\SosialEkonomi\SkorKemampuanMenabung; +use App\Enums\SosialEkonomi\TerdaftarKelompokTani; +use App\Enums\SosialEkonomi\PeranDalamKelompok; +use App\Enums\SosialEkonomi\StatusRekeningTabungan; +use App\Enums\SosialEkonomi\PengalamanKreditKebun; +use App\Enums\SosialEkonomi\KeterikatanHutangPanen; +use App\Enums\SosialEkonomi\PraktikIjon; +use App\Enums\SosialEkonomi\KebebasanMemilihPembeli; class ProfilPetaniController extends Controller { @@ -62,6 +76,7 @@ class ProfilPetaniController extends Controller $praktikBudidaya = PraktikBudidaya::where('petani_id', $petani->id)->first(); $surveyPanen = SurveyPanen::where('petani_id', $petani->id)->first(); + $sosialEkonomi = SosialEkonomi::where('petani_id', $id)->first(); $indikatorOnFarm = collect(); @@ -145,6 +160,280 @@ class ProfilPetaniController extends Controller 'konservasi_tanah' => $praktikBudidaya?->kebiasaan_konservasi_tanah ?? [], ]; + $d4SosialEkonomi = null; + + $terdaftarKelompok = $sosialEkonomi->terdaftar_kelompok_tani; + $peranKelompok = $sosialEkonomi->peran_dalam_kelompok; + + if ($sosialEkonomi) { + + $kecukupanPenghasilan = $sosialEkonomi->skor_kecukupan_penghasilan; + $kemampuanMenabung = $sosialEkonomi->skor_kemampuan_menabung; + + $rekening = $sosialEkonomi->status_rekening_tabungan; + $kredit = $sosialEkonomi->pengalaman_kredit_kebun; + $hutangPanen = $sosialEkonomi->keterikatan_hutang_panen; + $ijon = $sosialEkonomi->praktik_ijon; + + $programKeuanganRaw = $sosialEkonomi->status_program_keuangan_formal ?? []; + $namaProgram = [ + 'pkh' => 'PKH', + 'blt' => 'BLT', + 'kur' => 'KUR', + 'kredit_koperasi_resmi' => 'Kredit Koperasi', + 'credit_union_cu' => 'Credit Union (CU)', + 'pinjaman_bumdes' => 'Pinjaman BUMDes', + 'modal_hibah_dinas_pertanian' => 'Hibah Dinas Pertanian', + ]; + + $programBantuan = collect($programKeuanganRaw)->map(function ($status, $key) use ($namaProgram) { + $statusMeta = match ($status) { + 'sedang_menerima' => [ + 'label' => 'Sedang Menerima', + 'short' => 'Aktif', + 'color' => 'success', + 'icon' => 'tabler-circle-check', + ], + 'pernah_tapi_tidak_lagi' => [ + 'label' => 'Pernah, Tidak Lagi', + 'short' => 'Pernah', + 'color' => 'info', + 'icon' => 'tabler-history', + ], + 'belum_pernah' => [ + 'label' => 'Belum Pernah', + 'short' => 'Belum Pernah', + 'color' => 'secondary', + 'icon' => 'tabler-minus', + ], + default => [ + 'label' => Str::headline($status), + 'short' => Str::headline($status), + 'color' => 'secondary', + 'icon' => 'tabler-help-circle', + ], + }; + + return [ + 'key' => $key, + 'nama' => $namaProgram[$key] ?? Str::headline($key), + 'status' => $status, + 'label' => $statusMeta['label'], + 'short' => $statusMeta['short'], + 'color' => $statusMeta['color'], + 'icon' => $statusMeta['icon'], + ]; + + }) + ->values(); + + $d4SosialEkonomi = [ + + 'jumlah_tanggungan' => $sosialEkonomi->jumlah_tanggungan, + + 'kecukupan_penghasilan' => [ + 'skor' => $kecukupanPenghasilan?->value, + 'label' => $kecukupanPenghasilan?->label(), + + 'color' => $this->getScoreColor( + $kecukupanPenghasilan?->value + ), + ], + + 'kemampuan_menabung' => [ + 'skor' => $kemampuanMenabung?->value, + 'label' => $kemampuanMenabung?->label(), + + 'color' => $this->getScoreColor( + $kemampuanMenabung?->value + ), + ], + + 'status_kepemilikan_lahan' => $sosialEkonomi->status_kepemilikan_lahan, + + 'kelembagaan' => [ + 'terdaftar' => + $terdaftarKelompok === TerdaftarKelompokTani::YA, + + 'status' => + $terdaftarKelompok?->label(), + + 'peran' => + $peranKelompok?->label(), + ], + + 'kondisi_keuangan' => [ + 'rekening' => [ + 'label' => $rekening?->label(), + 'value' => $rekening?->value, + 'color' => $this->getFinancialColor( + $rekening?->value + ), + 'icon' => 'tabler-building-bank', + ], + + 'kredit' => [ + 'label' => $kredit?->label(), + 'value' => $kredit?->value, + 'color' => $this->getFinancialColor( + $kredit?->value + ), + 'icon' => 'tabler-credit-card', + ], + + 'hutang_panen' => [ + 'label' => $hutangPanen?->label(), + 'value' => $hutangPanen?->value, + 'color' => $this->getFinancialColor( + $hutangPanen?->value + ), + 'icon' => 'tabler-coins', + ], + + 'ijon' => [ + 'label' => $ijon?->label(), + 'value' => $ijon?->value, + 'color' => $this->getFinancialColor( + $ijon?->value + ), + 'icon' => 'tabler-link', + ], + ], + + 'program_bantuan' => $programBantuan, + ]; + } + + $surveyPelatihan = SurveyPelatihan::where('petani_id', $id) + ->orderByDesc('tahun_pelaksanaan') + ->get(); + + $surveySertifikasi = SurveySertifikasi::where('petani_id', $id) + ->orderByDesc('tahun_pelaksanaan') + ->get(); + + $aksesPasar = AksesPasar::where('petani_id', $id)->first(); + $saluranTerdahulu = collect($aksesPasar?->saluran_terdahulu ?? [] ); + + $d6SaluranPasar = [ + [ + 'key' => 'tengkulak', + 'label' => 'Tengkulak', + 'icon' => 'tabler-user-dollar', + 'aktif' => $saluranTerdahulu->contains( + fn ($item) => Str::contains( + Str::lower($item), + ['tengkulak', 'pedagang lokal'] + ) + ), + ], + + [ + 'key' => 'koperasi', + 'label' => 'Koperasi', + 'icon' => 'tabler-users-group', + 'aktif' => $saluranTerdahulu->contains( + fn ($item) => Str::contains( + Str::lower($item), + 'koperasi' + ) + ), + ], + + [ + 'key' => 'bumdes', + 'label' => 'BUMDes', + 'icon' => 'tabler-building-community', + 'aktif' => $saluranTerdahulu->contains( + fn ($item) => Str::contains( + Str::lower($item), + 'bumdes' + ) + ), + ], + + [ + 'key' => 'eksportir', + 'label' => 'Eksportir', + 'icon' => 'tabler-plane-departure', + 'aktif' => $saluranTerdahulu->contains( + fn ($item) => Str::contains( + Str::lower($item), + 'eksportir' + ) + ), + ], + ]; + + $hargaJualPanen = HargaJualPanen::where('petani_id', $id)->get(); + + $d6HargaJual = $hargaJualPanen->map(function ($item) { + + $hargaSekarang = $item->harga_panen_terakhir !== null + ? (float) $item->harga_panen_terakhir + : null; + + $hargaTahunLalu = $item->harga_tahun_lalu !== null + ? (float) $item->harga_tahun_lalu + : null; + + $perubahan = null; + + if ( + $hargaSekarang !== null && + $hargaTahunLalu !== null && + $hargaTahunLalu > 0 + ) { + $perubahan = ( + ($hargaSekarang - $hargaTahunLalu) + / $hargaTahunLalu + ) * 100; + } + + return [ + 'bentuk_produk' => $item->bentuk_produk, + + 'harga_sekarang' => $hargaSekarang, + + 'harga_tahun_lalu' => $hargaTahunLalu, + + 'harga_dua_tahun_lalu' => + $item->harga_dua_tahun_lalu !== null + ? (float) $item->harga_dua_tahun_lalu + : null, + + 'perubahan' => $perubahan, + + 'trend' => match (true) { + $perubahan === null => 'neutral', + $perubahan > 0 => 'up', + $perubahan < 0 => 'down', + default => 'stable', + }, + ]; + }); + + $kebebasanPembeli = $sosialEkonomi?->kebebasan_memilih_pembeli; + + $d6RantaiNilai = [ + 'saluran_pasar' => $d6SaluranPasar, + + 'harga_jual' => $d6HargaJual, + + 'kebebasan_memilih_pembeli' => [ + 'skor' => $kebebasanPembeli?->value, + 'label' => $kebebasanPembeli?->label(), + + 'persentase' => $kebebasanPembeli + ? ($kebebasanPembeli->value / 5) * 100 + : 0, + + 'color' => $this->getScoreColor( + $kebebasanPembeli?->value + ), + ], + ]; + $data = [ 'petani' => $petani, 'skorPetani' => $skorPetani, @@ -161,6 +450,16 @@ class ProfilPetaniController extends Controller 'praktikBudidaya' => $praktikBudidaya, 'indikatorOnFarm' => $indikatorOnFarm, 'detailOnFarm' => $detailOnFarm, + 'sosialEkonomi' => $sosialEkonomi, + 'd4SosialEkonomi' => $d4SosialEkonomi, + 'surveyPelatihan' => $surveyPelatihan, + 'surveySertifikasi' => $surveySertifikasi, + 'aksesPasar' => $aksesPasar, + 'd6SaluranPasar' => $d6SaluranPasar, + 'hargaJualPanen' => $hargaJualPanen, + 'd6HargaJual' => $d6HargaJual, + 'kebebasanPembeli' => $kebebasanPembeli, + 'd6RantaiNilai' => $d6RantaiNilai ]; return view('produktivitas.profil-petani.index', $data); } @@ -180,6 +479,20 @@ class ProfilPetaniController extends Controller }; } + private function getFinancialColor(?int $score): string + { + if ($score === null || $score === 0) { + return 'secondary'; + } + + return match (true) { + $score >= 5 => 'success', + $score >= 4 => 'info', + $score >= 2 => 'warning', + default => 'danger', + }; + } + private function buildProfiling(SkorPetani $skorPetani): array { $skorAkhir = $this->normalizeScore($skorPetani->skor_kesiapan_adopsi); diff --git a/resources/views/dashboard/indeks-petani.blade.php b/resources/views/dashboard/indeks-petani.blade.php index 37d9286..3eba5a0 100644 --- a/resources/views/dashboard/indeks-petani.blade.php +++ b/resources/views/dashboard/indeks-petani.blade.php @@ -6,12 +6,12 @@ crossorigin=""/> @endpush @@ -50,57 +50,112 @@ $colors = collect($segments) ->values(); $segmentStyles = collect($segments)->keyBy('name'); -$countSegmentasi = $countSegmentasi->keyBy('segmen'); -$seriesSegmentasi = collect($segments)->map(function ($segment) use ($countSegmentasi) { - return $countSegmentasi[$segment['name']]->total ?? 0; -}); -$seriesSegmentasiKomoditas = collect($segments)->map(function ($segment) use ($countSegmentasiByKomoditas, $komoditas) { - - return [ - 'name' => $segment['name'], - 'data' => $komoditas->map(function ($item) use ($countSegmentasiByKomoditas, $segment) { - - return optional( - $countSegmentasiByKomoditas->first(function ($row) use ($item, $segment) { - return $row->komoditas_id == $item->id - && $row->segmen == $segment['name']; - }) - )->total ?? 0; - - })->values(), - ]; - -})->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(); +$provinsi = $desaKelurahan + ->unique('provinsi_id') + ->sortBy('provinsi') + ->values(); @endphp
+
+
+ @csrf +
+
+
+ + {{-- FILTER WILAYAH --}} +
+ +
+ + Wilayah +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + {{-- FILTER DATA --}} +
+ +
+ + Data +
+ +
+ +
+ +
+ +
+ + + + +
+ +
+
+
+
+
@@ -111,11 +166,11 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use
-

{{ $countPetani }}

+

0

Total Petani

- {{ $countKomoditas }} + 0 komoditas utama

@@ -130,15 +185,13 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use
-

{{ number_format($sumLahan, 2, ',', '.') }} ha

+

0

+ ha

Total Luas Lahan

- @php - $avgLahan = $sumLahan / $countPetani; - @endphp

rata-rata - {{ number_format($avgLahan, 2, ',', '.') }} + ha/petani

@@ -153,12 +206,12 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use -

{{ number_format($avgSkor, 2, ',', '.') }}

+

Rata-rata Indeks Kesiapan Adopsi

Segmentasi: - {{ $avgSegmen }} +

@@ -172,11 +225,11 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use -

{{ $countDesa }}

+

0

Jumlah Desa Sasaran

- {{ $countKecamatan }} + 0 kecamatan sasaran

@@ -204,30 +257,7 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use % - - - @foreach ($segments as $segment) - @php - $total = $countSegmentasi->where('segmen', $segment['name'])->sum('total'); - $persen = $countPetani ? ($total / $countPetani) * 100 : 0; - @endphp - - - -
-
- -
- - {{ $segment['name'] }} - -
- - {{ number_format($total) }} - {{ number_format($persen, 2) }}% - - @endforeach - + @@ -341,30 +371,7 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use Segmen Dominan - - @foreach ($mapDesaSegmentasi as $desa) - @php - $style = $segmentStyles[$desa->segmentasi->segmen] ?? null; - $styleDominan = $segmentStyles[$desa->segmentasi->segmen_dominan] ?? null; - @endphp - - {{ $desa->desa_kelurahan }} - {{ number_format($desa->segmentasi->jumlah_petani) }} - - - {{ $desa->segmentasi->segmen }} - - ({{ number_format($desa->segmentasi->skor, 2, ',', '.') }}) - - - - {{ $desa->segmentasi->segmen_dominan }} - - ({{ number_format($desa->segmentasi->jumlah_dominan) }} petani) - - - @endforeach - + @@ -379,6 +386,10 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use
Daftar Petani

untuk semua komoditas

+
@@ -392,27 +403,7 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use - - @foreach ($daftarPetani as $item) - @php - $style = $segmentStyles[$item->segmen()] ?? null; - @endphp - - - - - - - - - @endforeach - +
Segmen
{{ $item->nama }}{{ $item->desaKelurahan?->nama }}{{ $item->komoditas?->nama }}{{ number_format($item->lahans?->sum('luas_lahan'), 2, ',', '.') }}{{ $item->skor ? number_format($item->skor?->skor_kesiapan_adopsi, 2, ',', '.') : '' }} - @if ($item->skor) - - {{ $item->segmen() }} - - @endif -
@@ -429,6 +420,137 @@ $mapDesaSegmentasi = $segmentasiByDesa->map(function ($segmentasi, $desaId) use crossorigin=""> + + + + + + + + + @endpush \ No newline at end of file diff --git a/resources/views/dashboard/indikator-pertanian.blade.php b/resources/views/dashboard/indikator-pertanian.blade.php index 29eb233..5984364 100644 --- a/resources/views/dashboard/indikator-pertanian.blade.php +++ b/resources/views/dashboard/indikator-pertanian.blade.php @@ -14,41 +14,37 @@ margin-bottom: .35rem; } + .indicator-filter-row { + padding-bottom: 1.5rem; + padding-top: 1.5rem; + } + .indicator-filter-bar { - align-items: end; + display: block; + } + + .indicator-filter-line { + align-items: center; display: flex; flex-wrap: wrap; - gap: .75rem; - margin-bottom: 1.25rem; + gap: .5rem; } - .indicator-filter-group { - flex: 1 1 150px; - min-width: 150px; - } - - .indicator-filter-actions { + .indicator-filter-section-label { + align-items: center; display: flex; - flex: 999 1 240px; - gap: .75rem; - justify-content: space-between; + font-weight: 500; + margin-right: .5rem; + white-space: nowrap; } - .indicator-filter-primary-actions { - display: flex; - gap: .75rem; - } - - .indicator-filter-label { - color: var(--bs-body-color); - font-size: .75rem; - font-weight: 600; - margin-bottom: .3rem; + .indicator-filter-export-action { + margin-left: auto; } .indicator-filter-bar .form-select, .indicator-filter-bar .btn { - min-height: 38px; + min-height: 31px; } .indicator-filter-bar .form-select { @@ -56,15 +52,10 @@ border-color: var(--bs-border-color); border-radius: var(--bs-border-radius); color: var(--bs-body-color); - font-size: .8125rem; - padding-bottom: .375rem; - padding-top: .375rem; } .indicator-filter-bar .btn { - font-size: .8125rem; - padding-bottom: .375rem; - padding-top: .375rem; + white-space: nowrap; } .indicator-filter-bar .form-select:focus { @@ -90,29 +81,16 @@ color: var(--bs-body-color); display: flex; font-size: .8125rem; - min-height: 38px; - padding: .375rem .75rem; + min-height: 31px; + padding: .25rem .75rem; } .indicator-filter-bar .input-group-text { background: var(--bs-paper-bg); border-color: var(--bs-border-color); color: var(--bs-secondary-color); - padding-left: .625rem; - padding-right: .625rem; - } - - .indicator-export-btn { - border-color: #28a745; - color: #28a745; - white-space: nowrap; - } - - .indicator-export-btn:hover, - .indicator-export-btn:focus { - background: rgba(40, 167, 69, .08); - border-color: #28a745; - color: #28a745; + padding-left: .5rem; + padding-right: .5rem; } .indicator-summary-value { @@ -190,16 +168,18 @@ } @media (max-width: 767.98px) { - .indicator-filter-bar, - .indicator-filter-actions, - .indicator-filter-primary-actions { + .indicator-filter-line { display: grid; grid-template-columns: 1fr; width: 100%; } - .indicator-filter-group { - min-width: 100%; + .indicator-filter-section-label { + margin-right: 0; + } + + .indicator-filter-export-action { + margin-left: 0; } .indicator-filter-bar .btn { @@ -225,96 +205,133 @@

-
- @foreach ($filterOptions as $filter) -
- + @php + $filtersByKey = collect($filterOptions)->keyBy('key'); + @endphp - @if (!empty($filter['icon'])) -
- - @if (!empty($filter['readonly'])) - @php - $selectedOption = collect($filter['options']) - ->firstWhere('value', $initialFilters[$filter['key']]); - @endphp - -
- {{ $selectedOption['label'] ?? 'Ngada' }} +
+
+
+
+
+
+ - @else - + @foreach ($filter['options'] as $option) + + @endforeach + + @endif +
+ @endforeach +
+ +
+ +
+ + + @foreach (['komoditas', 'segmentasi'] as $filterKey) + @php + $filter = $filtersByKey[$filterKey]; + @endphp + +
+ - @endif -
- @else - +
+ @endforeach + +
- @endforeach + + Filter + -
-
- -
+ - +
+ +
+
+
+
+
@@ -685,6 +702,7 @@ const komoditasSelect = document.querySelector('[data-filter-key="komoditas"]'); const segmentasiSelect = document.querySelector('[data-filter-key="segmentasi"]'); const selectedKabupaten = kabupatenFilter?.dataset.filterValue || initialFilters.kabupaten || 'all'; + const applyFilterButton = document.getElementById('indicator-apply-filter'); const resetButton = document.getElementById('indicator-reset-filter'); const exportButton = document.getElementById('indicator-export-data'); const chartInstances = {}; @@ -729,6 +747,10 @@ resetButton.disabled = isLoading; } + if (applyFilterButton) { + applyFilterButton.disabled = isLoading; + } + if (exportButton) { exportButton.disabled = isLoading; } @@ -970,11 +992,13 @@ filters.desa = 'all'; await loadDesaOptions('all'); } - - loadIndicatorData(); }); }); + applyFilterButton?.addEventListener('click', function () { + loadIndicatorData(); + }); + resetButton?.addEventListener('click', async function () { Object.assign(filters, { kecamatan: 'all', diff --git a/resources/views/produktivitas/profil-petani/index.blade.php b/resources/views/produktivitas/profil-petani/index.blade.php index 30a0a75..7d3d1a0 100644 --- a/resources/views/produktivitas/profil-petani/index.blade.php +++ b/resources/views/produktivitas/profil-petani/index.blade.php @@ -3,14 +3,14 @@ @push('styles')