diff --git a/app/Enums/PraktikBudidaya/FrekuensiPemangkasanPendamping.php b/app/Enums/PraktikBudidaya/FrekuensiPemangkasanPendamping.php index f6b87b7..ec52eb1 100644 --- a/app/Enums/PraktikBudidaya/FrekuensiPemangkasanPendamping.php +++ b/app/Enums/PraktikBudidaya/FrekuensiPemangkasanPendamping.php @@ -8,7 +8,7 @@ enum FrekuensiPemangkasanPendamping: string case TIDAK_RUTIN = 'Memangkas, tapi tidak rutin dan tidak tahu tekniknya'; case SATU_KALI_TAHUN = 'Memangkas 1 kali/tahun, tahu jenis tekniknya'; case DUA_KALI_TAHUN = 'Memangkas 2 kali/tahun, tahu jenis tekniknya'; - case LEBIH_DUA_KALI_TAHUN = 'Memangkas lebih dari 2 kali/tahun dengan teknik yang tepat dan pohon penaung juga dipangkas rutin'; + case LEBIH_DUA_KALI_TAHUN = 'Memangkas lebih dari 2 kali/tahun dengan teknik yang tepat, dan pohon penaung juga dipangkas rutin'; public function label(): string { @@ -17,7 +17,7 @@ enum FrekuensiPemangkasanPendamping: string self::TIDAK_RUTIN => 'Memangkas, tapi tidak rutin dan tidak tahu tekniknya', self::SATU_KALI_TAHUN => 'Memangkas 1 kali/tahun, tahu jenis tekniknya', self::DUA_KALI_TAHUN => 'Memangkas 2 kali/tahun, tahu jenis tekniknya', - self::LEBIH_DUA_KALI_TAHUN => 'Memangkas lebih dari 2 kali/tahun dengan teknik yang tepat dan pohon penaung juga dipangkas rutin', + self::LEBIH_DUA_KALI_TAHUN => 'Memangkas lebih dari 2 kali/tahun dengan teknik yang tepat, dan pohon penaung juga dipangkas rutin', }; } diff --git a/app/Enums/PraktikBudidaya/FrekuensiPemangkasanUtama.php b/app/Enums/PraktikBudidaya/FrekuensiPemangkasanUtama.php index 0444c65..e6430b1 100644 --- a/app/Enums/PraktikBudidaya/FrekuensiPemangkasanUtama.php +++ b/app/Enums/PraktikBudidaya/FrekuensiPemangkasanUtama.php @@ -17,7 +17,7 @@ enum FrekuensiPemangkasanUtama: int self::TIDAK_RUTIN => 'Memangkas, tapi tidak rutin dan tidak tahu tekniknya', self::SATU_KALI_TAHUN => 'Memangkas 1 kali/tahun, tahu jenis tekniknya', self::DUA_KALI_TAHUN => 'Memangkas 2 kali/tahun, tahu jenis tekniknya', - self::LEBIH_DUA_KALI_TAHUN => 'Memangkas lebih dari 2 kali/tahun dengan teknik yang tepat dan pohon penaung juga dipangkas rutin', + self::LEBIH_DUA_KALI_TAHUN => 'Memangkas lebih dari 2 kali/tahun dengan teknik yang tepat, dan pohon penaung juga dipangkas rutin', }; } diff --git a/app/Enums/PraktikBudidaya/MetodePenangananHamaPenyakit.php b/app/Enums/PraktikBudidaya/MetodePenangananHamaPenyakit.php index 9936527..ef8ffe4 100644 --- a/app/Enums/PraktikBudidaya/MetodePenangananHamaPenyakit.php +++ b/app/Enums/PraktikBudidaya/MetodePenangananHamaPenyakit.php @@ -16,8 +16,8 @@ enum MetodePenangananHamaPenyakit: int self::TIDAK_ADA => 'Tidak ada penanganan', self::CARA_TRADISIONAL => 'Cara tradisional (doa/ritual)', self::PESTISIDA_SANITASI => 'Pestisida atau sanitasi', - self::KOMBINASI => 'Kombinasi pestisada dan sanitasi', - self::PHT => 'Pengendalian hama terpadu(PHT)', + self::KOMBINASI => 'Kombinasi pestisida dan sanitasi', + self::PHT => 'Pengendalian hama terpadu (PHT)', }; } diff --git a/app/Http/Controllers/Web/Dashboard/SummaryController.php b/app/Http/Controllers/Web/Dashboard/SummaryController.php index c545f94..d374c51 100644 --- a/app/Http/Controllers/Web/Dashboard/SummaryController.php +++ b/app/Http/Controllers/Web/Dashboard/SummaryController.php @@ -5,8 +5,13 @@ namespace App\Http\Controllers\Web\Dashboard; use App\Enums\KeparahanSerangan; use App\Enums\KondisiTanaman; use App\Enums\PenyakitTanaman; +use App\Enums\PraktikBudidaya\FrekuensiPemangkasanUtama; +use App\Enums\PraktikBudidaya\FrekuensiSanitasiLahan; +use App\Enums\PraktikBudidaya\MetodePenangananHamaPenyakit; +use App\Enums\PraktikBudidaya\PemberianPupuk; use App\Enums\SeranganHama; use App\Http\Controllers\Controller; +use App\Models\Pertanian\Komoditas; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; @@ -67,6 +72,7 @@ class SummaryController extends Controller ->get([ 'id', 'lahan_id', + 'komoditas_id', 'kondisi_tanaman', 'umur_tanaman', 'serangan_hama', @@ -87,49 +93,189 @@ class SummaryController extends Controller $landMetrics = $this->karakteristikLandMetrics($request); $totalLuasLahan = $landMetrics['total_luas_lahan']; - $petaniCount = $landMetrics['total_petani']; $avgLuasPerPetani = $landMetrics['ratarata_luas_lahan']; - $jumlahTanaman = $conditionSource->whereNotNull('kondisi_tanaman')->count(); + $productivityCards = $this->productivityKpiCards($lahanIds); + $praktikBudidaya = $this->filteredPraktikBudidaya($request); $kpiCards = [ [ 'value' => number_format($totalLuasLahan, 2, ',', '.'), - 'unit' => 'Ha', + 'unit' => 'ha', 'label' => 'Total Luas Lahan', - 'description' => 'Luas keseluruhan lahan terfilter', + 'description' => 'Seluruh lahan petani', 'icon' => 'tabler-chart-area-line', 'variant' => 'success', ], [ 'value' => number_format($avgLuasPerPetani, 2, ',', '.'), - 'unit' => 'Ha/petani', - 'label' => 'Rata-Rata Luas Lahan per Petani', - 'description' => number_format($petaniCount, 0, ',', '.').' petani terfilter', + 'unit' => 'ha', + 'label' => 'Rata-rata Luas Lahan', + 'description' => 'Rata-rata per petani', 'icon' => 'tabler-ruler-measure', 'variant' => 'danger', ], - [ - 'value' => number_format($jumlahTanaman, 0, ',', '.'), - 'unit' => 'tanaman', - 'label' => 'Jumlah Tanaman', - 'description' => 'Total tanaman pada chart kondisi tanaman', - 'icon' => 'tabler-plant-2', - 'variant' => 'secondary', - ], ]; + $kpiCards = array_merge($kpiCards, $productivityCards); return [ 'kpiCards' => $kpiCards, 'chartData' => [ - 'umurLahan' => $this->ageBucketChart($lahan, 'umur_lahan'), 'umurTanaman' => $this->ageBucketChart($healthSource, 'umur_tanaman'), + 'jumlahTanamanPerKomoditas' => $this->plantCountByCommodityChart($tanaman, $lahan), 'kondisiTanaman' => $this->attributeChart($conditionSource, 'kondisi_tanaman', fn ($value) => $this->conditionLabel($value)), 'keparahanSerangan' => $this->attributeChart($healthSource, 'keparahan_serangan', fn ($value) => $this->severityLabel($value)), 'gejalaSerangan' => $this->symptomChart($healthSource), + 'intensitasPemangkasan' => $this->enumOptionChart($praktikBudidaya, 'frekuensi_pemangkasan_utama', FrekuensiPemangkasanUtama::class), + 'intensitasPemupukan' => $this->enumOptionChart($praktikBudidaya, 'pemberian_pupuk', PemberianPupuk::class), + 'metodePenangananHamaPenyakit' => $this->enumOptionChart($praktikBudidaya, 'metode_penanganan_opt', MetodePenangananHamaPenyakit::class), + 'intensitasPembersihanLahan' => $this->enumOptionChart($praktikBudidaya, 'frekuensi_sanitasi_lahan', FrekuensiSanitasiLahan::class), + 'sumberAirKebun' => $this->arrayOptionChart( + $praktikBudidaya, + 'sumber_air', + ['Sungai/mata air', 'Sumur', 'Mengandalkan hujan saja', 'Lainnya'], + fn ($value) => in_array($value, ['Sungai/mata air', 'Sumur', 'Mengandalkan hujan saja'], true) ? $value : 'Lainnya', + ), + 'kebiasaanPraktikBaik' => $this->arrayOptionChart( + $praktikBudidaya, + 'kebiasaan_konservasi_tanah', + [ + 'Membuat pematang/tanggul tanah di lahan miring supaya tanah tidak longsor ke bawah', + 'Menumpuk daun kering/sisa tanaman di sekitar pohon', + 'Menanam tanaman lain di sela-sela komoditas utama untuk menutupi tanah', + 'Membuat lubang atau parit kecil untuk menampung air hujan', + 'Tidak ada yang seperti itu di kebun saya', + ], + fn ($value) => $value === 'Membuat pematang atau tanggul tanah di lahan miring supaya tanah tidak longsor ke bawah' + ? 'Membuat pematang/tanggul tanah di lahan miring supaya tanah tidak longsor ke bawah' + : $value, + ), ], ]; } + private function filteredPraktikBudidaya(Request $request) + { + $petaniIds = $this->filteredPetaniIdsQuery($request); + + return DB::table('praktik_budidaya') + ->whereNull('praktik_budidaya.deleted_at') + ->whereIn('praktik_budidaya.petani_id', $petaniIds) + ->get([ + 'frekuensi_pemangkasan_utama', + 'pemberian_pupuk', + 'metode_penanganan_opt', + 'frekuensi_sanitasi_lahan', + 'sumber_air', + 'kebiasaan_konservasi_tanah', + ]); + } + + private function plantCountByCommodityChart($tanaman, $lahan): array + { + $lahanKomoditas = $lahan + ->mapWithKeys(fn ($row) => [(int) $row->id => $row->komoditas_nama ?: 'Belum ditentukan']); + + $komoditasNames = DB::table('master_komoditas') + ->whereNull('deleted_at') + ->pluck('nama', 'id'); + + $counts = $tanaman + ->map(function ($row) use ($komoditasNames, $lahanKomoditas) { + if ($row->komoditas_id && $komoditasNames->has($row->komoditas_id)) { + return $komoditasNames[$row->komoditas_id]; + } + + return $lahanKomoditas[(int) $row->lahan_id] ?? 'Belum ditentukan'; + }) + ->filter() + ->countBy() + ->sortDesc(); + + return [ + 'labels' => $counts->keys()->values()->all(), + 'series' => $counts->values()->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + + private function productivityKpiCards($lahanIds): array + { + $komoditas = Komoditas::query() + ->where('is_utama', true) + ->orderBy('nama') + ->limit(4) + ->get(['id', 'nama']); + + $produksiRows = DB::table('produksi') + ->whereNull('produksi.deleted_at') + ->leftJoin('map_lahan as lahan_produksi', 'lahan_produksi.id', '=', 'produksi.lahan_id') + ->when($lahanIds->isNotEmpty(), fn ($query) => $query->whereIn('produksi.lahan_id', $lahanIds)) + ->when($lahanIds->isEmpty(), fn ($query) => $query->whereRaw('1 = 0')) + ->selectRaw('COALESCE(produksi.komoditas_id, lahan_produksi.komoditas_id) as komoditas_id') + ->addSelect([ + 'produksi.jumlah_panen', + 'produksi.satuan', + 'produksi.luas_panen', + 'produksi.produktivitas', + ]) + ->get() + ->groupBy('komoditas_id'); + + $variants = ['primary', 'warning', 'info', 'secondary']; + $icon = 'tabler-chart-bar'; + + return $komoditas + ->values() + ->map(function ($item, int $index) use ($produksiRows, $variants, $icon) { + $rows = $produksiRows->get($item->id, collect()); + $average = $this->averageProductivity($rows); + + return [ + 'value' => number_format($average, 0, ',', '.'), + 'unit' => 'kg/ha', + 'label' => 'Produktivitas Rata-rata '.$item->nama, + 'description' => 'Rata-rata produktivitas per komoditas', + 'icon' => $icon, + 'variant' => $variants[$index % count($variants)], + ]; + }) + ->all(); + } + + private function averageProductivity($rows): float + { + if ($rows->isEmpty()) { + return 0; + } + + $storedAverage = $rows + ->pluck('produktivitas') + ->filter(fn ($value) => (float) $value > 0) + ->avg(); + + if ($storedAverage > 0) { + return round((float) $storedAverage, 2); + } + + $totalProduksiKg = $rows->sum(fn ($row) => $this->toKilograms( + (float) ($row->jumlah_panen ?? 0), + (string) ($row->satuan ?? 'kg') + )); + $totalLuasPanen = $rows->sum(fn ($row) => (float) ($row->luas_panen ?? 0)); + + return $totalLuasPanen > 0 + ? round($totalProduksiKg / $totalLuasPanen, 2) + : 0; + } + + private function toKilograms(float $value, string $unit): float + { + return match (strtolower($unit)) { + 'ton' => $value * 1000, + 'kuintal', 'kwintal' => $value * 100, + default => $value, + }; + } + private function filteredLahanQuery(Request $request) { return DB::table('map_lahan') @@ -271,6 +417,48 @@ class SummaryController extends Controller ]; } + private function enumOptionChart($rows, string $field, string $enumClass): array + { + $options = collect($enumClass::options()) + ->mapWithKeys(fn ($option) => [(string) $option['value'] => $option['label']]); + + $counts = $rows + ->pluck($field) + ->filter(fn ($value) => $value !== null && $value !== '') + ->map(fn ($value) => (string) $value) + ->countBy(); + + return [ + 'labels' => $options->values()->all(), + 'series' => $options->keys()->map(fn ($value) => (int) ($counts[$value] ?? 0))->values()->all(), + ]; + } + + private function arrayOptionChart($rows, string $field, array $labels, ?callable $normalizer = null): array + { + $counts = collect($labels)->mapWithKeys(fn ($label) => [$label => 0]); + + foreach ($rows as $row) { + foreach ($this->arrayValues($row->{$field} ?? null) as $value) { + $label = $normalizer ? $normalizer($value) : $value; + if ($label === null || $label === '') { + continue; + } + + if (!$counts->has($label)) { + $counts[$label] = 0; + } + + $counts[$label] = (int) $counts[$label] + 1; + } + } + + return [ + 'labels' => $counts->keys()->values()->all(), + 'series' => $counts->values()->map(fn ($value) => (int) $value)->values()->all(), + ]; + } + private function symptomChart($rows): array { $counts = collect(); diff --git a/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php b/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php index f35b373..6ce9279 100644 --- a/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php @@ -489,34 +489,34 @@ class SurveyPetaniController extends Controller { return [ [ - 'color' => '#28a745', - 'bg' => 'rgba(40,167,69,.15)', - 'tx' => '#28a745', + 'color' => '#6FD68F', + 'bg' => 'rgba(111,214,143,.24)', + 'tx' => '#6FD68F', ], [ - 'color' => '#007bff', - 'bg' => 'rgba(0,123,255,.15)', - 'tx' => '#007bff', + 'color' => '#5FC7D6', + 'bg' => 'rgba(95,199,214,.24)', + 'tx' => '#5FC7D6', ], [ - 'color' => '#fd7e14', - 'bg' => 'rgba(253,126,20,.15)', - 'tx' => '#fd7e14', + 'color' => '#FFB46F', + 'bg' => 'rgba(255,180,111,.26)', + 'tx' => '#FFB46F', ], [ - 'color' => '#dc3545', - 'bg' => 'rgba(220,53,69,.15)', - 'tx' => '#dc3545', + 'color' => '#F47C86', + 'bg' => 'rgba(244,124,134,.26)', + 'tx' => '#F47C86', ], [ - 'color' => '#6f42c1', - 'bg' => 'rgba(111,66,193,.15)', - 'tx' => '#6f42c1', + 'color' => '#9D8EF0', + 'bg' => 'rgba(157,142,240,.26)', + 'tx' => '#9D8EF0', ], [ - 'color' => '#20c997', - 'bg' => 'rgba(32,201,151,.15)', - 'tx' => '#20c997', + 'color' => '#65D8BD', + 'bg' => 'rgba(101,216,189,.26)', + 'tx' => '#65D8BD', ], ]; } diff --git a/public/assets/js/config.js b/public/assets/js/config.js index 47b3dd9..128fc68 100644 --- a/public/assets/js/config.js +++ b/public/assets/js/config.js @@ -37,6 +37,46 @@ window.config = { danger: window.Helpers.getCssVar('danger-bg-subtle'), dark: window.Helpers.getCssVar('dark-bg-subtle') }, + chartColors: { + series: ['#9D8EF0', '#6FD68F', '#FFB46F', '#5FC7D6', '#F47C86', '#9EA6B0', '#65D8BD', '#63C7E0'], + semantic: { + primary: '#9D8EF0', + secondary: '#9EA6B0', + success: '#6FD68F', + info: '#5FC7D6', + warning: '#FFB46F', + danger: '#F47C86', + purple: '#9D8EF0', + teal: '#65D8BD', + pink: '#F47C86', + gray: '#9EA6B0' + }, + text: { + primary: '#7367F0', + secondary: '#808390', + success: '#28C76F', + info: '#00BAD1', + warning: '#FF9F43', + danger: '#FF4C51', + purple: '#7367F0', + teal: '#20C997', + pink: '#FF4C51', + gray: '#808390' + }, + categories: { + coffee: '#6FD68F', + vanilla: '#FFB46F', + cacao: '#9D8EF0', + candlenut: '#9EA6B0', + shade: '#65D8BD', + policyPurple: '#9D8EF0', + policyPink: '#F47C86', + marketGreen: '#6FD68F', + marketRed: '#F47C86', + marketBlue: '#5FC7D6' + }, + grid: '#ECF0F6' + }, fontFamily: window.Helpers.getCssVar('font-family-base'), enableMenuLocalStorage: true // Enable menu state with local storage support }; diff --git a/public/assets/js/dashboards-analytics.js b/public/assets/js/dashboards-analytics.js index fef9fad..40324e8 100644 --- a/public/assets/js/dashboards-analytics.js +++ b/public/assets/js/dashboards-analytics.js @@ -9,6 +9,9 @@ cardColor = config.colors.cardColor; labelColor = config.colors.textMuted; headingColor = config.colors.headingColor; + const pastelChart = config.chartColors || {}; + const pastelSemantic = pastelChart.semantic || {}; + const pastelSeries = pastelChart.series || ['#9D8EF0', '#6FD68F', '#FFB46F', '#5FC7D6', '#F47C86', '#9EA6B0', '#65D8BD', '#63C7E0']; // swiper loop and autoplay // -------------------------------------------------------------------- @@ -48,16 +51,10 @@ grid: { show: false }, - colors: [config.colors.success], + colors: [pastelSemantic.success || '#6FD68F'], fill: { - type: 'gradient', - gradient: { - shadeIntensity: 1, - opacityFrom: 0.4, - gradientToColors: [config.colors.cardColor], - opacityTo: 0.1, - stops: [0, 100] - } + type: 'solid', + opacity: 0.22 }, dataLabels: { enabled: false @@ -151,13 +148,13 @@ } }, colors: [ - config.colors_label.primary, - config.colors_label.primary, - config.colors_label.primary, - config.colors_label.primary, - config.colors.primary, - config.colors_label.primary, - config.colors_label.primary + pastelSemantic.secondary || '#9EA6B0', + pastelSemantic.secondary || '#9EA6B0', + pastelSemantic.secondary || '#9EA6B0', + pastelSemantic.secondary || '#9EA6B0', + pastelSemantic.primary || '#9D8EF0', + pastelSemantic.secondary || '#9EA6B0', + pastelSemantic.secondary || '#9EA6B0' ], dataLabels: { enabled: false @@ -262,18 +259,10 @@ } } }, - colors: [config.colors.primary], + colors: [pastelSemantic.primary || '#9D8EF0'], fill: { - type: 'gradient', - gradient: { - shade: 'dark', - shadeIntensity: 0.5, - gradientToColors: [config.colors.primary], - inverseColors: true, - opacityFrom: 1, - opacityTo: 0.6, - stops: [30, 70, 100] - } + type: 'solid', + opacity: 0.9 }, stroke: { dashArray: 10 @@ -356,7 +345,10 @@ } }, - colors: [config.colors.primary, config.colors.secondary], + colors: [ + pastelSeries[0] || '#9D8EF0', + pastelSeries[1] || '#6FD68F' + ], dataLabels: { enabled: false }, @@ -369,7 +361,10 @@ legend: { show: false }, - colors: [config.colors.primary, config.colors.secondary], + colors: [ + pastelSeries[0] || '#9D8EF0', + pastelSeries[1] || '#6FD68F' + ], fill: { opacity: 1 }, diff --git a/resources/views/dashboard/akselerasi.blade.php b/resources/views/dashboard/akselerasi.blade.php index e89e489..9919495 100644 --- a/resources/views/dashboard/akselerasi.blade.php +++ b/resources/views/dashboard/akselerasi.blade.php @@ -238,6 +238,10 @@ @push('scripts') -@endpush \ No newline at end of file +@endpush diff --git a/resources/views/dashboard/dashboard.blade.php b/resources/views/dashboard/dashboard.blade.php index a2b2f91..639956e 100644 --- a/resources/views/dashboard/dashboard.blade.php +++ b/resources/views/dashboard/dashboard.blade.php @@ -7,9 +7,9 @@ transition: transform .2s ease; } .tk-stat:hover { transform: translateX(4px); } - .tk-stat.green { border-left-color: #28a745; } - .tk-stat.blue { border-left-color: #007bff; } - .tk-stat.amber { border-left-color: #fd7e14; } + .tk-stat.green { border-left-color: #6FD68F; } + .tk-stat.blue { border-left-color: #5FC7D6; } + .tk-stat.amber { border-left-color: #FFB46F; } .tk-stat-lbl { font-size: 10px; text-transform: uppercase; @@ -88,38 +88,38 @@ 'new_month' => 12, 'enumerators' => [ - ['name'=>'Enumerator Ngada 1','done'=>72,'target'=>80,'color'=>'#28a745','bg'=>'rgba(40,167,69,.15)','tx'=>'#28a745'], - ['name'=>'Enumerator Ngada 2','done'=>58,'target'=>80,'color'=>'#007bff','bg'=>'rgba(0,123,255,.15)','tx'=>'#007bff'], - ['name'=>'Enumerator Ngada 3','done'=>48,'target'=>80,'color'=>'#fd7e14','bg'=>'rgba(253,126,20,.15)','tx'=>'#fd7e14'], - ['name'=>'Enumerator Ngada 4','done'=>36,'target'=>80,'color'=>'#dc3545','bg'=>'rgba(220,53,69,.15)','tx'=>'#dc3545'], + ['name'=>'Enumerator Ngada 1','done'=>72,'target'=>80,'color'=>'#6FD68F','bg'=>'rgba(111,214,143,.24)','tx'=>'#6FD68F'], + ['name'=>'Enumerator Ngada 2','done'=>58,'target'=>80,'color'=>'#5FC7D6','bg'=>'rgba(95,199,214,.24)','tx'=>'#5FC7D6'], + ['name'=>'Enumerator Ngada 3','done'=>48,'target'=>80,'color'=>'#FFB46F','bg'=>'rgba(255,180,111,.26)','tx'=>'#FFB46F'], + ['name'=>'Enumerator Ngada 4','done'=>36,'target'=>80,'color'=>'#F47C86','bg'=>'rgba(244,124,134,.26)','tx'=>'#F47C86'], ], 'recent' => [ - ['code'=>'TKD-2026-0178','name'=>'Markus Bela', 'init'=>'MB','desa'=>'Wangka', 'date'=>'24 Jun 2026','pct'=>100,'status'=>'completed', 'bg'=>'rgba(40,167,69,.15)','tx'=>'#28a745'], - ['code'=>'TKD-2026-0177','name'=>'Theresia Nuka','init'=>'TN','desa'=>'Langa', 'date'=>'23 Jun 2026','pct'=>67, 'status'=>'in_progress','bg'=>'rgba(0,123,255,.15)','tx'=>'#007bff'], - ['code'=>'TKD-2026-0176','name'=>'Yosef Meo', 'init'=>'YM','desa'=>'Bobo', 'date'=>'22 Jun 2026','pct'=>100,'status'=>'completed', 'bg'=>'rgba(40,167,69,.15)','tx'=>'#28a745'], - ['code'=>'TKD-2026-0175','name'=>'Maria Seda', 'init'=>'MS','desa'=>'Tana Wolo','date'=>'21 Jun 2026','pct'=>22, 'status'=>'draft', 'bg'=>'rgba(253,126,20,.15)','tx'=>'#fd7e14'], - ['code'=>'TKD-2026-0174','name'=>'Rafael Bolo', 'init'=>'RB','desa'=>'Wangka', 'date'=>'20 Jun 2026','pct'=>11, 'status'=>'draft', 'bg'=>'rgba(220,53,69,.15)','tx'=>'#dc3545'], + ['code'=>'TKD-2026-0178','name'=>'Markus Bela', 'init'=>'MB','desa'=>'Wangka', 'date'=>'24 Jun 2026','pct'=>100,'status'=>'completed', 'bg'=>'rgba(111,214,143,.24)','tx'=>'#6FD68F'], + ['code'=>'TKD-2026-0177','name'=>'Theresia Nuka','init'=>'TN','desa'=>'Langa', 'date'=>'23 Jun 2026','pct'=>67, 'status'=>'in_progress','bg'=>'rgba(95,199,214,.24)','tx'=>'#5FC7D6'], + ['code'=>'TKD-2026-0176','name'=>'Yosef Meo', 'init'=>'YM','desa'=>'Bobo', 'date'=>'22 Jun 2026','pct'=>100,'status'=>'completed', 'bg'=>'rgba(111,214,143,.24)','tx'=>'#6FD68F'], + ['code'=>'TKD-2026-0175','name'=>'Maria Seda', 'init'=>'MS','desa'=>'Tana Wolo','date'=>'21 Jun 2026','pct'=>22, 'status'=>'draft', 'bg'=>'rgba(255,180,111,.26)','tx'=>'#FFB46F'], + ['code'=>'TKD-2026-0174','name'=>'Rafael Bolo', 'init'=>'RB','desa'=>'Wangka', 'date'=>'20 Jun 2026','pct'=>11, 'status'=>'draft', 'bg'=>'rgba(244,124,134,.26)','tx'=>'#F47C86'], ], 'komoditas' => [ - ['label'=>'Kopi', 'total'=>148,'pct'=>60,'color'=>'#28a745','arc'=>174], - ['label'=>'Kakao', 'total'=>82, 'pct'=>33,'color'=>'#007bff','arc'=>96], - ['label'=>'Vanili','total'=>33, 'pct'=>13,'color'=>'#fd7e14','arc'=>38], - ['label'=>'Kemiri','total'=>22, 'pct'=>9, 'color'=>'#6f42c1','arc'=>26], + ['label'=>'Kopi', 'total'=>148,'pct'=>60,'color'=>'#6FD68F','arc'=>174], + ['label'=>'Kakao', 'total'=>82, 'pct'=>33,'color'=>'#9D8EF0','arc'=>96], + ['label'=>'Vanili','total'=>33, 'pct'=>13,'color'=>'#FFB46F','arc'=>38], + ['label'=>'Kemiri','total'=>22, 'pct'=>9, 'color'=>'#9EA6B0','arc'=>26], ], 'kecamatan' => [ - ['name'=>'Bajawa','total'=>89,'pct'=>78,'color'=>'#28a745'], - ['name'=>'Soa', 'total'=>68,'pct'=>59,'color'=>'#007bff'], - ['name'=>'Golewa','total'=>57,'pct'=>50,'color'=>'#fd7e14'], + ['name'=>'Bajawa','total'=>89,'pct'=>78,'color'=>'#6FD68F'], + ['name'=>'Soa', 'total'=>68,'pct'=>59,'color'=>'#5FC7D6'], + ['name'=>'Golewa','total'=>57,'pct'=>50,'color'=>'#FFB46F'], ], 'pending' => [ - ['name'=>'Theresia Nuka','section'=>'D4-K3','pct'=>67,'bg'=>'rgba(0,123,255,.15)','tx'=>'#007bff'], - ['name'=>'Maria Seda', 'section'=>'D2-K2','pct'=>22,'bg'=>'rgba(253,126,20,.15)','tx'=>'#fd7e14'], - ['name'=>'Rafael Bolo', 'section'=>'D2-K1','pct'=>11,'bg'=>'rgba(220,53,69,.15)', 'tx'=>'#dc3545'], - ['name'=>'Antonius Wea', 'section'=>'D2-K1','pct'=>0, 'bg'=>'rgba(220,53,69,.15)', 'tx'=>'#dc3545'], + ['name'=>'Theresia Nuka','section'=>'D4-K3','pct'=>67,'bg'=>'rgba(95,199,214,.24)','tx'=>'#5FC7D6'], + ['name'=>'Maria Seda', 'section'=>'D2-K2','pct'=>22,'bg'=>'rgba(255,180,111,.26)','tx'=>'#FFB46F'], + ['name'=>'Rafael Bolo', 'section'=>'D2-K1','pct'=>11,'bg'=>'rgba(244,124,134,.26)', 'tx'=>'#F47C86'], + ['name'=>'Antonius Wea', 'section'=>'D2-K1','pct'=>0, 'bg'=>'rgba(244,124,134,.26)', 'tx'=>'#F47C86'], ], 'pending_more' => 32, ]; @@ -258,10 +258,10 @@ @foreach($d['recent'] as $s) @php $bc = match(true) { - $s['pct'] === 100 => '#28a745', - $s['pct'] >= 50 => '#007bff', - $s['pct'] >= 20 => '#fd7e14', - default => '#dc3545', + $s['pct'] === 100 => '#6FD68F', + $s['pct'] >= 50 => '#5FC7D6', + $s['pct'] >= 20 => '#FFB46F', + default => '#F47C86', }; @endphp
Komposisi petani berdasarkan gender, kelompok umur, dan pendidikan.
Tanggungan keluarga, penghasilan usaha tani, dan keanggotaan kelompok tani.
Karakteristik lahan usaha tani berdasarkan komoditas utama, luas lahan garapan, dan status kepemilikan lahan.
Komposisi petani menurut tingkat kesiapan adopsi, secara keseluruhan dan pada setiap komoditas.
Perbandingan skor dimensi dan komponen kesiapan adopsi petani.
Peta dan komposisi segmen kesiapan adopsi petani per desa/kelurahan.