diff --git a/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php b/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php index 1831b29..13fb387 100644 --- a/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/DemografiPetaniController.php @@ -11,6 +11,7 @@ use App\Models\Pertanian\Petani; use App\Models\Pertanian\Komoditas; use App\Models\Pertanian\Lahan; use App\Models\Pertanian\PendapatanKomoditas; +use App\Models\Pertanian\SosialEkonomi; class DemografiPetaniController extends Controller { @@ -20,7 +21,35 @@ class DemografiPetaniController extends Controller abort(403); } - $petaniCounts = Petani::selectRaw(" + return redirect()->route('dashboard.profil-pertanian', array_merge($request->query(), [ + 'tab' => 'demografi-petani', + ])); + } + + public function profil(Request $request) + { + if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { + abort(403); + } + + $activeTab = $request->query('tab') === 'indeks-petani' + ? 'indeks-petani' + : 'demografi-petani'; + + $demografiData = $this->contentData($request); + $indeksData = app(IndeksPetaniController::class)->contentData($request); + + return view('dashboard.profil-pertanian', [ + 'activeTab' => $activeTab, + 'indeksFilterAction' => route('dashboard.profil-pertanian'), + ] + $demografiData + $indeksData); + } + + public function contentData(Request $request): array + { + $filteredPetaniIds = $this->filteredPetaniIdsQuery($request); + + $petaniCounts = Petani::whereIn('petani.id', clone $filteredPetaniIds)->selectRaw(" COUNT(*) as total, COUNT(*) FILTER (WHERE jenis_kelamin = true) as laki, COUNT(*) FILTER (WHERE jenis_kelamin = false) as perempuan @@ -30,14 +59,18 @@ class DemografiPetaniController extends Controller $petaniLakilaki = $petaniCounts->laki; $petaniPerempuan = $petaniCounts->perempuan; - $totalKomoditas = Petani::whereNotNull('komoditas_id') - ->distinct() - ->count('komoditas_id'); + $totalKomoditas = Komoditas::query() + ->where('is_utama', true) + ->whereHas('petani', fn ($query) => $query->whereIn('petani.id', clone $filteredPetaniIds)) + ->count(); - $totalLuasLahan = Lahan::has('petani')->sum('luas_lahan'); + $totalLuasLahan = Lahan::has('petani') + ->whereIn('petani_id', clone $filteredPetaniIds) + ->sum('luas_lahan'); $ratarataLuasLahan = $totalLuasLahan && $totalPetani ? $totalLuasLahan / $totalPetani : 0; - $umurCounts = Petani::whereNotNull('tanggal_lahir')->selectRaw(" + $umurCounts = Petani::whereIn('petani.id', clone $filteredPetaniIds) + ->whereNotNull('tanggal_lahir')->selectRaw(" COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) < 30) as kurang_30, COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 30 AND 39) as umur_30_39, COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 40 AND 49) as umur_40_49, @@ -45,7 +78,8 @@ class DemografiPetaniController extends Controller COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) >= 60) as umur_60_keatas ")->first(); - $pendidikanCounts = Petani::whereNotNull('pendidikan_terakhir') + $pendidikanCounts = Petani::whereIn('petani.id', clone $filteredPetaniIds) + ->whereNotNull('pendidikan_terakhir') ->select('pendidikan_terakhir', DB::raw('COUNT(*) as total')) ->groupBy('pendidikan_terakhir') ->pluck('total', 'pendidikan_terakhir'); @@ -59,20 +93,71 @@ class DemografiPetaniController extends Controller 's1_keatas' => (int) ($pendidikanCounts['06_sarjana'] ?? 0) + (int) ($pendidikanCounts['07_magister'] ?? 0), ]; + $jumlahTanggunganBuckets = SosialEkonomi::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->whereNotNull('jumlah_tanggungan') + ->selectRaw(" + COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan = 0) as tanggungan_0, + COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan BETWEEN 1 AND 2) as tanggungan_1_2, + COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan BETWEEN 3 AND 4) as tanggungan_3_4, + COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan >= 5) as tanggungan_5_keatas + ") + ->first(); + + $jumlahTanggungan = [ + '0' => (int) ($jumlahTanggunganBuckets->tanggungan_0 ?? 0), + '1_2' => (int) ($jumlahTanggunganBuckets->tanggungan_1_2 ?? 0), + '3_4' => (int) ($jumlahTanggunganBuckets->tanggungan_3_4 ?? 0), + '5_keatas' => (int) ($jumlahTanggunganBuckets->tanggungan_5_keatas ?? 0), + ]; + + $kelompokTaniBuckets = Petani::query() + ->whereIn('petani.id', clone $filteredPetaniIds) + ->leftJoin('sosial_ekonomi', function ($join) { + $join->on('sosial_ekonomi.petani_id', '=', 'petani.id') + ->whereNull('sosial_ekonomi.deleted_at'); + }) + ->selectRaw(" + COUNT(DISTINCT petani.id) FILTER (WHERE sosial_ekonomi.terdaftar_kelompok_tani = 'ya') as terdaftar, + COUNT(DISTINCT petani.id) FILTER (WHERE sosial_ekonomi.terdaftar_kelompok_tani = 'tidak') as tidak_terdaftar, + COUNT(DISTINCT petani.id) FILTER (WHERE sosial_ekonomi.terdaftar_kelompok_tani IS NULL OR sosial_ekonomi.terdaftar_kelompok_tani NOT IN ('ya', 'tidak')) as belum_terisi + ") + ->first(); + + $kelompokTani = [ + 'terdaftar' => (int) ($kelompokTaniBuckets->terdaftar ?? 0), + 'tidak_terdaftar' => (int) ($kelompokTaniBuckets->tidak_terdaftar ?? 0), + 'belum_terisi' => (int) ($kelompokTaniBuckets->belum_terisi ?? 0), + ]; + + $desaSasaranRows = Petani::query() + ->leftJoin('master_desa_kelurahan as desa', 'petani.desa_kelurahan_id', '=', 'desa.id') + ->whereIn('petani.id', clone $filteredPetaniIds) + ->selectRaw('petani.desa_kelurahan_id as desa_id') + ->selectRaw("COALESCE(desa.nama, 'Tidak diketahui') as desa") + ->selectRaw('COUNT(*) as total') + ->groupBy('petani.desa_kelurahan_id', 'desa.nama') + ->orderByDesc('total') + ->orderBy('desa') + ->get(); + $komoditasUtama = Komoditas::query() - ->whereHas('petani') - ->withCount('petani') + ->whereHas('petani', fn ($query) => $query->whereIn('petani.id', clone $filteredPetaniIds)) + ->withCount(['petani' => fn ($query) => $query->whereIn('petani.id', clone $filteredPetaniIds)]) ->orderByDesc('petani_count') ->get(['id', 'nama']); $luasLahanBuckets = DB::query()->fromSub( - Lahan::query()->select('petani_id')->selectRaw('SUM(luas_lahan) as total_luas')->groupBy('petani_id'), + Lahan::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->select('petani_id') + ->selectRaw('luas_lahan'), 'agg' )->selectRaw(" - COUNT(*) FILTER (WHERE total_luas < 5000) as kurang_05, - COUNT(*) FILTER (WHERE total_luas >= 5000 AND total_luas <= 10000) as luas_05_1, - COUNT(*) FILTER (WHERE total_luas > 10000 AND total_luas <= 20000) as luas_1_2, - COUNT(*) FILTER (WHERE total_luas > 20000) as lebih_2 + COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan < 0.5) as kurang_05, + COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan >= 0.5 AND luas_lahan <= 1) as luas_05_1, + COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan > 1 AND luas_lahan <= 2) as luas_1_2, + COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan > 2) as lebih_2 ")->first(); $luasLahan = [ @@ -82,12 +167,28 @@ class DemografiPetaniController extends Controller 'lebih_2' => $luasLahanBuckets->lebih_2, ]; + $statusKepemilikanLahanRows = Lahan::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->whereNotNull('status_kepemilikan') + ->selectRaw('status_kepemilikan as status') + ->selectRaw('COUNT(DISTINCT petani_id) as total') + ->groupBy('status_kepemilikan') + ->orderByDesc('total') + ->get(); + + $pendapatanPerPetaniQuery = PendapatanKomoditas::query() + ->join('sosial_ekonomi', 'sosial_ekonomi.id', '=', 'pendapatan_komoditas.sosial_ekonomi_id') + ->whereNotNull('sosial_ekonomi.petani_id') + ->whereIn('sosial_ekonomi.petani_id', clone $filteredPetaniIds) + ->groupBy('sosial_ekonomi.petani_id') + ->selectRaw('SUM(pendapatan_komoditas.pendapatan) as total_pendapatan'); + + $ratarataPenghasilan = (float) DB::query() + ->fromSub(clone $pendapatanPerPetaniQuery, 'agg') + ->avg('total_pendapatan'); + $penghasilanBuckets = DB::query()->fromSub( - PendapatanKomoditas::query() - ->join('sosial_ekonomi', 'sosial_ekonomi.id', '=', 'pendapatan_komoditas.sosial_ekonomi_id') - ->whereNotNull('sosial_ekonomi.petani_id') - ->groupBy('sosial_ekonomi.petani_id') - ->selectRaw('SUM(pendapatan_komoditas.pendapatan) as total_pendapatan'), + clone $pendapatanPerPetaniQuery, 'agg' )->selectRaw(" COUNT(*) FILTER (WHERE total_pendapatan < 1000000) as kurang_1, @@ -112,6 +213,7 @@ class DemografiPetaniController extends Controller 'total_komoditas' => $totalKomoditas, 'total_luas_lahan' => $totalLuasLahan, 'ratarata_luas_lahan' => $ratarataLuasLahan, + 'ratarata_penghasilan' => $ratarataPenghasilan, 'kelompok_umur' => [ 'kurang_30' => $umurCounts->kurang_30, '30_39' => $umurCounts->umur_30_39, @@ -120,31 +222,94 @@ class DemografiPetaniController extends Controller '60_keatas' => $umurCounts->umur_60_keatas, ], 'pendidikan' => $pendidikan, + 'jumlah_tanggungan' => $jumlahTanggungan, + 'kelompok_tani' => $kelompokTani, + 'desa_sasaran' => [ + 'total' => $desaSasaranRows->count(), + 'ids' => $desaSasaranRows->pluck('desa_id')->values(), + 'labels' => $desaSasaranRows->pluck('desa')->values(), + 'series' => $desaSasaranRows->pluck('total')->map(fn ($v) => (int) $v)->values(), + ], 'komoditas_utama' => [ 'ids' => $komoditasUtama->pluck('id')->values(), 'labels' => $komoditasUtama->pluck('nama')->values(), 'series' => $komoditasUtama->pluck('petani_count')->map(fn ($v) => (int) $v)->values(), ], 'luas_lahan' => $luasLahan, + 'status_kepemilikan_lahan' => [ + 'keys' => $statusKepemilikanLahanRows->pluck('status')->values(), + 'labels' => $statusKepemilikanLahanRows + ->pluck('status') + ->map(fn ($status) => $this->statusLahanLabel((string) $status)) + ->values(), + 'series' => $statusKepemilikanLahanRows->pluck('total')->map(fn ($v) => (int) $v)->values(), + ], 'penghasilan' => $penghasilan, ]; $daftarPetani = Petani::with(['komoditas']) + ->whereIn('petani.id', clone $filteredPetaniIds) ->withSum('lahans as total_luas_lahan', 'luas_lahan') ->orderBy('id') ->paginate(10); - return view('dashboard.demografi-petani', compact('data', 'daftarPetani')); + return compact('data', 'daftarPetani'); + } + + private function filteredPetaniIdsQuery(Request $request) + { + $query = Petani::query() + ->leftJoin('master_desa_kelurahan as desa', 'petani.desa_kelurahan_id', '=', 'desa.id') + ->leftJoin('master_kecamatan as kecamatan', 'desa.kecamatan_id', '=', 'kecamatan.id') + ->leftJoin('master_kabupaten_kota as kabupaten', 'kecamatan.kabupaten_kota_id', '=', 'kabupaten.id') + ->when($request->filled('provinsi_id'), fn ($query) => $query->where('kabupaten.provinsi_id', $request->provinsi_id)) + ->when($request->filled('kabupatenKota_id'), fn ($query) => $query->where('kecamatan.kabupaten_kota_id', $request->kabupatenKota_id)) + ->when($request->filled('kecamatan_id'), fn ($query) => $query->where('desa.kecamatan_id', $request->kecamatan_id)) + ->when($request->filled('desaKelurahan_id'), fn ($query) => $query->where('petani.desa_kelurahan_id', $request->desaKelurahan_id)) + ->when($request->filled('komoditas_id'), fn ($query) => $query->where('petani.komoditas_id', $request->komoditas_id)); + + if ($request->filled('segmen')) { + $query->whereHas('skor', function ($query) use ($request) { + match ($request->segmen) { + '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), + 'Belum Lengkap' => $query->where(function ($query) { + $query->whereNull('skor_kesiapan_adopsi') + ->orWhere('skor_kesiapan_adopsi', '<', 1); + }), + default => null, + }; + }); + } + + return $query->select('petani.id'); + } + + private function statusLahanLabel(string $status): string + { + return match ($status) { + 'sendiri' => 'Milik Pribadi', + 'sewa' => 'Sewa', + 'adat' => 'Tanah Adat', + default => ucwords(str_replace('_', ' ', $status)), + }; } public function data(Request $request) { + $filteredPetaniIds = $this->filteredPetaniIdsQuery($request); $pendapatanSub = PendapatanKomoditas::query() ->join('sosial_ekonomi', 'sosial_ekonomi.id', '=', 'pendapatan_komoditas.sosial_ekonomi_id') ->whereColumn('sosial_ekonomi.petani_id', 'petani.id') ->selectRaw('SUM(pendapatan_komoditas.pendapatan)'); $query = Petani::with('komoditas') + ->whereIn('petani.id', clone $filteredPetaniIds) ->withSum('lahans as total_luas_lahan', 'luas_lahan') ->addSelect(['total_pendapatan' => $pendapatanSub]); @@ -187,6 +352,45 @@ class DemografiPetaniController extends Controller } } + if ($request->filled('jumlah_tanggungan')) { + $tanggunganQuery = SosialEkonomi::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->whereNotNull('jumlah_tanggungan') + ->select('petani_id') + ->distinct(); + + match ($request->jumlah_tanggungan) { + '0' => $tanggunganQuery->where('jumlah_tanggungan', 0), + '1_2' => $tanggunganQuery->whereBetween('jumlah_tanggungan', [1, 2]), + '3_4' => $tanggunganQuery->whereBetween('jumlah_tanggungan', [3, 4]), + '5_keatas' => $tanggunganQuery->where('jumlah_tanggungan', '>=', 5), + default => null, + }; + + $query->whereIn('petani.id', $tanggunganQuery); + } + + if ($request->filled('kelompok_tani')) { + match ($request->kelompok_tani) { + 'terdaftar' => $query->whereIn('petani.id', SosialEkonomi::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->where('terdaftar_kelompok_tani', 'ya') + ->select('petani_id') + ->distinct()), + 'tidak_terdaftar' => $query->whereIn('petani.id', SosialEkonomi::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->where('terdaftar_kelompok_tani', 'tidak') + ->select('petani_id') + ->distinct()), + 'belum_terisi' => $query->whereNotIn('petani.id', SosialEkonomi::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->whereIn('terdaftar_kelompok_tani', ['ya', 'tidak']) + ->select('petani_id') + ->distinct()), + default => null, + }; + } + if ($request->filled('komoditas')) { $query->where('komoditas_id', $request->komoditas); } @@ -213,15 +417,28 @@ class DemografiPetaniController extends Controller } if ($request->filled('luas_lahan')) { - $lahanQuery = Lahan::query()->select('petani_id')->groupBy('petani_id'); + $lahanQuery = Lahan::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->select('petani_id') + ->distinct(); + 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'), + 'kurang_05' => $lahanQuery->where('luas_lahan', '<', 0.5), + '05_1' => $lahanQuery->whereBetween('luas_lahan', [0.5, 1]), + '1_2' => $lahanQuery->where('luas_lahan', '>', 1)->where('luas_lahan', '<=', 2), + 'lebih_2' => $lahanQuery->where('luas_lahan', '>', 2), default => null, }; - $query->whereIn('id', $lahanQuery->pluck('petani_id')); + + $query->whereIn('petani.id', $lahanQuery); + } + + if ($request->filled('status_kepemilikan_lahan')) { + $query->whereIn('petani.id', Lahan::query() + ->whereIn('petani_id', clone $filteredPetaniIds) + ->where('status_kepemilikan', $request->status_kepemilikan_lahan) + ->select('petani_id') + ->distinct()); } $daftarPetani = $query->orderBy('id')->paginate(10); @@ -275,4 +492,4 @@ class DemografiPetaniController extends Controller ], ]); } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php b/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php index a7ec362..b6361c2 100644 --- a/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/IndeksPetaniController.php @@ -103,9 +103,21 @@ class IndeksPetaniController extends Controller abort(403); } + return redirect()->route('dashboard.profil-pertanian', array_merge($request->query(), [ + 'tab' => 'indeks-petani', + ])); + } + + public function contentData(Request $request): array + { $filters = $this->filters($request); $title = 'Dashboard Profil Petani'; + $segments = $this->segments(); + $colors = collect($segments) + ->pluck('color') + ->map(fn($c) => "var(--bs-{$c})") + ->values(); $komoditas = Komoditas::where('is_utama', true)->get(); $petaniQuery = $this->petaniQuery($filters); @@ -125,6 +137,11 @@ class IndeksPetaniController extends Controller ->distinct() ->get(); + $provinsi = $desaKelurahan + ->unique('provinsi_id') + ->sortBy('provinsi') + ->values(); + $wilayah = $desaKelurahan ->groupBy('provinsi_id') ->map(function ($provinsi) { @@ -157,12 +174,15 @@ class IndeksPetaniController extends Controller ]; })->values(); - return view('dashboard.indeks-petani', array_merge($filters, + return array_merge($filters, compact( 'komoditas', 'desaKelurahan', + 'provinsi', 'wilayah', - ))); + 'segments', + 'colors', + )); } public function summary(Request $request): JsonResponse @@ -655,4 +675,4 @@ class IndeksPetaniController extends Controller return response()->json($data); } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php index 1279bc3..1524a58 100644 --- a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php +++ b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Web\Dashboard; use App\Enums\KeparahanSerangan; use App\Enums\PenyakitTanaman; +use App\Enums\PraktikBudidaya\KondisiPengelolaanAir; use App\Enums\PraktikBudidaya\PemberianPupuk; use App\Enums\SeranganHama; use App\Enums\SosialEkonomi\StatusKepemilikanLahanSosialEkonomi; @@ -13,12 +14,14 @@ use App\Models\Pertanian\Lahan; use App\Models\Pertanian\Petani; use App\Models\Pertanian\PraktikBudidaya; use App\Models\Pertanian\Produksi; +use App\Models\Pertanian\SurveyPanen; 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; +use App\Models\Wilayah\Provinsi; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; @@ -95,11 +98,180 @@ class IndikatorPertanianController extends Controller private function dashboardPayload(array $filters): array { return [ + 'overviewData' => $this->overviewData($filters), + 'landProfileData' => $this->landProfileData($filters), 'summaryData' => $this->summaryData($filters), 'chartData' => $this->chartData($filters), ]; } + private function overviewData(array $filters): array + { + $totalPetani = $this->applyPetaniFilters(Petani::query(), $filters)->count(); + $totalLahan = $this->applyLahanFilters(Lahan::query(), $filters)->count(); + $totalLuasLahan = (float) $this->applyLahanFilters(Lahan::has('petani'), $filters)->sum('luas_lahan'); + $jumlahDesa = $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('desa_kelurahan_id') + ->distinct('desa_kelurahan_id') + ->count('desa_kelurahan_id'); + $jumlahKecamatan = $this->applyLahanFilters(Lahan::query(), $filters) + ->leftJoin('master_desa_kelurahan as d', 'd.id', '=', 'map_lahan.desa_kelurahan_id') + ->whereNotNull('d.kecamatan_id') + ->distinct('d.kecamatan_id') + ->count('d.kecamatan_id'); + $totalProduksiKg = $this->totalProduksiKg($filters); + $rataRataProduktivitas = $totalLuasLahan > 0 ? $totalProduksiKg / $totalLuasLahan : 0; + $tanamanProduktif = $this->tanamanProduktifCount($filters); + $batchPanen = $this->batchPanenCount($filters); + + return [ + 'kpiCards' => [ + [ + 'value' => number_format($totalPetani, 0, ',', '.'), + 'label' => 'Jumlah Petani', + 'description' => 'Petani yang tercakup dalam filter aktif', + 'icon' => 'tabler-users', + 'variant' => 'primary', + ], + [ + 'value' => number_format($totalLahan, 0, ',', '.'), + 'label' => 'Jumlah Kebun/Lahan', + 'description' => 'Kebun atau lahan terdata', + 'icon' => 'tabler-trees', + 'variant' => 'success', + ], + [ + 'value' => number_format($totalLuasLahan, 2, ',', '.').' ha', + 'label' => 'Luas Lahan', + 'description' => 'Akumulasi luas lahan terdata', + 'icon' => 'tabler-ruler-measure', + 'variant' => 'warning', + ], + [ + 'value' => number_format($jumlahDesa, 0, ',', '.').' desa', + 'label' => 'Desa/Kecamatan', + 'description' => number_format($jumlahKecamatan, 0, ',', '.').' kecamatan tercakup', + 'icon' => 'tabler-map-pin', + 'variant' => 'info', + ], + [ + 'value' => number_format($totalProduksiKg, 0, ',', '.').' kg', + 'label' => 'Total Produksi', + 'description' => $this->productionSummaryDescription($filters), + 'icon' => 'tabler-wheat', + 'variant' => 'primary', + ], + [ + 'value' => number_format($rataRataProduktivitas, 0, ',', '.').' kg/ha', + 'label' => 'Produktivitas Rata-rata', + 'description' => 'Berdasarkan produksi dan luas lahan terdata', + 'icon' => 'tabler-chart-bar', + 'variant' => 'success', + ], + [ + 'value' => number_format($tanamanProduktif, 0, ',', '.'), + 'label' => 'Tanaman Produktif', + 'description' => 'Tanaman dengan kondisi baik', + 'icon' => 'tabler-plant-2', + 'variant' => 'warning', + ], + [ + 'value' => number_format($batchPanen, 0, ',', '.'), + 'label' => 'Batch Panen Tercatat', + 'description' => 'Catatan produksi dan survey panen', + 'icon' => 'tabler-basket', + 'variant' => 'info', + ], + ], + 'commodityFocus' => $this->commodityFocusData($filters), + 'map' => [ + 'features' => $this->farmMapFeatures($filters), + 'levels' => $this->mapLevelData($filters), + ], + ]; + } + + private function landProfileData(array $filters): array + { + $totalTanaman = (int) $this->applyLahanFilters(Lahan::query(), $filters)->sum('jumlah_tanaman'); + $rataRataUmurTanaman = (float) $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('umur_tanaman') + ->avg('umur_tanaman'); + $komoditasCount = (int) $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('komoditas_id') + ->distinct('komoditas_id') + ->count('komoditas_id'); + $statusLahanCount = (int) $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('status_kepemilikan') + ->distinct('status_kepemilikan') + ->count('status_kepemilikan'); + $tanamanPenaung = $this->shadowTreeSummary($filters); + $tanamanPendamping = $this->companionPlantSummary($filters); + $diversityAverage = $this->plantDiversityAverage($filters); + + return [ + 'conditionCards' => [ + [ + 'value' => number_format($komoditasCount, 0, ',', '.'), + 'label' => 'Luas Lahan per Komoditas', + 'description' => 'Komoditas dengan luas lahan terdata', + 'icon' => 'tabler-chart-treemap', + 'variant' => 'primary', + ], + [ + 'value' => number_format($totalTanaman, 0, ',', '.'), + 'label' => 'Jumlah Tanaman', + 'description' => 'Akumulasi jumlah tanaman pada lahan', + 'icon' => 'tabler-trees', + 'variant' => 'success', + ], + [ + 'value' => number_format($rataRataUmurTanaman, 1, ',', '.').' tahun', + 'label' => 'Umur Tanaman', + 'description' => 'Rata-rata umur tanaman terdata', + 'icon' => 'tabler-calendar-stats', + 'variant' => 'warning', + ], + [ + 'value' => number_format($statusLahanCount, 0, ',', '.'), + 'label' => 'Status Lahan', + 'description' => 'Jumlah kategori status kepemilikan lahan', + 'icon' => 'tabler-certificate', + 'variant' => 'info', + ], + ], + 'agroecologyItems' => [ + ['label' => 'Sumber Air Lahan', 'value' => $this->sourceWaterSummary($filters), 'status' => 'available'], + ['label' => 'Pengelolaan Air & Irigasi', 'value' => $this->waterManagementSummary($filters), 'status' => 'available'], + ['label' => 'Kebutuhan Air per Musim', 'value' => $this->seasonalWaterNeedSummary($filters), 'status' => 'available'], + ['label' => 'Praktik Konservasi Tanah', 'value' => $this->soilConservationSummary($filters), 'status' => 'available'], + ], + 'agroforestryCards' => [ + [ + 'value' => number_format($tanamanPenaung['total'], 0, ',', '.'), + 'label' => 'Jumlah Tanaman Penaung', + 'description' => $tanamanPenaung['types'].' jenis tanaman penaung', + 'icon' => 'tabler-leaf', + 'variant' => 'success', + ], + [ + 'value' => number_format($tanamanPendamping['types'], 0, ',', '.'), + 'label' => 'Jenis Tanaman Pendamping', + 'description' => number_format($tanamanPendamping['total'], 0, ',', '.').' entri tanaman pendamping', + 'icon' => 'tabler-flower', + 'variant' => 'warning', + ], + [ + 'value' => number_format(round($diversityAverage), 0, ',', '.'), + 'label' => 'Tingkat Campuran Tanaman', + 'description' => 'Rata-rata kombinasi tanaman utama, pendamping, dan penaung', + 'icon' => 'tabler-binary-tree', + 'variant' => 'primary', + ], + ], + ]; + } + private function summaryData(array $filters): array { $totalPetani = $this->applyPetaniFilters(Petani::query(), $filters)->count(); @@ -166,6 +338,10 @@ class IndikatorPertanianController extends Controller 'statusPanen' => $this->statusPanenChart($filters), 'surveyProduktivitasHa' => $this->surveyProduktivitasByUnitChart($filters, 'ha_tahun'), 'surveyProduktivitasPohon' => $this->surveyProduktivitasByUnitChart($filters, 'pohon_tahun'), + 'luasLahanPerKomoditas' => $this->luasLahanPerKomoditasChart($filters), + 'jumlahTanamanPerKomoditas' => $this->jumlahTanamanPerKomoditasChart($filters), + 'umurTanaman' => $this->umurTanamanChart($filters), + 'sumberAir' => $this->sumberAirChart($filters), ]; } @@ -355,6 +531,82 @@ class IndikatorPertanianController extends Controller ]; } + private function luasLahanPerKomoditasChart(array $filters): array + { + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'map_lahan.komoditas_id') + ->whereNotNull('map_lahan.luas_lahan') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('SUM(map_lahan.luas_lahan) as total') + ->groupBy('k.id', 'k.nama') + ->havingRaw('SUM(map_lahan.luas_lahan) > 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 jumlahTanamanPerKomoditasChart(array $filters): array + { + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'map_lahan.komoditas_id') + ->whereNotNull('map_lahan.jumlah_tanaman') + ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") + ->selectRaw('SUM(map_lahan.jumlah_tanaman) as total') + ->groupBy('k.id', 'k.nama') + ->havingRaw('SUM(map_lahan.jumlah_tanaman) > 0') + ->orderByDesc('total') + ->get(); + + return [ + 'labels' => $rows->pluck('label')->values()->all(), + 'series' => $rows->pluck('total')->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + + private function umurTanamanChart(array $filters): array + { + $bucketOrder = ['< 3 tahun', '3-7 tahun', '8-15 tahun', '> 15 tahun']; + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('umur_tanaman') + ->pluck('umur_tanaman') + ->map(function ($age) { + $age = (float) $age; + + return match (true) { + $age < 3 => '< 3 tahun', + $age <= 7 => '3-7 tahun', + $age <= 15 => '8-15 tahun', + default => '> 15 tahun', + }; + }) + ->countBy() + ->sortBy(fn ($value, $label) => array_search($label, $bucketOrder, true)); + + return [ + 'labels' => $rows->keys()->values()->all(), + 'series' => $rows->values()->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + + private function sumberAirChart(array $filters): array + { + $rows = $this->applyPraktikBudidayaFilters(PraktikBudidaya::query(), $filters) + ->get(['sumber_air']) + ->flatMap(fn (PraktikBudidaya $praktik) => $this->arrayValues($praktik->sumber_air)) + ->filter() + ->countBy() + ->sortDesc(); + + return [ + 'labels' => $rows->keys()->values()->all(), + 'series' => $rows->values()->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + private function kondisiTanamanChart(array $filters): array { $rows = $this->applyTanamanTableFilters(DB::table('map_tanaman'), $filters) @@ -572,6 +824,415 @@ class IndikatorPertanianController extends Controller ]; } + private function tanamanProduktifCount(array $filters): int + { + return (int) $this->applyTanamanTableFilters(DB::table('map_tanaman'), $filters) + ->whereNull('map_tanaman.deleted_at') + ->where('map_tanaman.kondisi_tanaman', 'baik') + ->count('map_tanaman.id'); + } + + private function batchPanenCount(array $filters): int + { + $produksiCount = $this->applyProduksiFilters(Produksi::query(), $filters)->count(); + $surveyPanenCount = $this->applySurveyPanenFilters(SurveyPanen::query(), $filters)->count(); + + return (int) $produksiCount + (int) $surveyPanenCount; + } + + private function productionSummaryDescription(array $filters): string + { + $chart = $this->produksiPerKomoditasChart($filters); + + if (empty($chart['series'])) { + return 'Belum ada produksi aktual per komoditas'; + } + + return collect($chart['labels']) + ->map(fn ($label, $index) => $label.': '.number_format((float) ($chart['series'][$index] ?? 0), 0, ',', '.').' kg') + ->take(3) + ->implode(' | '); + } + + private function commodityFocusData(array $filters): array + { + $focusCommodities = ['Kopi', 'Kakao', 'Vanili', 'Kemiri']; + $rows = $this->applyLahanFilters(Lahan::query(), $filters) + ->leftJoin('master_komoditas as k', 'k.id', '=', 'map_lahan.komoditas_id') + ->whereIn(DB::raw('LOWER(k.nama)'), collect($focusCommodities)->map(fn ($name) => strtolower($name))->all()) + ->selectRaw('k.nama as label') + ->selectRaw('COUNT(map_lahan.id) as total') + ->groupBy('k.nama') + ->get() + ->mapWithKeys(fn ($row) => [strtolower((string) $row->label) => (int) $row->total]); + + return collect($focusCommodities) + ->map(fn ($name) => [ + 'label' => $name, + 'total' => $rows[strtolower($name)] ?? 0, + ]) + ->values() + ->all(); + } + + private function farmMapFeatures(array $filters): array + { + return $this->applyLahanFilters( + Lahan::query()->with(['desaKelurahan.kecamatan', 'komoditas']), + $filters + ) + ->where(function ($query) { + $query + ->whereNotNull('lat') + ->orWhereNotNull('long') + ->orWhereNotNull('path'); + }) + ->limit(250) + ->get() + ->map(fn (Lahan $lahan) => [ + 'id' => $lahan->id, + 'name' => $lahan->nama, + 'commodity' => $lahan->komoditas?->nama ?? 'Belum ditentukan', + 'area' => (float) $lahan->luas_lahan, + 'village' => $lahan->desaKelurahan?->nama, + 'district' => $lahan->desaKelurahan?->kecamatan?->nama, + 'lat' => is_numeric($lahan->lat) ? (float) $lahan->lat : null, + 'lng' => is_numeric($lahan->long) ? (float) $lahan->long : null, + 'path' => is_array($lahan->path) ? $lahan->path : null, + ]) + ->values() + ->all(); + } + + private function mapLevelData(array $filters): array + { + $lahanSummaryByDesa = $this->applyLahanFilters(Lahan::query(), $filters) + ->whereNotNull('desa_kelurahan_id') + ->select('desa_kelurahan_id') + ->selectRaw('COUNT(*) as total_lahan') + ->selectRaw('COALESCE(SUM(luas_lahan), 0) as total_luas') + ->groupBy('desa_kelurahan_id') + ->get(); + + $desaIds = $lahanSummaryByDesa->pluck('desa_kelurahan_id')->filter()->unique()->values(); + + if ($filters['desa'] !== 'all') { + $desaIds->push($filters['desa']); + } + + $desaList = DesaKelurahan::query() + ->select('id', 'nama', 'path', 'kecamatan_id') + ->when($desaIds->isNotEmpty(), fn ($query) => $query->whereIn('id', $desaIds->unique()->values())) + ->with([ + 'kecamatan:id,nama,path,kabupaten_kota_id', + 'kecamatan.kabupatenKota:id,nama,path,provinsi_id', + 'kecamatan.kabupatenKota.provinsi:id,nama,path', + ]) + ->get() + ->keyBy('id'); + + $geoProvinsi = []; + $geoKabupaten = []; + $geoKecamatan = []; + $geoDesa = []; + $geoLahan = []; + + foreach ($lahanSummaryByDesa as $summary) { + $desa = $desaList->get($summary->desa_kelurahan_id); + $kec = $desa?->kecamatan; + $kab = $kec?->kabupatenKota; + $prov = $kab?->provinsi; + $totalLahan = (int) $summary->total_lahan; + $totalLuas = (float) $summary->total_luas; + + if ($prov && $prov->path) { + $this->accumulateGeoLevel($geoProvinsi, $prov->id, null, $prov->nama, $prov->path, $totalLahan, $totalLuas); + } + + if ($kab && $kab->path) { + $this->accumulateGeoLevel($geoKabupaten, $kab->id, $prov?->id, $kab->nama, $kab->path, $totalLahan, $totalLuas); + } + + if ($kec && $kec->path) { + $this->accumulateGeoLevel($geoKecamatan, $kec->id, $kab?->id, $kec->nama, $kec->path, $totalLahan, $totalLuas); + } + + if ($desa && $desa->path) { + $this->accumulateGeoLevel($geoDesa, $desa->id, $kec?->id, $desa->nama, $desa->path, $totalLahan, $totalLuas); + } + } + + $this->ensureSelectedRegionOnMap($filters, $geoProvinsi, $geoKabupaten, $geoKecamatan, $geoDesa); + + $mapLahan = $this->applyLahanFilters( + Lahan::query()->with([ + 'profile:id,nama', + 'petani:id,nama', + 'komoditas:id,nama', + 'tanaman:id,lahan_id,komoditas_id', + 'tanaman.komoditas:id,nama', + ]), + $filters + ) + ->whereNotNull('path') + ->orderByDesc('updated_at') + ->limit(500) + ->get(); + + foreach ($mapLahan as $lahan) { + if (! $this->hasMapPolygon($lahan->path)) { + continue; + } + + $tanaman = $lahan->tanaman + ->map(fn ($tanaman) => $tanaman->komoditas?->nama) + ->filter() + ->unique() + ->values(); + + if ($tanaman->isEmpty() && $lahan->komoditas?->nama) { + $tanaman = collect([$lahan->komoditas->nama]); + } + + $geoLahan[] = [ + 'id' => $lahan->id, + 'parent_id' => $lahan->desa_kelurahan_id, + 'polygon' => $lahan->path, + 'nama_petani' => $lahan->petani?->nama ?? $lahan->profile?->nama ?? 'N/A', + 'luas' => (float) $lahan->luas_lahan, + 'tanaman' => $tanaman, + ]; + } + + return [ + 'provinsi' => array_values($geoProvinsi), + 'kabupaten' => array_values($geoKabupaten), + 'kecamatan' => array_values($geoKecamatan), + 'desa' => array_values($geoDesa), + 'lahan' => $geoLahan, + ]; + } + + private function accumulateGeoLevel(array &$bucket, int|string $id, int|string|null $parentId, string $name, mixed $polygon, int $totalLahan, float $totalLuas): void + { + if (! isset($bucket[$id])) { + $bucket[$id] = [ + 'id' => $id, + 'parent_id' => $parentId, + 'nama' => $name, + 'polygon' => $polygon, + 'total_lahan' => 0, + 'total_luas' => 0, + ]; + } + + $bucket[$id]['total_lahan'] += $totalLahan; + $bucket[$id]['total_luas'] += $totalLuas; + } + + private function ensureSelectedRegionOnMap(array $filters, array &$geoProvinsi, array &$geoKabupaten, array &$geoKecamatan, array &$geoDesa): void + { + $kabupaten = $filters['kabupaten'] !== 'all' + ? KabupatenKota::query()->with('provinsi:id,nama,path')->find($filters['kabupaten']) + : null; + + if ($kabupaten && $kabupaten->path && ! isset($geoKabupaten[$kabupaten->id])) { + $this->accumulateGeoLevel($geoKabupaten, $kabupaten->id, $kabupaten->provinsi_id, $kabupaten->nama, $kabupaten->path, 0, 0); + } + + if ($kabupaten?->provinsi && $kabupaten->provinsi->path && ! isset($geoProvinsi[$kabupaten->provinsi->id])) { + $this->accumulateGeoLevel($geoProvinsi, $kabupaten->provinsi->id, null, $kabupaten->provinsi->nama, $kabupaten->provinsi->path, 0, 0); + } + + if ($filters['kecamatan'] !== 'all') { + $kecamatan = Kecamatan::query()->find($filters['kecamatan']); + + if ($kecamatan && $kecamatan->path && ! isset($geoKecamatan[$kecamatan->id])) { + $this->accumulateGeoLevel($geoKecamatan, $kecamatan->id, $kecamatan->kabupaten_kota_id, $kecamatan->nama, $kecamatan->path, 0, 0); + } + } + + if ($filters['desa'] !== 'all') { + $desa = DesaKelurahan::query()->find($filters['desa']); + + if ($desa && $desa->path && ! isset($geoDesa[$desa->id])) { + $this->accumulateGeoLevel($geoDesa, $desa->id, $desa->kecamatan_id, $desa->nama, $desa->path, 0, 0); + } + } + } + + private function hasMapPolygon(mixed $path): bool + { + if (is_array($path)) { + return ! empty($path); + } + + if (! is_string($path) || blank($path) || strtolower($path) === 'null') { + return false; + } + + $decoded = json_decode($path, true); + + return json_last_error() === JSON_ERROR_NONE && ! empty($decoded) && $decoded !== 'null'; + } + + private function shadowTreeSummary(array $filters): array + { + $items = $this->applyLahanFilters(Lahan::query(), $filters) + ->get(['tanaman_penaung']) + ->flatMap(fn (Lahan $lahan) => $this->arrayValues($lahan->tanaman_penaung)) + ->filter() + ->values(); + + return [ + 'total' => $items->count(), + 'types' => $items->unique(fn ($item) => strtolower((string) $item))->count(), + ]; + } + + private function companionPlantSummary(array $filters): array + { + $items = $this->applyLahanFilters(Lahan::query(), $filters) + ->get(['id', 'komoditas_lain']) + ->flatMap(fn (Lahan $lahan) => $this->arrayValues($lahan->komoditas_lain)) + ->filter() + ->values(); + + return [ + 'total' => $items->count(), + 'types' => $items->unique(fn ($item) => strtolower((string) $item))->count(), + ]; + } + + private function plantDiversityAverage(array $filters): float + { + $lahan = $this->applyLahanFilters(Lahan::query(), $filters) + ->get(['komoditas_id', 'komoditas_lain', 'tanaman_penaung']); + + if ($lahan->isEmpty()) { + return 0; + } + + return (float) $lahan->avg(function (Lahan $item) { + $total = $item->komoditas_id ? 1 : 0; + $total += count($this->arrayValues($item->komoditas_lain)); + $total += count($this->arrayValues($item->tanaman_penaung)); + + return $total; + }); + } + + private function sourceWaterSummary(array $filters): string + { + $chart = $this->sumberAirChart($filters); + + if (empty($chart['labels'])) { + return 'Belum ada data'; + } + + return collect($chart['labels']) + ->map(fn ($label, $index) => $label.' ('.number_format((int) ($chart['series'][$index] ?? 0), 0, ',', '.').')') + ->take(2) + ->implode(', '); + } + + private function waterManagementSummary(array $filters): string + { + $rows = $this->applyPraktikBudidayaFilters(PraktikBudidaya::query(), $filters) + ->whereNotNull('kondisi_pengelolaan_air') + ->pluck('kondisi_pengelolaan_air') + ->map(fn ($value) => $this->waterManagementShortLabel((int) $value)) + ->countBy() + ->sortDesc(); + + return $this->topCountSummary($rows); + } + + private function seasonalWaterNeedSummary(array $filters): string + { + $rows = $this->applyPraktikBudidayaFilters(PraktikBudidaya::query(), $filters) + ->whereNotNull('kebutuhan_air_permusim') + ->pluck('kebutuhan_air_permusim') + ->map(fn ($value) => $this->shortEnumLabel((string) $value)) + ->countBy() + ->sortDesc(); + + return $this->topCountSummary($rows); + } + + private function soilConservationSummary(array $filters): string + { + $rows = $this->applyPraktikBudidayaFilters(PraktikBudidaya::query(), $filters) + ->get(['kebiasaan_konservasi_tanah']) + ->flatMap(fn (PraktikBudidaya $praktik) => $this->arrayValues($praktik->kebiasaan_konservasi_tanah)) + ->filter() + ->countBy() + ->sortDesc(); + + return $this->topCountSummary($rows); + } + + private function soilConservationScoreSummary(array $filters): string + { + $average = $this->applyPraktikBudidayaFilters(PraktikBudidaya::query(), $filters) + ->whereNotNull('nilai_konservasi_tanah') + ->avg('nilai_konservasi_tanah'); + + if ($average === null) { + return 'Belum ada data'; + } + + return 'Rata-rata '.number_format((float) $average, 1, ',', '.'); + } + + private function topCountSummary($rows): string + { + if ($rows->isEmpty()) { + return 'Belum ada data'; + } + + return $rows + ->map(fn ($count, $label) => $label.' ('.number_format((int) $count, 0, ',', '.').')') + ->take(2) + ->implode(', '); + } + + private function waterManagementShortLabel(int $value): string + { + return match (KondisiPengelolaanAir::tryFrom($value)) { + KondisiPengelolaanAir::KURANG_TIDAK_ADA_UPAYA => 'Kurang, tanpa upaya', + KondisiPengelolaanAir::KURANG_TIDAK_SUDAH_BERUPAYA => 'Kurang, ada upaya', + KondisiPengelolaanAir::CUKUP_DARI_HUJAN => 'Cukup dari hujan', + KondisiPengelolaanAir::CUKUP_IRIGASI_PINJAM => 'Cukup, irigasi pinjam', + KondisiPengelolaanAir::CUKUP_IRIGASI_SENDIRI => 'Cukup, irigasi sendiri', + default => 'Belum ditentukan', + }; + } + + private function arrayValues(mixed $value): array + { + if (is_array($value)) { + return collect($value) + ->flatten() + ->filter(fn ($item) => filled($item)) + ->map(fn ($item) => is_scalar($item) ? (string) $item : json_encode($item)) + ->values() + ->all(); + } + + if (is_string($value) && filled($value) && strtolower($value) !== 'null') { + $decoded = json_decode($value, true); + + if (json_last_error() === JSON_ERROR_NONE) { + return $this->arrayValues($decoded); + } + + return [$value]; + } + + return []; + } + private function chartFromRows($rows, callable $labelResolver): array { return [ @@ -676,6 +1337,13 @@ class IndikatorPertanianController extends Controller ->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('komoditas_id', $filters['komoditas'])); } + private function applySurveyPanenFilters($query, array $filters) + { + return $query->whereHas('petani', function ($petani) use ($filters) { + $this->applyPetaniFilters($petani, $filters); + }); + } + private function applyTanamanTableFilters($query, array $filters) { return $query diff --git a/resources/views/dashboard/demografi-petani.blade.php b/resources/views/dashboard/demografi-petani.blade.php index d542d69..f97b83d 100644 --- a/resources/views/dashboard/demografi-petani.blade.php +++ b/resources/views/dashboard/demografi-petani.blade.php @@ -1,1339 +1,12 @@ @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
-- 0 - komoditas utama -
-Total Luas Lahan
-- rata-rata - - ha/petani -
-Rata-rata Indeks Kesiapan Adopsi
-- Segmentasi: - -
-Jumlah Desa Sasaran
-- 0 - kecamatan sasaran -
-untuk semua komoditas
-| - | Petani | -% | -
|---|
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 | -
|---|
untuk semua komoditas
-| Nama Petani | -Desa/Kelurahan | -Komoditas | -Luas Lahan (ha) | -Indeks Kesiapan Adopsi | -Segmen | -
|---|
- {{ $summary['label'] }} -
- -- - {{ $summary['description'] }} - -
-