Update Koperasi

This commit is contained in:
2026-11-06 22:38:45 +07:00
parent 6232b28e11
commit cb36682d9e
79 changed files with 4639 additions and 1378 deletions
+33
View File
@@ -0,0 +1,33 @@
'use strict';
document.addEventListener('DOMContentLoaded', () => {
const page = document.querySelector('.koperasi-list-page');
if (!page) return;
page.querySelector('#koperasi-per-page').addEventListener('change', event => event.target.form.requestSubmit());
page.querySelectorAll('[data-koperasi-row]').forEach(row => {
row.addEventListener('click', event => {
if (event.target.closest('a, button, input, select, textarea, label, form')) return;
window.location.href = row.querySelector('.edit-record').href;
});
});
page.querySelectorAll('[data-koperasi-delete]').forEach(form => {
form.addEventListener('submit', event => {
event.preventDefault();
Swal.fire({
title: 'Hapus koperasi?',
text: `Data koperasi "${form.dataset.nama}" akan dihapus.`,
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Ya, hapus',
cancelButtonText: 'Batal',
customClass: { confirmButton: 'btn btn-danger me-3', cancelButton: 'btn btn-label-secondary' },
buttonsStyling: false
}).then(result => {
if (result.isConfirmed) form.submit();
});
});
});
});
+49
View File
@@ -0,0 +1,49 @@
'use strict';
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('[data-koperasi-wilayah], #koperasi-filter-form').forEach(container => {
const levels = ['provinsi', 'kabupaten', 'kecamatan', 'desa']
.map(name => ({ name, input: container.querySelector(`[data-wilayah-${name}]`) }))
.filter(level => level.input);
const controllers = new Map();
const updateRequired = () => {
if (!container.matches('[data-koperasi-wilayah]')) return;
const hasSelection = levels.some(level => level.input.value);
levels.forEach(level => { level.input.required = hasSelection; });
};
const reset = level => {
controllers.get(level.name)?.abort();
level.input.replaceChildren(new Option(level.input.options[0].textContent, ''));
level.input.disabled = true;
};
levels.forEach((level, index) => {
if (index === levels.length - 1) return;
level.input.addEventListener('change', async () => {
levels.slice(index + 1).forEach(reset);
updateRequired();
if (!level.input.value) return;
const child = levels[index + 1];
const controller = new AbortController();
controllers.set(child.name, controller);
const url = new URL(container.dataset[`${child.name}Url`].replace(':id', encodeURIComponent(level.input.value)), window.location.href);
url.searchParams.set('all_wilayah', '1');
try {
const response = await fetch(url, {
signal: controller.signal,
headers: { 'Accept': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '' }
});
if (!response.ok) throw new Error('Wilayah gagal dimuat');
const options = await response.json();
if (controller.signal.aborted) return;
options.forEach(option => child.input.add(new Option(option.nama, option.id)));
child.input.disabled = false;
updateRequired();
} catch (error) {
if (error.name === 'AbortError') return;
child.input.add(new Option('Gagal memuat wilayah, pilih ulang wilayah induk', '', false, true));
}
});
});
updateRequired();
});
});
+119
View File
@@ -0,0 +1,119 @@
'use strict';
document.addEventListener('DOMContentLoaded', () => {
const page = document.querySelector('.koperasi-profile-page');
if (!page) return;
page.querySelectorAll('[data-koperasi-locked-tab]').forEach(tab => {
tab.addEventListener('click', event => event.preventDefault());
});
page.querySelectorAll('[data-koperasi-survey]').forEach(operasional => {
const fields = Array.from(operasional.querySelectorAll('[data-koperasi-survey-field]'));
const conditions = new Map(fields.map(wrapper => [wrapper.dataset.koperasiSurveyField, JSON.parse(wrapper.dataset.koperasiConditions)]));
const context = JSON.parse(operasional.dataset.koperasiContext);
const requiredFields = JSON.parse(operasional.dataset.koperasiRequired);
const selectedValues = name => Array.from(operasional.elements)
.filter(input => input.name === name || input.name === name + '[]')
.filter(input => !['checkbox', 'radio'].includes(input.type) || input.checked)
.map(input => input.value);
const matches = condition => {
if (condition.any) return condition.any.some(matches);
if (condition.source === 'profile') return condition.values.includes(context[condition.field]);
return active(condition.field) && condition.values.some(value => selectedValues(condition.field).includes(value));
};
const active = field => (conditions.get(field) || []).every(matches);
const updateDependencies = () => {
fields.forEach(wrapper => {
const field = wrapper.dataset.koperasiSurveyField;
const visible = active(field);
const required = visible && requiredFields.includes(field);
wrapper.classList.toggle('d-none', !visible);
wrapper.querySelectorAll('input, select, textarea').forEach(input => {
input.disabled = !visible;
input.required = required && input.type !== 'checkbox';
input.setCustomValidity('');
});
const checkboxes = wrapper.querySelectorAll('input[type="checkbox"]');
if (required && checkboxes.length && !Array.from(checkboxes).some(input => input.checked)) {
checkboxes[0].setCustomValidity('Pilih sedikitnya satu pilihan.');
}
const indicator = wrapper.querySelector('[data-koperasi-required-indicator]');
if (indicator) indicator.classList.toggle('d-none', !required);
});
};
operasional.addEventListener('change', event => {
const input = event.target;
const group = input.closest('[data-koperasi-exclusive]');
if (group && input.type === 'checkbox' && input.checked) {
group.querySelectorAll('input[type="checkbox"]').forEach(option => {
if (option !== input && (input.value === group.dataset.koperasiExclusive || option.value === group.dataset.koperasiExclusive)) {
option.checked = false;
}
});
}
updateDependencies();
});
updateDependencies();
});
const activeSection = document.getElementById(window.location.hash.slice(1));
if (activeSection && page.contains(activeSection) && activeSection.matches('[data-koperasi-section]')) {
const showSection = () => {
activeSection.scrollIntoView({ behavior: 'instant', block: 'start' });
activeSection.focus({ preventScroll: true });
};
if (document.readyState === 'complete') {
requestAnimationFrame(showSection);
} else {
window.addEventListener('load', () => requestAnimationFrame(showSection), { once: true });
}
}
const form = page.querySelector('[data-koperasi-profile]');
if (form) {
const jenis = form.querySelector('[name="jenis_koperasi"]');
const wrapper = form.querySelector('#koperasi-jenis-lainnya-wrapper');
const lainnya = form.querySelector('[name="jenis_koperasi_lainnya"]');
const toggleJenisLainnya = () => {
const isLainnya = jenis.value === form.dataset.jenisLainnya;
wrapper.classList.toggle('d-none', !isLainnya);
lainnya.disabled = !isLainnya;
};
jenis.addEventListener('change', toggleJenisLainnya);
toggleJenisLainnya();
const fokus = form.querySelector('[name="fokus_komoditas"]');
const detail = form.querySelector('[name="detail_fokus_komoditas"]');
const fokusWrapper = form.querySelector('#koperasi-detail-fokus-wrapper');
const toggleFokus = () => {
const aktif = fokus.value === fokus.dataset.fokusYa;
fokusWrapper.classList.toggle('d-none', !aktif);
detail.disabled = !aktif;
};
fokus.addEventListener('change', toggleFokus);
toggleFokus();
}
const formatRupiah = value => {
const negative = value.trimStart().startsWith('-');
const digits = value.replace(/\D/g, '').replace(/^0+(?=\d)/, '');
return (negative ? '-' : '') + digits.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
};
page.querySelectorAll('[data-koperasi-rupiah]').forEach(input => {
if (/^-?[\d.]+$/.test(input.value)) input.value = formatRupiah(input.value);
input.addEventListener('input', () => {
const digitsBefore = input.value.slice(0, input.selectionStart).replace(/\D/g, '').length;
input.value = formatRupiah(input.value);
let cursor = input.value.startsWith('-') ? 1 : 0;
let count = 0;
while (cursor < input.value.length && count < digitsBefore) {
if (/\d/.test(input.value[cursor])) count++;
cursor++;
}
input.setSelectionRange(cursor, cursor);
});
});
});