solve dashboard indikator pertanian

This commit is contained in:
2026-08-13 16:31:11 +07:00
parent 6830142a82
commit b96de514e3
2 changed files with 157 additions and 55 deletions
@@ -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([
@@ -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"]')