diff --git a/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php b/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php new file mode 100644 index 0000000..93c98b3 --- /dev/null +++ b/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php @@ -0,0 +1,260 @@ +count(); + $petaniPerempuan = Petani::where('jenis_kelamin', 0)->count(); + $totalKomoditas = Petani::whereNotNull('komoditas_id') + ->distinct() + ->count('komoditas_id'); + $totalLuasLahan = Lahan::has('petani') + ->sum('luas_lahan'); + $ratarataLuasLahan = $totalLuasLahan && $totalPetani ? $totalLuasLahan / $totalPetani : 0; + + $umurKurang30 = Petani::whereNotNull('tanggal_lahir')->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) < 30")->count(); + $umur30sampai39 = Petani::whereNotNull('tanggal_lahir')->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 30 AND 39")->count(); + $umur40sampai49 = Petani::whereNotNull('tanggal_lahir')->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 40 AND 49")->count(); + $umur50sampai59 = Petani::whereNotNull('tanggal_lahir')->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 50 AND 59")->count(); + $umur60keatas = Petani::whereNotNull('tanggal_lahir')->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) >= 60")->count(); + + $pendidikanCounts = Petani::whereNotNull('pendidikan_terakhir') + ->select('pendidikan_terakhir', DB::raw('COUNT(*) as total')) + ->groupBy('pendidikan_terakhir') + ->pluck('total', 'pendidikan_terakhir'); + + $pendidikan = [ + 'tidak_sekolah' => (int) ($pendidikanCounts['01_tidak_sekolah'] ?? 0), + 'sd' => (int) ($pendidikanCounts['02_sd'] ?? 0), + 'smp' => (int) ($pendidikanCounts['03_smp'] ?? 0), + 'sma' => (int) ($pendidikanCounts['04_sma'] ?? 0), + 'diploma' => (int) ($pendidikanCounts['05_diploma'] ?? 0), + + 's1_keatas' => + (int) ($pendidikanCounts['06_sarjana'] ?? 0) + + (int) ($pendidikanCounts['07_magister'] ?? 0), + ]; + + $komoditasUtama = Komoditas::query() + ->whereHas('petani') + ->withCount('petani') + ->orderByDesc('petani_count') + ->get(['id', 'nama']); + + $luasLahanPerPetani = Lahan::has('petani') + ->select('petani_id') + ->selectRaw('SUM(luas_lahan) as total_luas') + ->groupBy('petani_id') + ->get(); + + $luasLahan = [ + 'kurang_05' => $luasLahanPerPetani->filter(fn ($item) => $item->total_luas < 5000)->count(), + '05_1' => $luasLahanPerPetani->filter(fn ($item) => $item->total_luas >= 5000 && $item->total_luas <= 10000)->count(), + '1_2' => $luasLahanPerPetani->filter(fn ($item) => $item->total_luas > 10000 && $item->total_luas <= 20000)->count(), + 'lebih_2' => $luasLahanPerPetani->filter(fn ($item) => $item->total_luas > 20000)->count(), + ]; + + $pendapatanPerPetani = PendapatanKomoditas::with('sosialEkonomi.petani')->get() + ->filter(fn ($item) => $item->sosialEkonomi?->petani) + ->groupBy(fn ($item) => $item->sosialEkonomi->petani_id) + ->map(fn ($items) => $items->sum('pendapatan')); + + $penghasilan = [ + 'kurang_1' => $pendapatanPerPetani->filter(fn ($value) => $value < 1000000)->count(), + '1_3' => $pendapatanPerPetani->filter(fn ($value) => $value >= 1000000 && $value <= 3000000)->count(), + '3_5' => $pendapatanPerPetani->filter(fn ($value) => $value > 3000000 && $value <= 5000000)->count(), + '5_10' => $pendapatanPerPetani->filter(fn ($value) => $value > 5000000 && $value <= 10000000)->count(), + 'lebih_10' => $pendapatanPerPetani->filter(fn ($value) => $value > 10000000)->count(), + ]; + + $data = [ + 'total_petani' => $totalPetani, + 'petani_lakilaki' => $petaniLakilaki, + 'petani_perempuan' => $petaniPerempuan, + 'total_komoditas' => $totalKomoditas, + 'total_luas_lahan' => $totalLuasLahan, + 'ratarata_luas_lahan' => $ratarataLuasLahan, + 'kelompok_umur' => [ + 'kurang_30' => $umurKurang30, + '30_39' => $umur30sampai39, + '40_49' => $umur40sampai49, + '50_59' => $umur50sampai59, + '60_keatas' => $umur60keatas, + ], + 'pendidikan' => $pendidikan, + 'komoditas_utama' => [ + 'ids' => $komoditasUtama + ->pluck('id') + ->values(), + + 'labels' => $komoditasUtama + ->pluck('nama') + ->values(), + + 'series' => $komoditasUtama + ->pluck('petani_count') + ->map(fn ($value) => (int) $value) + ->values(), + ], + 'luas_lahan' => $luasLahan, + 'penghasilan' => $penghasilan, + ]; + + $daftarPetani = Petani::with([ + 'komoditas' + ]) + ->withSum('lahans as total_luas_lahan', 'luas_lahan') + ->orderBy('id') + ->paginate(10); + // dd($daftarPetani); + return view('dashboard.demografi-petani', compact('data', 'daftarPetani')); + } + + public function data(Request $request) + { + $query = Petani::with('komoditas')->withSum( 'lahans as total_luas_lahan', 'luas_lahan'); + + if ($request->filled('search')) { + $search = $request->search; + $query->where('nama', 'ILIKE', "%{$search}%" ); + } + + $pendapatanPerPetani = PendapatanKomoditas::with('sosialEkonomi.petani')->get() + ->filter(fn ($item) => $item->sosialEkonomi?->petani) + ->groupBy(fn ($item) => $item->sosialEkonomi->petani_id) + ->map(fn ($items) => $items->sum('pendapatan')); + + if ($request->has('gender') && $request->gender !== '') { + $query->where('jenis_kelamin', $request->gender ); + } + + if ($request->filled('umur')) { + match ($request->umur) { + 'kurang_30' => $query->whereNotNull('tanggal_lahir') + ->whereRaw("EXTRACT( YEAR FROM AGE( CURRENT_DATE, tanggal_lahir)) < 30"), + '30_39' => $query->whereNotNull('tanggal_lahir') + ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 30 AND 39"), + '40_49' => $query->whereNotNull('tanggal_lahir') + ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 40 AND 49"), + '50_59' => $query->whereNotNull('tanggal_lahir') + ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 50 AND 59"), + '60_keatas' => $query ->whereNotNull('tanggal_lahir') + ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) >= 60"), + default => null + }; + } + + if ($request->filled('pendidikan')) { + $pendidikanMap = [ + 'tidak_sekolah' => ['01_tidak_sekolah'], + 'sd' => ['02_sd'], + 'smp' => ['03_smp'], + 'sma' => ['04_sma'], + 'diploma' => ['05_diploma'], + 's1_keatas' => ['06_sarjana', '07_magister'], + ]; + + if (isset($pendidikanMap[$request->pendidikan])) { + $query->whereIn('pendidikan_terakhir', $pendidikanMap[$request->pendidikan]); + } + } + + if ($request->filled('komoditas')) { + $query->where('komoditas_id', $request->komoditas); + } + + if ($request->filled('penghasilan')) { + $filteredPendapatan = + match ($request->penghasilan) { + 'kurang_1' => $pendapatanPerPetani ->filter(fn ($value) => $value < 1000000 ), + '1_3' => $pendapatanPerPetani->filter( fn ($value) => $value >= 1000000 && $value <= 3000000 ), + '3_5' => $pendapatanPerPetani->filter(fn ($value) => $value > 3000000 && $value <= 5000000 ), + '5_10' => $pendapatanPerPetani->filter(fn ($value) => $value > 5000000 && $value <= 10000000 ), + 'lebih_10' => $pendapatanPerPetani->filter(fn ($value) => $value > 10000000 ), + default => collect() + }; + + $query->whereIn('id', $filteredPendapatan->keys()->values()->all()); + } + + if ($request->filled('luas_lahan')) { + $lahanQuery = Lahan::query()->select('petani_id')->groupBy('petani_id'); + match ($request->luas_lahan) { + 'kurang_05' => $lahanQuery->havingRaw('SUM(luas_lahan) < 5000' ), + '05_1' => $lahanQuery->havingRaw('SUM(luas_lahan) >= 5000 AND SUM(luas_lahan) <= 10000' ), + '1_2' => $lahanQuery->havingRaw('SUM(luas_lahan) > 10000 AND SUM(luas_lahan) <= 20000'), + 'lebih_2' => $lahanQuery->havingRaw('SUM(luas_lahan) > 20000'), + default => null + }; + $query->whereIn('id', $lahanQuery->pluck('petani_id')); + } + + $daftarPetani = $query->orderBy('id')->paginate(10); + + $pendidikanLabels = [ + '01_tidak_sekolah' => 'Tidak Sekolah', + '02_sd' => 'SD', + '03_smp' => 'SMP', + '04_sma' => 'SMA', + '05_diploma' => 'Diploma', + '06_sarjana' => 'Sarjana', + '07_magister' => 'Magister', + ]; + + $rows = collect($daftarPetani->items())->map(function ($petani) use ( + $pendidikanLabels, + $pendapatanPerPetani + ) { + $umur = $petani->tanggal_lahir ? \Carbon\Carbon::parse($petani->tanggal_lahir)->age : null; + $pendidikanRaw = $petani->getRawOriginal('pendidikan_terakhir'); + $pendapatan = $pendapatanPerPetani->get($petani->id); + + $rentangPenghasilan = match (true) { + $pendapatan === null => '-', + $pendapatan < 1000000 => '< Rp1 juta', + $pendapatan <= 3000000 => 'Rp1 - 3 juta', + $pendapatan <= 5000000 => 'Rp3 - 5 juta', + $pendapatan <= 10000000 => 'Rp5 - 10 juta', + default => '> Rp10 juta', + }; + + return [ + 'id' => $petani->kode ?? $petani->id, + 'nama' => $petani->nama ?? '-', + 'jenis_kelamin' => $petani->jenis_kelamin, + 'gender' => $petani->jenis_kelamin == 1 ? 'Laki-laki' : 'Perempuan', + 'umur' => $umur, + 'komoditas' => $petani->komoditas?->nama ?? '-', + 'luas_lahan' => (float) ($petani->total_luas_lahan ?? 0 ), + 'pendidikan' => $pendidikanLabels[$pendidikanRaw ] ?? '-', + 'rentang_penghasilan' => $rentangPenghasilan, + ]; + }); + + return response()->json([ + 'data' => $rows, + 'pagination' => [ + 'current_page' => $daftarPetani->currentPage(), + 'last_page' => $daftarPetani->lastPage(), + 'per_page' => $daftarPetani->perPage(), + 'total' => $daftarPetani->total(), + 'from' => $daftarPetani->firstItem(), + 'to' => $daftarPetani->lastItem(), + ], + ]); + } +} diff --git a/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php b/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php new file mode 100644 index 0000000..4fbe6e3 --- /dev/null +++ b/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php @@ -0,0 +1,180 @@ +get(); + + $petani = Petani::pluck('id'); + $lahan = Lahan::has('petani')->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 + "; + + $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'); + + $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'); + + if ($avgSkor >= 4.0) { + $avgSegmen = 'Penggerak'; + } elseif ($avgSkor >= 3.0) { + $avgSegmen = 'Perintis'; + } elseif ($avgSkor >= 2.0) { + $avgSegmen = 'Pemerhati'; + } elseif ($avgSkor >= 1.0) { + $avgSegmen = 'Pemula'; + } else { + $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'); + + $countSegmentasi = SkorPetani::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') + ->selectRaw(" + petani.komoditas_id, + $case AS segmen, + COUNT(petani.id) AS total + ") + ->groupBy('petani.komoditas_id') + ->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')) + ->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')) + ->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, + avg(skor_komp_4_d4_k4_keterlibatan_kelembagaan) as skor_komp_4_d4_k4_keterlibatan_kelembagaan, + avg(skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan) as skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan, + 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') + ->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 + ") + ->whereIn('petani.id', $petani) + ->distinct() + ->get(); + + $mapSegmentasi = SkorPetani::query() + ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') + ->whereNull('petani.deleted_at') + ->selectRaw("petani.desa_kelurahan_id, + $case AS segmen, + COUNT(petani.id) AS total + ") + ->groupBy('petani.desa_kelurahan_id') + ->groupByRaw($case) + ->get(); + + $mapAvgSkorSegmentasi = SkorPetani::query() + ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') + ->whereNull('petani.deleted_at') + ->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(); + + $daftarPetani = Petani::query() + ->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', + )); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php new file mode 100644 index 0000000..9f4a55c --- /dev/null +++ b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php @@ -0,0 +1,760 @@ +kabupatenOptions(); + $ngadaOption = collect($kabupatenOptions)->first( + fn ($option) => str_contains(strtolower($option['label']), 'ngada') + ); + $initialFilters = $this->selectedFilters($request, $ngadaOption['value'] ?? 'all'); + + $totalPetani = $this->applyPetaniFilters(Petani::query(), $initialFilters)->count(); + $totalLuasLahan = ((float) $this->applyLahanFilters(Lahan::query(), $initialFilters)->sum('luas_lahan')) / 10000; + $rataRataLuasLahan = $totalPetani > 0 + ? $totalLuasLahan / $totalPetani + : 0; + $totalProduksiKg = $this->totalProduksiKg($initialFilters); + $rataRataProduksiKg = $totalPetani > 0 + ? $totalProduksiKg / $totalPetani + : 0; + $rataRataProduktivitas = $totalLuasLahan > 0 + ? $totalProduksiKg / $totalLuasLahan + : 0; + + $filterOptions = [ + [ + 'key' => 'kabupaten', + 'label' => 'Kabupaten', + 'options' => $kabupatenOptions, + 'icon' => 'tabler-map-pin', + 'readonly' => true, + ], + [ + 'key' => 'kecamatan', + 'label' => 'Kecamatan', + 'options' => $this->kecamatanOptions(), + ], + [ + 'key' => 'desa', + 'label' => 'Desa', + 'options' => $this->desaOptions(), + ], + [ + 'key' => 'komoditas', + 'label' => 'Komoditas', + 'options' => $this->komoditasOptions(), + ], + [ + 'key' => 'segmentasi', + 'label' => 'Segmentasi', + 'options' => $this->segmentasiOptions(), + ], + ]; + + $summaryData = [ + [ + 'value' => number_format($totalPetani, 0, ',', '.'), + 'label' => 'Petani Terdata', + 'description' => 'Total petani yang masuk sistem', + 'icon' => 'tabler-users', + 'variant' => 'primary', + ], + [ + 'value' => number_format($totalLuasLahan, 2, ',', '.').' ha', + 'label' => 'Total Luas Lahan', + 'description' => 'Rata-rata '.number_format($rataRataLuasLahan, 2, ',', '.').' ha/petani', + 'icon' => 'tabler-mountain', + 'variant' => 'success', + ], + [ + 'value' => number_format($totalProduksiKg, 0, ',', '.').' kg', + 'label' => 'Total Produksi (Semua Komoditas)', + 'description' => 'Rata-rata '.number_format($rataRataProduksiKg, 0, ',', '.').' kg/petani', + 'icon' => 'tabler-wheat', + 'variant' => 'warning', + ], + [ + 'value' => number_format($rataRataProduktivitas, 0, ',', '.').' kg/ha', + 'label' => 'Rata-rata Produktivitas', + 'description' => 'Semua komoditas berdasarkan total produksi dan luas lahan', + 'icon' => 'tabler-chart-bar', + 'variant' => 'info', + ], + ]; + + return view('dashboard.indikator-pertanian', [ + 'title' => 'Indikator Pertanian', + 'initialFilters' => $initialFilters, + 'filterOptions' => $filterOptions, + 'summaryData' => $summaryData, + 'chartData' => [ + 'petaniPerKomoditas' => $this->petaniPerKomoditasChart($initialFilters), + 'luasLahanPerKecamatan' => $this->luasLahanPerKecamatanChart($initialFilters), + 'kondisiTanaman' => $this->kondisiTanamanChart($initialFilters), + 'statusKepemilikanLahan' => $this->statusKepemilikanLahanChart($initialFilters), + 'seranganHama' => $this->seranganHamaChart($initialFilters), + 'penyakitTanaman' => $this->penyakitTanamanChart($initialFilters), + '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'), + ], + ]); + } + + private function selectedFilters(Request $request, string $defaultKabupaten): array + { + $filters = [ + 'kabupaten' => $defaultKabupaten, + 'kecamatan' => $this->validFilterValue($request->query('kecamatan'), Kecamatan::class), + 'desa' => $this->validFilterValue($request->query('desa'), DesaKelurahan::class), + 'komoditas' => $this->validFilterValue($request->query('komoditas'), Komoditas::class), + 'segmentasi' => $this->validSegmentasi((string) $request->query('segmentasi', 'all')), + ]; + + if ($filters['desa'] !== 'all') { + $desa = DesaKelurahan::query()->find($filters['desa']); + + if (! $desa || ($filters['kecamatan'] !== 'all' && (string) $desa->kecamatan_id !== $filters['kecamatan'])) { + $filters['desa'] = 'all'; + } + } + + if ($filters['kecamatan'] === 'all') { + $filters['desa'] = 'all'; + } + + return $filters; + } + + private function validFilterValue(mixed $value, string $modelClass): string + { + if (! $value || $value === 'all') { + return 'all'; + } + + return $modelClass::query()->whereKey($value)->exists() + ? (string) $value + : 'all'; + } + + private function validSegmentasi(string $value): string + { + return in_array($value, [ + 'Penggerak', + 'Perintis', + 'Pemerhati', + 'Pemula', + 'Belum tersegmentasi', + 'all', + ], true) ? $value : 'all'; + } + + private function kabupatenOptions(): array + { + return $this->withAllOption( + 'Semua Kabupaten', + KabupatenKota::query() + ->orderBy('nama') + ->get(['id', 'kode', 'nama']) + ->map(fn (KabupatenKota $kabupaten) => [ + 'value' => (string) $kabupaten->id, + 'label' => $this->kabupatenLabel($kabupaten), + ]) + ->values() + ->all() + ); + } + + private function kecamatanOptions(): array + { + return $this->withAllOption( + 'Semua Kecamatan', + Kecamatan::query() + ->orderBy('nama') + ->get(['id', 'nama']) + ->map(fn (Kecamatan $kecamatan) => [ + 'value' => (string) $kecamatan->id, + 'label' => $kecamatan->nama, + ]) + ->values() + ->all() + ); + } + + private function desaOptions(): array + { + return $this->withAllOption( + 'Semua Desa', + DesaKelurahan::query() + ->orderBy('nama') + ->get(['id', 'nama', 'kecamatan_id']) + ->map(fn (DesaKelurahan $desa) => [ + 'value' => (string) $desa->id, + 'label' => $desa->nama, + 'parent' => (string) $desa->kecamatan_id, + ]) + ->values() + ->all() + ); + } + + private function komoditasOptions(): array + { + return $this->withAllOption( + 'Semua Komoditas', + Komoditas::query() + ->orderBy('nama') + ->get(['id', 'nama']) + ->map(fn (Komoditas $komoditas) => [ + 'value' => (string) $komoditas->id, + 'label' => $komoditas->nama, + ]) + ->values() + ->all() + ); + } + + private function segmentasiOptions(): array + { + $segments = SkorPetani::query() + ->whereNotNull('skor_kesiapan_adopsi') + ->pluck('skor_kesiapan_adopsi') + ->map(fn ($score) => $this->segmentLabel((float) $score)) + ->filter() + ->unique() + ->sortBy(fn ($segment) => array_search($segment, [ + 'Penggerak', + 'Perintis', + 'Pemerhati', + 'Pemula', + 'Belum tersegmentasi', + ], true)) + ->map(fn ($segment) => [ + 'value' => $segment, + 'label' => $segment, + ]) + ->values() + ->all(); + + return $this->withAllOption('Semua Segmentasi', $segments); + } + + private function totalProduksiKg(array $filters): float + { + return $this->applyProduksiFilters(Produksi::query(), $filters) + ->whereNotNull('jumlah_panen') + ->get(['jumlah_panen', 'satuan']) + ->sum(fn (Produksi $produksi) => $this->toKilograms( + (float) $produksi->jumlah_panen, + (string) $produksi->satuan + )); + } + + private function petaniPerKomoditasChart(array $filters): array + { + $rows = $this->applyPetaniFilters(Petani::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'petani.komoditas_id') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('COUNT(petani.id) as total') + ->groupBy('k.id', 'k.nama') + ->orderByDesc('total') + ->get(); + + return [ + 'labels' => $rows->pluck('label')->values()->all(), + 'series' => $rows->pluck('total')->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + + private function luasLahanPerKecamatanChart(array $filters): array + { + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->leftJoin('master_desa_kelurahan as d', 'd.id', '=', 'map_lahan.desa_kelurahan_id') + ->leftJoin('master_kecamatan as k', 'k.id', '=', 'd.kecamatan_id') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('SUM(map_lahan.luas_lahan) / 10000 as total') + ->groupBy('k.id', 'k.nama') + ->havingRaw('SUM(map_lahan.luas_lahan) > 0') + ->orderByDesc('total') + ->limit(8) + ->get() + ->filter(fn ($row) => round((float) $row->total, 2) > 0) + ->values(); + + return [ + 'labels' => $rows->pluck('label')->values()->all(), + 'series' => $rows->pluck('total')->map(fn ($value) => round((float) $value, 2))->values()->all(), + ]; + } + + private function kondisiTanamanChart(array $filters): array + { + $rows = $this->applyTanamanTableFilters(DB::table('map_tanaman'), $filters) + ->whereNull('map_tanaman.deleted_at') + ->whereNotNull('map_tanaman.kondisi_tanaman') + ->selectRaw('map_tanaman.kondisi_tanaman as label') + ->selectRaw('COUNT(map_tanaman.id) as total') + ->groupBy('map_tanaman.kondisi_tanaman') + ->orderByDesc('total') + ->get(); + + if ($rows->isEmpty()) { + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNull('deleted_at') + ->whereNotNull('kondisi_tanaman') + ->selectRaw('kondisi_tanaman as label') + ->selectRaw('COUNT(map_lahan.id) as total') + ->groupBy('kondisi_tanaman') + ->orderByDesc('total') + ->get(); + } + + return [ + 'labels' => $rows->pluck('label')->map(fn ($label) => $this->shortEnumLabel((string) $label))->values()->all(), + 'series' => $rows->pluck('total')->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + + private function seranganHamaChart(array $filters): array + { + return $this->tanamanAttributeChart( + $filters, + 'serangan_hama', + fn ($label) => $this->enumLabel(SeranganHama::class, (string) $label) + ); + } + + private function penyakitTanamanChart(array $filters): array + { + return $this->tanamanAttributeChart( + $filters, + 'penyakit_tanaman', + fn ($label) => $this->enumLabel(PenyakitTanaman::class, (string) $label) + ); + } + + private function keparahanSeranganChart(array $filters): array + { + return $this->tanamanAttributeChart( + $filters, + 'keparahan_serangan', + fn ($label) => $this->keparahanSeranganLabel((string) $label) + ); + } + + private function statusKepemilikanLahanChart(array $filters): array + { + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('status_kepemilikan') + ->selectRaw('status_kepemilikan as label') + ->selectRaw('COUNT(map_lahan.id) as total') + ->groupBy('status_kepemilikan') + ->orderByDesc('total') + ->get(); + + return $this->chartFromRows($rows, fn ($label) => $this->shortEnumLabel((string) $label)); + } + + private function statusHakKelolaLahanChart(array $filters): array + { + $rows = $this->applySosialEkonomiFilters(SosialEkonomi::query(), $filters) + ->whereNotNull('status_kepemilikan_lahan') + ->selectRaw('status_kepemilikan_lahan as label') + ->selectRaw('COUNT(sosial_ekonomi.id) as total') + ->groupBy('status_kepemilikan_lahan') + ->orderByDesc('total') + ->get(); + + return $this->chartFromRows( + $rows, + fn ($label) => $this->enumLabel(StatusKepemilikanLahanSosialEkonomi::class, (string) $label) + ); + } + + private function praktikPemupukanChart(array $filters): array + { + $rows = $this->applyPraktikBudidayaFilters(PraktikBudidaya::query(), $filters) + ->whereNotNull('pemberian_pupuk') + ->selectRaw('pemberian_pupuk as label') + ->selectRaw('COUNT(praktik_budidaya.id) as total') + ->groupBy('pemberian_pupuk') + ->orderBy('pemberian_pupuk') + ->get(); + + return $this->chartFromRows( + $rows, + fn ($label) => $this->pemberianPupukLabel((int) $label) + ); + } + + 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 [ + 'labels' => $rows + ->pluck('label') + ->map(fn ($label) => $labelResolver($label)) + ->values() + ->all(), + 'series' => $rows + ->pluck('total') + ->map(fn ($value) => (int) $value) + ->values() + ->all(), + ]; + } + + private function tanamanAttributeChart(array $filters, string $field, callable $labelResolver): array + { + $qualifiedField = 'map_tanaman.'.$field; + + $rows = $this->applyTanamanTableFilters(DB::table('map_tanaman'), $filters) + ->whereNull('map_tanaman.deleted_at') + ->whereNotNull($qualifiedField) + ->selectRaw($qualifiedField.' as label') + ->selectRaw('COUNT(map_tanaman.id) as total') + ->groupBy($qualifiedField) + ->orderByDesc('total') + ->get(); + + if ($rows->isEmpty()) { + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull($field) + ->selectRaw($field.' as label') + ->selectRaw('COUNT(map_lahan.id) as total') + ->groupBy($field) + ->orderByDesc('total') + ->get(); + } + + return $this->chartFromRows($rows, $labelResolver); + } + + private function applyPetaniFilters($query, array $filters) + { + return $query + ->when($filters['kecamatan'] !== 'all', function ($query) use ($filters) { + $query->whereHas('desaKelurahan', fn ($desa) => $desa->where('kecamatan_id', $filters['kecamatan'])); + }) + ->when($filters['desa'] !== 'all', fn ($query) => $query->where('desa_kelurahan_id', $filters['desa'])) + ->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('komoditas_id', $filters['komoditas'])) + ->when($filters['segmentasi'] !== 'all', function ($query) use ($filters) { + $query->whereHas('skor', function ($skor) use ($filters) { + $this->applySegmentasiRange($skor, $filters['segmentasi']); + }); + }); + } + + private function applyLahanFilters($query, array $filters) + { + return $query + ->when($filters['kecamatan'] !== 'all', function ($query) use ($filters) { + $query->whereHas('desaKelurahan', fn ($desa) => $desa->where('kecamatan_id', $filters['kecamatan'])); + }) + ->when($filters['desa'] !== 'all', fn ($query) => $query->where('desa_kelurahan_id', $filters['desa'])) + ->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('komoditas_id', $filters['komoditas'])) + ->when($filters['segmentasi'] !== 'all', function ($query) use ($filters) { + $query->whereIn('petani_id', $this->segmentasiPetaniIdsQuery($filters['segmentasi'])); + }); + } + + private function applyProduksiFilters($query, array $filters) + { + return $query + ->when($filters['kecamatan'] !== 'all' || $filters['desa'] !== 'all' || $filters['segmentasi'] !== 'all', function ($query) use ($filters) { + $query->whereHas('lahan', function ($lahan) use ($filters) { + $this->applyLahanFilters($lahan, $filters); + }); + }) + ->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('komoditas_id', $filters['komoditas'])); + } + + private function applySosialEkonomiFilters($query, array $filters) + { + return $query->whereHas('petani', function ($petani) use ($filters) { + $this->applyPetaniFilters($petani, $filters); + }); + } + + private function applyPraktikBudidayaFilters($query, array $filters) + { + return $query->whereHas('petani', function ($petani) use ($filters) { + $this->applyPetaniFilters($petani, $filters); + }); + } + + 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 + ->leftJoin('map_lahan as l', 'l.id', '=', 'map_tanaman.lahan_id') + ->when($filters['kecamatan'] !== 'all', function ($query) use ($filters) { + $query + ->leftJoin('master_desa_kelurahan as d', 'd.id', '=', 'l.desa_kelurahan_id') + ->where('d.kecamatan_id', $filters['kecamatan']); + }) + ->when($filters['desa'] !== 'all', fn ($query) => $query->where('l.desa_kelurahan_id', $filters['desa'])) + ->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('map_tanaman.komoditas_id', $filters['komoditas'])) + ->when($filters['segmentasi'] !== 'all', function ($query) use ($filters) { + $query->where(function ($query) use ($filters) { + $query + ->whereIn('map_tanaman.petani_id', $this->segmentasiPetaniIdsQuery($filters['segmentasi'])) + ->orWhereIn('l.petani_id', $this->segmentasiPetaniIdsQuery($filters['segmentasi'])); + }); + }); + } + + private function segmentasiPetaniIdsQuery(string $segmentasi) + { + return Petani::query() + ->select('id') + ->whereHas('skor', function ($skor) use ($segmentasi) { + $this->applySegmentasiRange($skor, $segmentasi); + }); + } + + private function applySegmentasiRange($query, string $segmentasi) + { + return match ($segmentasi) { + 'Penggerak' => $query->where('skor_kesiapan_adopsi', '>=', 4), + 'Perintis' => $query->where('skor_kesiapan_adopsi', '>=', 3)->where('skor_kesiapan_adopsi', '<', 4), + 'Pemerhati' => $query->where('skor_kesiapan_adopsi', '>=', 2)->where('skor_kesiapan_adopsi', '<', 3), + 'Pemula' => $query->where('skor_kesiapan_adopsi', '>=', 1)->where('skor_kesiapan_adopsi', '<', 2), + default => $query->where(function ($query) { + $query->whereNull('skor_kesiapan_adopsi')->orWhere('skor_kesiapan_adopsi', '<', 1); + }), + }; + } + + private function shortEnumLabel(string $value): string + { + return str($value) + ->replace('_', ' ') + ->headline() + ->toString(); + } + + private function enumLabel(string $enumClass, int|string $value): string + { + $case = $enumClass::tryFrom($value); + + if (! $case) { + return $this->shortEnumLabel((string) $value); + } + + return method_exists($case, 'label') + ? $case->label() + : $this->shortEnumLabel((string) $case->value); + } + + private function keparahanSeranganLabel(string $value): string + { + return match (KeparahanSerangan::tryFrom($value)) { + KeparahanSerangan::RINGAN => 'Ringan', + KeparahanSerangan::SEDANG => 'Sedang', + KeparahanSerangan::BERAT => 'Parah', + default => $this->shortEnumLabel($value), + }; + } + + private function pemberianPupukLabel(int $value): string + { + return match (PemberianPupuk::tryFrom($value)) { + PemberianPupuk::TIDAK_PERNAH => 'Tidak pernah', + PemberianPupuk::JENIS_DOSIS_WAKTU_TIDAK_MENENTU => 'Tidak menentu', + PemberianPupuk::JENIS_SESUAI_DOSIS_TIDAK_MENENTU => 'Jenis sesuai', + PemberianPupuk::JENIS_DOSIS_SESUAI_WAKTU_CUKUP_TEPAT => 'Cukup tepat', + PemberianPupuk::JENIS_DOSIS_SESUAI_WAKTU_TEPAT => 'Tepat & rutin', + default => $this->shortEnumLabel((string) $value), + }; + } + + private function toKilograms(float $value, string $unit): float + { + return match (strtolower($unit)) { + 'ton' => $value * 1000, + 'kuintal', 'kwintal' => $value * 100, + default => $value, + }; + } + + private function withAllOption(string $label, array $options): array + { + return array_merge([ + [ + 'value' => 'all', + 'label' => $label, + ], + ], $options); + } + + private function kabupatenLabel(KabupatenKota $kabupaten): string + { + return preg_replace('/^(kabupaten|kota)\s+/i', '', $kabupaten->nama); + } + + private function segmentLabel(float $score): string + { + return match (true) { + $score >= 4.0 => 'Penggerak', + $score >= 3.0 => 'Perintis', + $score >= 2.0 => 'Pemerhati', + $score >= 1.0 => 'Pemula', + default => 'Belum tersegmentasi', + }; + } +} diff --git a/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php b/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php index 68a6b17..e74952d 100644 --- a/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php @@ -110,7 +110,7 @@ class ProfilPetaniController extends Controller 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, avg(skor_komp_4_d4_k4_keterlibatan_kelembagaan) as skor_komp_4_d4_k4_keterlibatan_kelembagaan, - avg(skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan) as skor_komp_5_d4_k5_k6_akses_kebebasan_keuanga, + avg(skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan) as skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan, 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(); diff --git a/app/Models/Pertanian/Lahan.php b/app/Models/Pertanian/Lahan.php index 8021c23..fc18aca 100644 --- a/app/Models/Pertanian/Lahan.php +++ b/app/Models/Pertanian/Lahan.php @@ -18,6 +18,7 @@ use App\Enums\KondisiTanaman; use App\Enums\SeranganHama; use App\Enums\PenyakitTanaman; use App\Enums\KeparahanSerangan; +use App\Models\Pertanian\Petani; class Lahan extends Model { @@ -98,7 +99,7 @@ class Lahan extends Model public function petani(): BelongsTo { - return $this->belongsTo(Profile::class, 'petani_id'); + return $this->belongsTo(Petani::class, 'petani_id'); } public function komoditas(): BelongsTo diff --git a/app/Models/Pertanian/Petani.php b/app/Models/Pertanian/Petani.php index a44bb2e..e7053e0 100644 --- a/app/Models/Pertanian/Petani.php +++ b/app/Models/Pertanian/Petani.php @@ -339,7 +339,7 @@ class Petani extends Model $skor >= 3.0 => 'Perintis', $skor >= 2.0 => 'Pemerhati', $skor >= 1.0 => 'Pemula', - default => 'Belum tersegmentasi', + default => 'Belum lengkap', }; } @@ -365,10 +365,10 @@ class Petani extends Model } elseif ($skor->skor_kesiapan_adopsi >= 1.0) { return 'Pemula'; } else { - return 'Belum tersegmentasi'; + return 'Belum lengkap'; } - return 'Belum tersegmentasi'; + return 'Belum lengkap'; } public function keteranganSegmen(): ?string diff --git a/app/Models/Pertanian/SkorPetani.php b/app/Models/Pertanian/SkorPetani.php index b1482bc..3d2fb0a 100644 --- a/app/Models/Pertanian/SkorPetani.php +++ b/app/Models/Pertanian/SkorPetani.php @@ -4,6 +4,9 @@ namespace App\Models\Pertanian; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +use App\Models\Pertanian\Petani; class SkorPetani extends Model { @@ -139,4 +142,9 @@ class SkorPetani extends Model ); }); } + + public function petani(): BelongsTo + { + return $this->belongsTo(Petani::class, 'petani_id'); + } } diff --git a/resources/views/dashboard/demografi-petani.blade.php b/resources/views/dashboard/demografi-petani.blade.php new file mode 100644 index 0000000..68ed927 --- /dev/null +++ b/resources/views/dashboard/demografi-petani.blade.php @@ -0,0 +1,1325 @@ +@extends('layout.main') + +@push('styles') + + +@endpush + +@section('content') +
+ Total Petani +
+ + + Petani yang telah terdata + ++ Total Komoditas +
+ + + Komoditas utama yang dikelola petani + ++ Total Luas Lahan +
+ + + Seluruh lahan petani + +| No. | +Nama Petani | +Gender | +Umur | +Komoditas | +Luas Lahan | +Pendidikan | +Rentang Pendapatan | +
|---|
Total Petani
++ {{ $countKomoditas }} + komoditas utama +
+Total Luas Lahan
++ rata-rata + {{ number_format($avgLahan, 2, ',', '.') }} + ha/petani +
+Rata-rata Indeks Kesiapan Adopsi
++ Segmentasi: + {{ $avgSegmen }} +
+Jumlah Desa Sasaran
++ {{ $countKecamatan }} + kecamatan sasaran +
+untuk semua komoditas
+| + | Petani | +% | +
|---|---|---|
|
+
+
+
+
+
+
+ {{ $segment['name'] }}
+
+ |
+ {{ number_format($total) }} | +{{ number_format($persen, 2) }}% | +
per komoditas
+untuk semua komoditas
+untuk semua komoditas
+berdasarkan sebaran wilayah untuk semua komoditas
+berdasarkan sebaran wilayah untuk semua komoditas
+| Desa/Kelurahan | +Petani | +Segmen Rata-rata | +Segmen Dominan | +
|---|---|---|---|
| {{ $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) + | +
untuk semua komoditas
+| Nama Petani | +Desa/Kelurahan | +Komoditas | +Luas Lahan (ha) | +Indeks Kesiapan Adopsi | +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 + | +
+ Kondisi dan performa usaha tani petani berdasarkan hasil survei +
++ {{ $summary['label'] }} +
+ ++ + {{ $summary['description'] }} + +
+Petani
+Total Petani
{{ $petaniSummary->count('total') }} komoditas utama diff --git a/resources/views/layout/sidebar.blade.php b/resources/views/layout/sidebar.blade.php index 202c5c0..bcbc985 100644 --- a/resources/views/layout/sidebar.blade.php +++ b/resources/views/layout/sidebar.blade.php @@ -68,6 +68,23 @@ @endif + @if(in_array($userRole, ['super_admin', 'admin']) && env('APP_NAME') == 'AgroMonev') +
+ + @endif + @if(in_array($userRole, ['super_admin', 'admin', 'fasilitator']) && env('APP_NAME') == 'AgroMonev')