mengubah sistem menjadi lebih terfokus ke poverty
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
function startAdd(type) {
|
||||
cancelMapClick();
|
||||
const btnId = type === 'ri' ? 'btn-add-ri' : 'btn-add-pm';
|
||||
const label = type === 'ri' ? 'lokasi Rumah Ibadah' : 'lokasi Penduduk Miskin';
|
||||
document.getElementById(btnId).classList.add('active');
|
||||
showInstruction(`Klik di peta untuk menentukan ${label}`);
|
||||
onceMapClick((lat, lng) => {
|
||||
document.getElementById(btnId).classList.remove('active');
|
||||
hideInstruction();
|
||||
if (type === 'ri') openRIForm(null, lat, lng);
|
||||
else openPMForm(null, lat, lng);
|
||||
});
|
||||
}
|
||||
|
||||
function openRIForm(data, lat, lng) {
|
||||
const isEdit = !!data;
|
||||
const fLat = isEdit ? data.latitude : lat;
|
||||
const fLng = isEdit ? data.longitude : lng;
|
||||
const isAdmin = window.currentUser && window.currentUser.role === 'admin';
|
||||
const accountFieldsHTML = isAdmin ? `
|
||||
<div style="margin-top:16px; border-top: 1px solid var(--line); padding-top:14px;">
|
||||
<div class="layer-section-title">Akun Rumah Ibadah</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Username Rumah Ibadah</label>
|
||||
<input class="form-input" id="ri-username" value="${esc(isEdit ? data.username || '' : '')}" placeholder="username_rumah_ibadah" autocomplete="off" readonly style="background-color:#f1f5f9;cursor:not-allowed;color:#64748b;"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Password Rumah Ibadah ${isEdit ? '(kosongkan jika tidak diubah)' : '*'}</label>
|
||||
<input class="form-input" id="ri-password" type="password" placeholder="••••••••" autocomplete="new-password"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
` : '';
|
||||
|
||||
openModal(isEdit ? 'Edit Rumah Ibadah' : 'Tambah Rumah Ibadah', `
|
||||
<div class="form-coord">📍 Koordinat: ${fLat.toFixed(7)}, ${fLng.toFixed(7)}</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Rumah Ibadah *</label>
|
||||
<input class="form-input" id="ri-nama" value="${esc(isEdit ? data.nama : '')}" placeholder="Masjid Al-Ikhlas…"/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Jenis *</label>
|
||||
<select class="form-select" id="ri-jenis">
|
||||
${['Masjid', 'Gereja', 'Pura', 'Vihara', 'Klenteng', 'Lainnya'].map(j =>
|
||||
`<option value="${j}"${isEdit && data.jenis === j ? ' selected' : ''}>${j}</option>`
|
||||
).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Radius (meter) *</label>
|
||||
<input class="form-input" id="ri-radius" type="number" value="${isEdit ? data.radius_meter : 500}" min="50" max="10000"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Alamat</label>
|
||||
<input class="form-input" id="ri-alamat" value="${isEdit ? esc(data.alamat || '') : 'Memuat alamat otomatis...'}" placeholder="Jl. …"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">No. WhatsApp</label>
|
||||
<input class="form-input" id="ri-nowa" value="${esc(isEdit ? data.no_wa || '' : '')}" placeholder="081234…"/>
|
||||
</div>
|
||||
${accountFieldsHTML}`,
|
||||
`<button class="btn btn-ghost" onclick="closeModal()">Batal</button>
|
||||
<button class="btn btn-primary" onclick="saveRI(${isEdit ? data.id : 'null'},${fLat},${fLng})">💾 Simpan</button>`);
|
||||
|
||||
// Attach dynamic username locking listener
|
||||
if (isAdmin) {
|
||||
const namaEl = document.getElementById('ri-nama');
|
||||
const usernameEl = document.getElementById('ri-username');
|
||||
if (namaEl && usernameEl) {
|
||||
namaEl.addEventListener('input', () => {
|
||||
usernameEl.value = namaEl.value
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]/g, '_')
|
||||
.replace(/_+/g, '_')
|
||||
.replace(/^_+|_+$/g, '');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Geocode address asynchronously
|
||||
if (!isEdit) {
|
||||
getAddressFromCoords(fLat, fLng).then(addr => {
|
||||
const el = document.getElementById('ri-alamat');
|
||||
if (el && el.value === 'Memuat alamat otomatis...') {
|
||||
el.value = addr || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function saveRI(id, lat, lng) {
|
||||
const usernameEl = document.getElementById('ri-username');
|
||||
const passwordEl = document.getElementById('ri-password');
|
||||
const body = {
|
||||
nama: document.getElementById('ri-nama').value.trim(),
|
||||
jenis: document.getElementById('ri-jenis').value,
|
||||
alamat: document.getElementById('ri-alamat').value.trim(),
|
||||
no_wa: document.getElementById('ri-nowa').value.trim(),
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
radius_meter: parseInt(document.getElementById('ri-radius').value),
|
||||
username: usernameEl ? usernameEl.value.trim() : '',
|
||||
password: passwordEl ? passwordEl.value : ''
|
||||
};
|
||||
if (!body.nama) return toast('Nama wajib diisi', 'error');
|
||||
|
||||
// Validate account password for new Rumah Ibadah
|
||||
const isAdmin = window.currentUser && window.currentUser.role === 'admin';
|
||||
if (isAdmin && !id) {
|
||||
if (!body.username) return toast('Username Rumah Ibadah wajib terisi', 'error');
|
||||
if (!body.password) return toast('Password Rumah Ibadah wajib diisi', 'error');
|
||||
}
|
||||
|
||||
const res = await callAPI(id ? `rumah_ibadah.php?id=${id}` : 'rumah_ibadah.php', id ? 'PUT' : 'POST', body);
|
||||
if (res.status === 'success') {
|
||||
toast(res.message, 'success');
|
||||
closeModal();
|
||||
await recalcAllProximity();
|
||||
switchTab('rumah_ibadah');
|
||||
} else {
|
||||
toast(res.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function openPMForm(data, lat, lng) {
|
||||
const isEdit = !!data;
|
||||
const fLat = isEdit ? data.latitude : lat;
|
||||
const fLng = isEdit ? data.longitude : lng;
|
||||
openModal(isEdit ? 'Edit Penduduk Miskin' : 'Tambah Penduduk Miskin', `
|
||||
<div class="form-coord">📍 Koordinat: ${fLat.toFixed(7)}, ${fLng.toFixed(7)}</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Lengkap *</label>
|
||||
<input class="form-input" id="pm-nama" value="${esc(isEdit ? data.nama : '')}" placeholder="Ahmad Subarjo…"/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">No. WhatsApp</label>
|
||||
<input class="form-input" id="pm-nowa" value="${esc(isEdit ? data.no_wa || '' : '')}" placeholder="081234…"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">NIK</label>
|
||||
<input class="form-input" id="pm-nik" value="${esc(isEdit ? data.nik || '' : '')}" placeholder="617101…"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Alamat</label>
|
||||
<input class="form-input" id="pm-alamat" value="${isEdit ? esc(data.alamat || '') : 'Memuat alamat otomatis...'}" placeholder="Jl. …"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Jumlah Anggota Keluarga</label>
|
||||
<input class="form-input" id="pm-jml" type="number" value="${isEdit ? data.jumlah_anggota : 1}" min="1" max="20"/>
|
||||
</div>`,
|
||||
`<button class="btn btn-ghost" onclick="closeModal()">Batal</button>
|
||||
<button class="btn btn-primary" onclick="savePM(${isEdit ? data.id : 'null'},${fLat},${fLng})">💾 Simpan</button>`);
|
||||
|
||||
// Geocode address asynchronously
|
||||
if (!isEdit) {
|
||||
getAddressFromCoords(fLat, fLng).then(addr => {
|
||||
const el = document.getElementById('pm-alamat');
|
||||
if (el && el.value === 'Memuat alamat otomatis...') {
|
||||
el.value = addr || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function savePM(id, lat, lng) {
|
||||
const body = {
|
||||
nama: document.getElementById('pm-nama').value.trim(),
|
||||
no_wa: document.getElementById('pm-nowa').value.trim(),
|
||||
nik: document.getElementById('pm-nik').value.trim(),
|
||||
alamat: document.getElementById('pm-alamat').value.trim(),
|
||||
jumlah_anggota: parseInt(document.getElementById('pm-jml').value) || 1,
|
||||
latitude: lat,
|
||||
longitude: lng
|
||||
};
|
||||
if (!body.nama) return toast('Nama wajib diisi', 'error');
|
||||
const res = await callAPI(id ? `penduduk_miskin.php?id=${id}` : 'penduduk_miskin.php', id ? 'PUT' : 'POST', body);
|
||||
if (res.status === 'success') {
|
||||
toast(res.message, 'success');
|
||||
closeModal();
|
||||
switchTab('penduduk_miskin');
|
||||
} else {
|
||||
toast(res.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function editRI(id) {
|
||||
map.closePopup();
|
||||
const res = await callAPI(`rumah_ibadah.php?id=${id}`);
|
||||
if (res.data) openRIForm(res.data, res.data.latitude, res.data.longitude);
|
||||
}
|
||||
|
||||
async function deleteRI(id) {
|
||||
if (!confirm('Hapus rumah ibadah ini?')) return;
|
||||
const res = await callAPI(`rumah_ibadah.php?id=${id}`, 'DELETE');
|
||||
if (res.status === 'success') {
|
||||
toast('Dihapus', 'success');
|
||||
map.closePopup();
|
||||
await recalcAllProximity();
|
||||
switchTab('rumah_ibadah');
|
||||
}
|
||||
}
|
||||
|
||||
async function editPM(id) {
|
||||
map.closePopup();
|
||||
const res = await callAPI(`penduduk_miskin.php?id=${id}`);
|
||||
if (res.data) openPMForm(res.data, res.data.latitude, res.data.longitude);
|
||||
}
|
||||
|
||||
async function deletePM(id) {
|
||||
if (!confirm('Hapus data ini?')) return;
|
||||
const res = await callAPI(`penduduk_miskin.php?id=${id}`, 'DELETE');
|
||||
if (res.status === 'success') {
|
||||
toast('Dihapus', 'success');
|
||||
map.closePopup();
|
||||
await recalcAllProximity();
|
||||
switchTab('penduduk_miskin');
|
||||
}
|
||||
}
|
||||
|
||||
// Haversine formula — returns distance in meters between two lat/lng points
|
||||
Reference in New Issue
Block a user