diff --git a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php index bb9bfca..2ee1f22 100644 --- a/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php +++ b/app/Http/Controllers/Web/Dashboard/IndikatorPertanianController.php @@ -26,7 +26,8 @@ class IndikatorPertanianController extends Controller { public function index(Request $request) { - $initialFilters = $this->selectedFilters($request, $this->defaultKabupatenId()); + $defaultKabupatenId = $this->defaultKabupatenId(); + $initialFilters = $this->selectedFilters($request, $defaultKabupatenId); $payload = $this->dashboardPayload($initialFilters); $filterOptions = [ @@ -40,22 +41,22 @@ class IndikatorPertanianController extends Controller [ 'key' => 'kecamatan', 'label' => 'Kecamatan', - 'options' => $this->kecamatanOptions(), + 'options' => $this->withAllOption('Semua Kecamatan', []), ], [ 'key' => 'desa', 'label' => 'Desa', - 'options' => $this->desaOptions(), + 'options' => $this->withAllOption('Semua Desa', []), ], [ 'key' => 'komoditas', 'label' => 'Komoditas', - 'options' => $this->komoditasOptions(), + 'options' => $this->withAllOption('Semua Komoditas', []), ], [ 'key' => 'segmentasi', 'label' => 'Segmentasi', - 'options' => $this->segmentasiOptions(), + 'options' => $this->withAllOption('Semua Segmentasi', []), ], ]; @@ -68,6 +69,13 @@ class IndikatorPertanianController extends Controller public function data(Request $request) { + if ($request->query('mode') === 'filter-options') { + return response()->json([ + 'komoditas' => $this->komoditasOptions(), + 'segmentasi' => $this->segmentasiOptions(), + ]); + } + $filters = $this->selectedFilters($request, $this->defaultKabupatenId()); return response()->json([ diff --git a/resources/views/dashboard/indikator-pertanian.blade.php b/resources/views/dashboard/indikator-pertanian.blade.php index cc3048c..cda6791 100644 --- a/resources/views/dashboard/indikator-pertanian.blade.php +++ b/resources/views/dashboard/indikator-pertanian.blade.php @@ -660,21 +660,19 @@ let chartData = @json($chartData); const dashboardUrl = @json(route('dashboard.indikator-pertanian')); const dashboardDataUrl = @json(route('dashboard.indikator-pertanian.data')); + const filterOptionsUrl = `${dashboardDataUrl}?mode=filter-options`; + const kecamatanUrlBase = @json(url('/kecamatanbykabupatenkota')); + const desaUrlBase = @json(url('/desakelurahanbykecamatan')); const initialFilters = @json($initialFilters); const filters = { ...initialFilters }; const filterSelects = document.querySelectorAll('.indicator-filter-select'); const filterBar = document.getElementById('indicator-filter-bar'); + const kabupatenFilter = document.querySelector('[data-filter-key="kabupaten"]'); const kecamatanSelect = document.querySelector('[data-filter-key="kecamatan"]'); const desaSelect = document.querySelector('[data-filter-key="desa"]'); - const desaOptions = desaSelect - ? Array.from(desaSelect.options).map(function (option) { - return { - value: option.value, - label: option.textContent, - parent: option.dataset.parent || null, - }; - }) - : []; + const komoditasSelect = document.querySelector('[data-filter-key="komoditas"]'); + const segmentasiSelect = document.querySelector('[data-filter-key="segmentasi"]'); + const selectedKabupaten = kabupatenFilter?.dataset.filterValue || initialFilters.kabupaten || 'all'; const resetButton = document.getElementById('indicator-reset-filter'); const exportButton = document.getElementById('indicator-export-data'); const chartInstances = {}; @@ -724,6 +722,132 @@ } } + async function fetchJson(url) { + const response = await fetch(url, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + }, + }); + + if (!response.ok) { + throw new Error(`HTTP Error ${response.status}`); + } + + return response.json(); + } + + function normalizeOptions(items, allLabel) { + return [ + { value: 'all', label: allLabel }, + ...items + .filter(function (item) { + return String(item.value ?? item.id ?? '') !== 'all'; + }) + .map(function (item) { + return { + value: String(item.value ?? item.id), + label: item.label ?? item.nama ?? '-', + }; + }), + ]; + } + + function setSelectOptions(select, options, selectedValue) { + if (!select) { + return; + } + + select.innerHTML = ''; + + options.forEach(function (option) { + select.add(new Option(option.label, option.value)); + }); + + select.value = options.some(function (option) { + return option.value === selectedValue; + }) ? selectedValue : 'all'; + } + + async function loadKecamatanOptions(selectedValue = filters.kecamatan) { + if (!kecamatanSelect || selectedKabupaten === 'all') { + return; + } + + kecamatanSelect.disabled = true; + + try { + const data = await fetchJson(`${kecamatanUrlBase}/${selectedKabupaten}`); + const options = normalizeOptions(data, 'Semua Kecamatan'); + + setSelectOptions(kecamatanSelect, options, selectedValue); + filters.kecamatan = kecamatanSelect.value; + } catch (error) { + console.error('Gagal memuat kecamatan:', error); + } finally { + kecamatanSelect.disabled = false; + } + } + + async function loadDesaOptions(selectedValue = filters.desa) { + if (!desaSelect) { + return; + } + + if (!filters.kecamatan || filters.kecamatan === 'all') { + setSelectOptions(desaSelect, normalizeOptions([], 'Semua Desa'), 'all'); + desaSelect.disabled = true; + filters.desa = 'all'; + return; + } + + desaSelect.disabled = true; + + try { + const data = await fetchJson(`${desaUrlBase}/${filters.kecamatan}`); + const options = normalizeOptions(data, 'Semua Desa'); + + setSelectOptions(desaSelect, options, selectedValue); + filters.desa = desaSelect.value; + } catch (error) { + console.error('Gagal memuat desa:', error); + } finally { + desaSelect.disabled = false; + } + } + + async function loadDashboardFilterOptions() { + try { + const data = await fetchJson(filterOptionsUrl); + + setSelectOptions( + komoditasSelect, + normalizeOptions(data.komoditas || [], 'Semua Komoditas'), + filters.komoditas + ); + filters.komoditas = komoditasSelect?.value || 'all'; + + setSelectOptions( + segmentasiSelect, + normalizeOptions(data.segmentasi || [], 'Semua Segmentasi'), + filters.segmentasi + ); + filters.segmentasi = segmentasiSelect?.value || 'all'; + } catch (error) { + console.error('Gagal memuat opsi filter indikator:', error); + } + } + + async function loadInitialFilterOptions() { + await Promise.all([ + loadKecamatanOptions(filters.kecamatan), + loadDashboardFilterOptions(), + ]); + + await loadDesaOptions(filters.desa); + } + function updateSummaryCards(summaryData) { document.querySelectorAll('[data-summary-card]').forEach(function (card) { const summary = summaryData[Number(card.dataset.summaryCard)]; @@ -783,12 +907,10 @@ kecamatanSelect.value = filters.kecamatan; } - renderDesaOptions(filters.desa); - filterSelects.forEach(function (select) { const key = select.dataset.filterKey; - if (key !== 'desa' && filters[key] !== undefined) { + if (filters[key] !== undefined) { select.value = filters[key]; } }); @@ -826,51 +948,22 @@ } } - function renderDesaOptions(selectedValue = initialFilters.desa) { - if (!desaSelect || !kecamatanSelect) { - return; - } - - const selectedKecamatan = kecamatanSelect.value; - const canSelectDesa = selectedKecamatan !== 'all'; - const availableOptions = desaOptions.filter(function (option) { - return option.value === 'all' || option.parent === selectedKecamatan; - }); - - desaSelect.innerHTML = ''; - - availableOptions.forEach(function (option) { - const element = new Option(option.label, option.value); - - if (option.parent) { - element.dataset.parent = option.parent; - } - - desaSelect.add(element); - }); - - desaSelect.disabled = !canSelectDesa; - desaSelect.value = availableOptions.some(function (option) { - return option.value === selectedValue; - }) ? selectedValue : 'all'; - filters.desa = desaSelect.value; - } - - renderDesaOptions(); - filterSelects.forEach(function (select) { - select.addEventListener('change', function (event) { - filters[event.target.dataset.filterKey] = event.target.value; + select.addEventListener('change', async function (event) { + const key = event.target.dataset.filterKey; - if (event.target.dataset.filterKey === 'kecamatan') { - renderDesaOptions('all'); + filters[key] = event.target.value; + + if (key === 'kecamatan') { + filters.desa = 'all'; + await loadDesaOptions('all'); } loadIndicatorData(); }); }); - resetButton?.addEventListener('click', function () { + resetButton?.addEventListener('click', async function () { Object.assign(filters, { kecamatan: 'all', desa: 'all', @@ -882,7 +975,7 @@ select.value = 'all'; }); - renderDesaOptions('all'); + await loadDesaOptions('all'); loadIndicatorData(); }); @@ -1498,6 +1591,7 @@ } renderLahanCharts(); + loadInitialFilterOptions(); document .querySelector('[data-bs-target="#indicator-tab-lahan-tanaman"]')