solve dashboard indikator pertanian
This commit is contained in:
@@ -26,7 +26,8 @@ class IndikatorPertanianController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$initialFilters = $this->selectedFilters($request, $this->defaultKabupatenId());
|
$defaultKabupatenId = $this->defaultKabupatenId();
|
||||||
|
$initialFilters = $this->selectedFilters($request, $defaultKabupatenId);
|
||||||
$payload = $this->dashboardPayload($initialFilters);
|
$payload = $this->dashboardPayload($initialFilters);
|
||||||
|
|
||||||
$filterOptions = [
|
$filterOptions = [
|
||||||
@@ -40,22 +41,22 @@ class IndikatorPertanianController extends Controller
|
|||||||
[
|
[
|
||||||
'key' => 'kecamatan',
|
'key' => 'kecamatan',
|
||||||
'label' => 'Kecamatan',
|
'label' => 'Kecamatan',
|
||||||
'options' => $this->kecamatanOptions(),
|
'options' => $this->withAllOption('Semua Kecamatan', []),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'key' => 'desa',
|
'key' => 'desa',
|
||||||
'label' => 'Desa',
|
'label' => 'Desa',
|
||||||
'options' => $this->desaOptions(),
|
'options' => $this->withAllOption('Semua Desa', []),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'key' => 'komoditas',
|
'key' => 'komoditas',
|
||||||
'label' => 'Komoditas',
|
'label' => 'Komoditas',
|
||||||
'options' => $this->komoditasOptions(),
|
'options' => $this->withAllOption('Semua Komoditas', []),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'key' => 'segmentasi',
|
'key' => 'segmentasi',
|
||||||
'label' => 'Segmentasi',
|
'label' => 'Segmentasi',
|
||||||
'options' => $this->segmentasiOptions(),
|
'options' => $this->withAllOption('Semua Segmentasi', []),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -68,6 +69,13 @@ class IndikatorPertanianController extends Controller
|
|||||||
|
|
||||||
public function data(Request $request)
|
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());
|
$filters = $this->selectedFilters($request, $this->defaultKabupatenId());
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|||||||
@@ -660,21 +660,19 @@
|
|||||||
let chartData = @json($chartData);
|
let chartData = @json($chartData);
|
||||||
const dashboardUrl = @json(route('dashboard.indikator-pertanian'));
|
const dashboardUrl = @json(route('dashboard.indikator-pertanian'));
|
||||||
const dashboardDataUrl = @json(route('dashboard.indikator-pertanian.data'));
|
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 initialFilters = @json($initialFilters);
|
||||||
const filters = { ...initialFilters };
|
const filters = { ...initialFilters };
|
||||||
const filterSelects = document.querySelectorAll('.indicator-filter-select');
|
const filterSelects = document.querySelectorAll('.indicator-filter-select');
|
||||||
const filterBar = document.getElementById('indicator-filter-bar');
|
const filterBar = document.getElementById('indicator-filter-bar');
|
||||||
|
const kabupatenFilter = document.querySelector('[data-filter-key="kabupaten"]');
|
||||||
const kecamatanSelect = document.querySelector('[data-filter-key="kecamatan"]');
|
const kecamatanSelect = document.querySelector('[data-filter-key="kecamatan"]');
|
||||||
const desaSelect = document.querySelector('[data-filter-key="desa"]');
|
const desaSelect = document.querySelector('[data-filter-key="desa"]');
|
||||||
const desaOptions = desaSelect
|
const komoditasSelect = document.querySelector('[data-filter-key="komoditas"]');
|
||||||
? Array.from(desaSelect.options).map(function (option) {
|
const segmentasiSelect = document.querySelector('[data-filter-key="segmentasi"]');
|
||||||
return {
|
const selectedKabupaten = kabupatenFilter?.dataset.filterValue || initialFilters.kabupaten || 'all';
|
||||||
value: option.value,
|
|
||||||
label: option.textContent,
|
|
||||||
parent: option.dataset.parent || null,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
: [];
|
|
||||||
const resetButton = document.getElementById('indicator-reset-filter');
|
const resetButton = document.getElementById('indicator-reset-filter');
|
||||||
const exportButton = document.getElementById('indicator-export-data');
|
const exportButton = document.getElementById('indicator-export-data');
|
||||||
const chartInstances = {};
|
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) {
|
function updateSummaryCards(summaryData) {
|
||||||
document.querySelectorAll('[data-summary-card]').forEach(function (card) {
|
document.querySelectorAll('[data-summary-card]').forEach(function (card) {
|
||||||
const summary = summaryData[Number(card.dataset.summaryCard)];
|
const summary = summaryData[Number(card.dataset.summaryCard)];
|
||||||
@@ -783,12 +907,10 @@
|
|||||||
kecamatanSelect.value = filters.kecamatan;
|
kecamatanSelect.value = filters.kecamatan;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDesaOptions(filters.desa);
|
|
||||||
|
|
||||||
filterSelects.forEach(function (select) {
|
filterSelects.forEach(function (select) {
|
||||||
const key = select.dataset.filterKey;
|
const key = select.dataset.filterKey;
|
||||||
|
|
||||||
if (key !== 'desa' && filters[key] !== undefined) {
|
if (filters[key] !== undefined) {
|
||||||
select.value = filters[key];
|
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) {
|
filterSelects.forEach(function (select) {
|
||||||
select.addEventListener('change', function (event) {
|
select.addEventListener('change', async function (event) {
|
||||||
filters[event.target.dataset.filterKey] = event.target.value;
|
const key = event.target.dataset.filterKey;
|
||||||
|
|
||||||
if (event.target.dataset.filterKey === 'kecamatan') {
|
filters[key] = event.target.value;
|
||||||
renderDesaOptions('all');
|
|
||||||
|
if (key === 'kecamatan') {
|
||||||
|
filters.desa = 'all';
|
||||||
|
await loadDesaOptions('all');
|
||||||
}
|
}
|
||||||
|
|
||||||
loadIndicatorData();
|
loadIndicatorData();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
resetButton?.addEventListener('click', function () {
|
resetButton?.addEventListener('click', async function () {
|
||||||
Object.assign(filters, {
|
Object.assign(filters, {
|
||||||
kecamatan: 'all',
|
kecamatan: 'all',
|
||||||
desa: 'all',
|
desa: 'all',
|
||||||
@@ -882,7 +975,7 @@
|
|||||||
select.value = 'all';
|
select.value = 'all';
|
||||||
});
|
});
|
||||||
|
|
||||||
renderDesaOptions('all');
|
await loadDesaOptions('all');
|
||||||
loadIndicatorData();
|
loadIndicatorData();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1498,6 +1591,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderLahanCharts();
|
renderLahanCharts();
|
||||||
|
loadInitialFilterOptions();
|
||||||
|
|
||||||
document
|
document
|
||||||
.querySelector('[data-bs-target="#indicator-tab-lahan-tanaman"]')
|
.querySelector('[data-bs-target="#indicator-tab-lahan-tanaman"]')
|
||||||
|
|||||||
Reference in New Issue
Block a user