420 lines
25 KiB
HTML
420 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Survei Lapangan - Dinsos Pontianak</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
body { font-family: 'Poppins', sans-serif; }
|
|
</style>
|
|
</head>
|
|
<body class="bg-gray-100 flex flex-col min-h-screen">
|
|
|
|
<nav class="bg-emerald-600 p-4 shadow-md z-30 flex items-center gap-4 text-white sticky top-0">
|
|
<a href="index.html" class="hover:bg-emerald-700 p-2 rounded-lg transition">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
|
|
</a>
|
|
<h1 class="text-xl font-bold">Formulir Survei Kemiskinan Kriteria BPS</h1>
|
|
</nav>
|
|
|
|
<main class="flex-grow p-4 md:p-8 flex justify-center items-start">
|
|
<div class="bg-white w-full max-w-2xl rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
|
|
<div class="bg-gray-50 border-b border-gray-200 p-6 flex justify-between items-center">
|
|
<div class="flex flex-col items-center gap-2">
|
|
<div id="indikator_1" class="w-8 h-8 rounded-full bg-emerald-600 text-white flex justify-center items-center font-bold text-sm transition-colors">1</div>
|
|
<span class="text-[10px] font-semibold text-gray-600">Identitas</span>
|
|
</div>
|
|
<div class="h-1 flex-1 bg-gray-200 mx-1 rounded">
|
|
<div id="garis_1" class="h-full bg-emerald-600 w-0 transition-all duration-300"></div>
|
|
</div>
|
|
<div class="flex flex-col items-center gap-2">
|
|
<div id="indikator_2" class="w-8 h-8 rounded-full bg-gray-300 text-gray-600 flex justify-center items-center font-bold text-sm transition-colors">2</div>
|
|
<span class="text-[10px] font-semibold text-gray-600">Rumah</span>
|
|
</div>
|
|
<div class="h-1 flex-1 bg-gray-200 mx-1 rounded">
|
|
<div id="garis_2" class="h-full bg-emerald-600 w-0 transition-all duration-300"></div>
|
|
</div>
|
|
<div class="flex flex-col items-center gap-2">
|
|
<div id="indikator_3" class="w-8 h-8 rounded-full bg-gray-300 text-gray-600 flex justify-center items-center font-bold text-sm transition-colors">3</div>
|
|
<span class="text-[10px] font-semibold text-gray-600">Ekonomi</span>
|
|
</div>
|
|
<div class="h-1 flex-1 bg-gray-200 mx-1 rounded">
|
|
<div id="garis_3" class="h-full bg-emerald-600 w-0 transition-all duration-300"></div>
|
|
</div>
|
|
<div class="flex flex-col items-center gap-2">
|
|
<div id="indikator_4" class="w-8 h-8 rounded-full bg-gray-300 text-gray-600 flex justify-center items-center font-bold text-sm transition-colors">4</div>
|
|
<span class="text-[10px] font-semibold text-gray-600">Lokasi</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="p-6">
|
|
<div id="peringatan_error" class="hidden mb-4 p-3 bg-red-50 border border-red-200 text-red-700 rounded-lg text-sm font-medium"></div>
|
|
|
|
<form id="form_survei" onsubmit="return false;">
|
|
|
|
<div id="langkah_1" class="space-y-4">
|
|
<h2 class="text-lg font-bold text-gray-800 border-b pb-2">Informasi Legalitas Identitas</h2>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Nomor Induk Kependudukan (NIK)</label>
|
|
<input type="text" id="input_nik" maxlength="16" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none" placeholder="16 Digit NIK KTP Kepala Keluarga">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Nama Lengkap Kepala Keluarga</label>
|
|
<input type="text" id="input_nama_kk" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none" placeholder="Masukkan nama lengkap">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Nomor Kartu Keluarga (No KK)</label>
|
|
<input type="text" id="input_no_kk" maxlength="16" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none" placeholder="16 Digit Nomor KK">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Jumlah Anggota Keluarga Tanggungan</label>
|
|
<input type="number" id="input_jumlah_tanggungan" min="0" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none" placeholder="Contoh: 4">
|
|
</div>
|
|
</div>
|
|
|
|
<div id="langkah_2" class="hidden space-y-4">
|
|
<h2 class="text-lg font-bold text-gray-800 border-b pb-2">Kondisi Fisik Rumah Tinggal</h2>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Luas Lantai Per Kapita (Per Orang)</label>
|
|
<select id="input_luas_lantai" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih ukuran luas...</option>
|
|
<option value="Kurang dari 8m2">Kurang dari 8 meter persegi per orang</option>
|
|
<option value="8m2 atau Lebih">8 meter persegi atau lebih per orang</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Material Bahan Lantai Terluas</label>
|
|
<select id="input_material_lantai" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih jenis material...</option>
|
|
<option value="Tanah / Bambu">Tanah / Bambu / Kayu Murah</option>
|
|
<option value="Semen / Keramik">Semen / Ubin / Keramik</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Material Bahan Dinding Terluas</label>
|
|
<select id="input_material_dinding" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih jenis dinding...</option>
|
|
<option value="Bambu / Rumbia / Kayu Murah">Bambu / Rumbia / Kayu Kualitas Rendah</option>
|
|
<option value="Tembok Permanen">Tembok / Bata / Plesteran</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Fasilitas Sanitasi (MCK)</label>
|
|
<select id="input_fasilitas_sanitasi" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih fasilitas sanitasi...</option>
|
|
<option value="Tidak Ada / Bersama">Tidak Ada / Menggunakan MCK Umum atau Bersama</option>
|
|
<option value="Milik Sendiri">Ada Pribadi di Dalam Rumah</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="langkah_3" class="hidden space-y-4">
|
|
<h2 class="text-lg font-bold text-gray-800 border-b pb-2">Kondisi Ekonomi & Fasilitas Utilitas</h2>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Sumber Air Minum Utama</label>
|
|
<select id="input_sumber_air" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih sumber air...</option>
|
|
<option value="Sumur Tak Terlindung / Sungai / Air Hujan">Sumur Tak Terlindung / Air Hujan / Sungai</option>
|
|
<option value="PDAM / Sumur Terlindung">PDAM / Sumur Bor Terlindung</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Sumber Penerangan Utama</label>
|
|
<select id="input_sumber_penerangan" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih jenis penerangan...</option>
|
|
<option value="Non-PLN / Menumpang">Bukan Listrik PLN / Menumpang Tetangga</option>
|
|
<option value="PLN Mandiri">Listrik Meteran PLN Sendiri</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Pekerjaan Utama Kepala Keluarga</label>
|
|
<input type="text" id="input_pekerjaan" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none" placeholder="Contoh: Buruh Harian Lepas, Pemulung">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Estimasi Pendapatan Total Per Bulan (Rp)</label>
|
|
<input type="number" id="input_pendapatan" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none" placeholder="Contoh: 1200000">
|
|
</div>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Frekuensi Makan Per Hari</label>
|
|
<select id="input_frekuensi_makan" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih frekuensi...</option>
|
|
<option value="1 Kali atau Kurang">1 Kali Sehari atau Kurang</option>
|
|
<option value="2 Kali">2 Kali Sehari</option>
|
|
<option value="3 Kali atau Lebih">3 Kali Sehari atau Lebih</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Kepemilikan Aset Kendaraan</label>
|
|
<select id="input_kepemilikan_aset" class="w-full p-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-emerald-500 outline-none">
|
|
<option value="">Pilih status kepemilikan...</option>
|
|
<option value="Tidak Memiliki Motor">Tidak Memiliki Sepeda Motor</option>
|
|
<option value="Memiliki Motor / Aset Lain">Memiliki Motor atau Aset Berharga Lain</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="langkah_4" class="hidden space-y-4">
|
|
<h2 class="text-lg font-bold text-gray-800 border-b pb-2">Verifikasi Titik Lokasi Geografis</h2>
|
|
<button type="button" onclick="dapatkan_lokasi_gps()" class="bg-blue-50 text-blue-700 hover:bg-blue-100 border border-blue-200 px-4 py-3 rounded-xl text-sm font-bold transition w-full">
|
|
Ambil Koordinat Lewat GPS Perangkat
|
|
</button>
|
|
<div class="h-64 w-full rounded-xl overflow-hidden border border-gray-300 relative z-0">
|
|
<div id="wadah_peta" class="h-full w-full"></div>
|
|
</div>
|
|
<div class="flex gap-4">
|
|
<div class="flex-1">
|
|
<label class="block text-xs font-medium text-gray-500">Garis Lintang (Latitude)</label>
|
|
<input type="text" id="input_lat" class="w-full p-2 bg-gray-50 border rounded text-sm text-gray-700" readonly>
|
|
</div>
|
|
<div class="flex-1">
|
|
<label class="block text-xs font-medium text-gray-500">Garis Bujur (Longitude)</label>
|
|
<input type="text" id="input_lng" class="w-full p-2 bg-gray-50 border rounded text-sm text-gray-700" readonly>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
|
|
<div class="bg-gray-50 border-t border-gray-200 p-4 flex justify-between">
|
|
<button type="button" id="btn_mundur" onclick="ubah_langkah(-1)" class="hidden px-6 py-2 rounded-lg font-bold text-gray-600 hover:bg-gray-200 transition">Sebelumnya</button>
|
|
<div class="flex-1"></div>
|
|
<button type="button" id="btn_maju" onclick="ubah_langkah(1)" class="bg-emerald-600 text-white px-8 py-2 rounded-lg font-bold hover:bg-emerald-700 transition shadow-sm">Selanjutnya</button>
|
|
<button type="button" id="btn_kirim" onclick="kirim_data_survei()" class="hidden bg-emerald-600 text-white px-8 py-2 rounded-lg font-bold hover:bg-emerald-700 transition shadow-sm">Kirim Hasil Survei</button>
|
|
</div>
|
|
|
|
</div>
|
|
</main>
|
|
|
|
<script>
|
|
let langkah_sekarang = 1;
|
|
const total_langkah = 4;
|
|
|
|
let instansi_peta = null;
|
|
let penanda_peta = null;
|
|
|
|
const btn_mundur = document.getElementById('btn_mundur');
|
|
const btn_maju = document.getElementById('btn_maju');
|
|
const btn_kirim = document.getElementById('btn_kirim');
|
|
const peringatan_error = document.getElementById('peringatan_error');
|
|
|
|
function tampilkan_error(pesan) {
|
|
peringatan_error.textContent = pesan;
|
|
peringatan_error.classList.remove('hidden');
|
|
}
|
|
|
|
function sembunyikan_error() {
|
|
peringatan_error.classList.add('hidden');
|
|
peringatan_error.textContent = '';
|
|
}
|
|
|
|
function validasi_langkah_aktif() {
|
|
sembunyikan_error();
|
|
|
|
switch(langkah_sekarang) {
|
|
case 1:
|
|
if (!/^\d{16}$/.test(document.getElementById('input_nik').value)) {
|
|
tampilkan_error('NIK wajib diisi tepat 16 digit angka.');
|
|
return false;
|
|
}
|
|
if (document.getElementById('input_nama_kk').value.trim().length < 3) {
|
|
tampilkan_error('Nama lengkap kepala keluarga wajib diisi (minimal 3 karakter).');
|
|
return false;
|
|
}
|
|
if (!/^\d{16}$/.test(document.getElementById('input_no_kk').value)) {
|
|
tampilkan_error('Nomor Kartu Keluarga wajib diisi tepat 16 digit angka.');
|
|
return false;
|
|
}
|
|
if (document.getElementById('input_jumlah_tanggungan').value === '') {
|
|
tampilkan_error('Jumlah anggota keluarga tanggungan harus diisi.');
|
|
return false;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!document.getElementById('input_luas_lantai').value ||
|
|
!document.getElementById('input_material_lantai').value ||
|
|
!document.getElementById('input_material_dinding').value ||
|
|
!document.getElementById('input_fasilitas_sanitasi').value) {
|
|
tampilkan_error('Seluruh parameter kelayakan rumah tinggal wajib dipilih.');
|
|
return false;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (!document.getElementById('input_sumber_air').value ||
|
|
!document.getElementById('input_sumber_penerangan').value ||
|
|
!document.getElementById('input_frekuensi_makan').value ||
|
|
!document.getElementById('input_kepemilikan_aset').value) {
|
|
tampilkan_error('Seluruh parameter utilitas and sosial ekonomi wajib dipilih.');
|
|
return false;
|
|
}
|
|
if (document.getElementById('input_pekerjaan').value.trim() === '') {
|
|
tampilkan_error('Pekerjaan utama harus diisi.');
|
|
return false;
|
|
}
|
|
const pendapatan = document.getElementById('input_pendapatan').value;
|
|
if (pendapatan === '' || Number(pendapatan) < 0) {
|
|
tampilkan_error('Estimasi nominal pendapatan harus diisi dengan angka valid.');
|
|
return false;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (!document.getElementById('input_lat').value) {
|
|
tampilkan_error('Titik koordinat penanda spasial belum terekam di peta.');
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function ubah_langkah(arah) {
|
|
if (arah === 1 && !validasi_langkah_aktif()) return;
|
|
|
|
document.getElementById(`langkah_${langkah_sekarang}`).classList.add('hidden');
|
|
langkah_sekarang += arah;
|
|
document.getElementById(`langkah_${langkah_sekarang}`).classList.remove('hidden');
|
|
|
|
perbarui_antarmuka_wizard();
|
|
}
|
|
|
|
function perbarui_antarmuka_wizard() {
|
|
if (langkah_sekarang === 1) {
|
|
btn_mundur.classList.add('hidden');
|
|
} else {
|
|
btn_mundur.classList.remove('hidden');
|
|
}
|
|
|
|
if (langkah_sekarang === total_langkah) {
|
|
btn_maju.classList.add('hidden');
|
|
btn_kirim.classList.remove('hidden');
|
|
setTimeout(inisialisasi_peta, 100);
|
|
} else {
|
|
btn_maju.classList.remove('hidden');
|
|
btn_kirim.classList.add('hidden');
|
|
}
|
|
|
|
for (let i = 1; i <= total_langkah; i++) {
|
|
const indikator = document.getElementById(`indikator_${i}`);
|
|
if (i <= langkah_sekarang) {
|
|
indikator.classList.replace('bg-gray-300', 'bg-emerald-600');
|
|
indikator.classList.replace('text-gray-600', 'text-white');
|
|
} else {
|
|
indikator.classList.replace('bg-emerald-600', 'bg-gray-300');
|
|
indikator.classList.replace('text-white', 'text-gray-600');
|
|
}
|
|
}
|
|
|
|
if(document.getElementById('garis_1')) document.getElementById('garis_1').style.width = langkah_sekarang >= 2 ? '100%' : '0%';
|
|
if(document.getElementById('garis_2')) document.getElementById('garis_2').style.width = langkah_sekarang >= 3 ? '100%' : '0%';
|
|
if(document.getElementById('garis_3')) document.getElementById('garis_3').style.width = langkah_sekarang >= 4 ? '100%' : '0%';
|
|
}
|
|
|
|
function inisialisasi_peta() {
|
|
if (instansi_peta !== null) {
|
|
instansi_peta.invalidateSize();
|
|
return;
|
|
}
|
|
|
|
instansi_peta = L.map('wadah_peta').setView([-0.0227, 109.3425], 13);
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
attribution: '© OpenStreetMap'
|
|
}).addTo(instansi_peta);
|
|
|
|
instansi_peta.on('click', function(e) {
|
|
const lat = e.latlng.lat;
|
|
const lng = e.latlng.lng;
|
|
|
|
if (penanda_peta) instansi_peta.removeLayer(penanda_peta);
|
|
penanda_peta = L.marker([lat, lng]).addTo(instansi_peta);
|
|
|
|
document.getElementById('input_lat').value = lat.toFixed(6);
|
|
document.getElementById('input_lng').value = lng.toFixed(6);
|
|
sembunyikan_error();
|
|
});
|
|
}
|
|
|
|
function dapatkan_lokasi_gps() {
|
|
if (navigator.geolocation) {
|
|
navigator.geolocation.getCurrentPosition(
|
|
function(posisi) {
|
|
const lat = posisi.coords.latitude;
|
|
const lng = posisi.coords.longitude;
|
|
|
|
document.getElementById('input_lat').value = lat.toFixed(6);
|
|
document.getElementById('input_lng').value = lng.toFixed(6);
|
|
|
|
instansi_peta.setView([lat, lng], 16);
|
|
if (penanda_peta) instansi_peta.removeLayer(penanda_peta);
|
|
penanda_peta = L.marker([lat, lng]).addTo(instansi_peta);
|
|
sembunyikan_error();
|
|
},
|
|
function(error) {
|
|
tampilkan_error("Gagal menangkap koordinat satelit GPS. Pastikan izin lokasi aktif.");
|
|
}
|
|
);
|
|
} else {
|
|
tampilkan_error("Perangkat peramban tidak mendukung navigasi Geolocation.");
|
|
}
|
|
}
|
|
|
|
async function kirim_data_survei() {
|
|
if (!validasi_langkah_aktif()) return;
|
|
|
|
btn_kirim.disabled = true;
|
|
btn_kirim.innerHTML = 'Mengirim Data...';
|
|
|
|
const payload_survei = {
|
|
nik: document.getElementById('input_nik').value,
|
|
nama_kk: document.getElementById('input_nama_kk').value,
|
|
no_kk: document.getElementById('input_no_kk').value,
|
|
jumlah_tanggungan: parseInt(document.getElementById('input_jumlah_tanggungan').value) || 0,
|
|
lat: parseFloat(document.getElementById('input_lat').value),
|
|
lng: parseFloat(document.getElementById('input_lng').value),
|
|
id_rumah_ibadah: null,
|
|
indikator_bps: {
|
|
luas_lantai_per_kapita: document.getElementById('input_luas_lantai').value,
|
|
material_lantai: document.getElementById('input_material_lantai').value,
|
|
material_dinding: document.getElementById('input_material_dinding').value,
|
|
fasilitas_sanitasi: document.getElementById('input_fasilitas_sanitasi').value,
|
|
sumber_air_minum: document.getElementById('input_sumber_air').value,
|
|
sumber_penerangan: document.getElementById('input_sumber_penerangan').value,
|
|
pekerjaan_utama: document.getElementById('input_pekerjaan').value,
|
|
pendapatan_bulanan: parseFloat(document.getElementById('input_pendapatan').value) || 0,
|
|
frekuensi_makan: document.getElementById('input_frekuensi_makan').value,
|
|
kepemilikan_aset: document.getElementById('input_kepemilikan_aset').value
|
|
}
|
|
};
|
|
|
|
try {
|
|
// Diubah ke relative path
|
|
const http_response = await fetch('/api/survey/submit', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload_survei)
|
|
});
|
|
|
|
const json_result = await http_response.json();
|
|
|
|
if (!http_response.ok) throw new Error(json_result.error || 'Terjadi kesalahan internal server.');
|
|
|
|
alert('Data rekam survei kriteria baru berhasil disimpan ke basis data!');
|
|
window.location.href = 'index.html';
|
|
|
|
} catch (error_sistem) {
|
|
tampilkan_error(error_sistem.message);
|
|
btn_kirim.disabled = false;
|
|
btn_kirim.innerHTML = 'Kirim Hasil Survei';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |