indonesian / views /index.ejs
devusman's picture
Update views/index.ejs
b05ea1a verified
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Alat Bantu Pencarian Data Bantuan Sosial</title>
<style>
/* --- Gaya Dasar & Tata Letak --- */
* {
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
color: #172b4d;
margin: 1em;
line-height: 1.5;
}
.cb-container {
max-width: 900px;
margin: auto;
background: #ffffff;
padding: 1.5em;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.cb-grid {
display: grid;
grid-template-columns: 1fr;
gap: 2.5em;
}
.cb-col h2,
.cb-col h3 {
border-bottom: 2px solid #dfe1e6;
padding-bottom: 0.5em;
margin-top: 0;
margin-bottom: 1.2em;
color: #091e42;
}
/* --- Formulir --- */
.cb-label {
display: block;
margin-bottom: 0.5em;
font-weight: bold;
font-size: 0.95em;
color: #42526e;
}
.cb-select,
.cb-input {
width: 100%;
padding: 0.85em;
margin-bottom: 1.2em;
border: 2px solid #dfe1e6;
border-radius: 6px;
background-color: #fafbfc;
font-size: 1em;
color: #172b4d;
text-transform: uppercase;
transition: border-color 0.2s;
}
.cb-select:focus,
.cb-input:focus {
border-color: #0052cc;
outline: none;
}
.cb-select:disabled {
background-color: #f4f5f7;
cursor: not-allowed;
}
/* --- Tombol --- */
.cb-actions {
display: flex;
gap: 1em;
margin-top: 1.5em;
flex-direction: column;
}
.cb-btn {
border: none;
padding: 0.85em 1.5em;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
text-decoration: none;
text-align: center;
font-size: 1em;
width: 100%;
transition: background-color 0.2s;
}
.cb-btn-primary {
background-color: #0052cc;
color: white;
}
.cb-btn-primary:hover {
background-color: #0747a6;
}
.cb-btn-gray {
background-color: #ebecf0;
color: #42526e;
}
.cb-btn-gray:hover {
background-color: #dfe1e6;
}
/* --- Info & Disclaimer --- */
.cb-note,
.cb-disclaimer {
margin-top: 1.5em;
padding: 1em;
border-radius: 6px;
font-size: 0.9em;
}
.cb-note {
background-color: #e6fcff;
border-left: 4px solid #00c7e6;
}
.cb-disclaimer {
background-color: #fffae6;
border-left: 4px solid #ffab00;
}
/* --- Kotak Hasil --- */
.cb-result {
display: none;
margin-top: 2.5em;
padding: 1.5em;
border-radius: 8px;
background-color: #fafbfc;
}
.cb-kv {
display: grid;
grid-template-columns: 1fr;
gap: 0.5em 1em;
}
.cb-kv div:nth-child(odd) {
font-weight: bold;
color: #6b778c;
}
/* Styling untuk nama kini sama dengan value lainnya */
.cb-kv div:nth-child(even) {
font-weight: 600;
}
/* --- Desain Responsif --- */
@media (min-width: 600px) {
.cb-actions {
flex-direction: row;
}
.cb-btn {
width: auto;
}
.cb-kv {
grid-template-columns: 140px 1fr;
}
}
@media (min-width: 900px) {
.cb-container {
padding: 2em;
}
.cb-grid {
grid-template-columns: 2fr 1fr;
}
}
</style>
</head>
<body>
<div class="cb-container" id="cek-bansos-tool">
<div class="cb-grid">
<div class="cb-col">
<h2>Pencarian Data Penerima Manfaat</h2>
<label class="cb-label" for="provinsi">Provinsi</label>
<select id="provinsi" class="cb-select">
<option value="">=== PILIH PROVINSI ===</option>
</select>
<label class="cb-label" for="kabupaten">Kabupaten/Kota</label>
<select id="kabupaten" class="cb-select" disabled>
<option value="">=== PILIH KABUPATEN/KOTA ===</option>
</select>
<label class="cb-label" for="kecamatan">Kecamatan</label>
<select id="kecamatan" class="cb-select" disabled>
<option value="">=== PILIH KECAMATAN ===</option>
</select>
<label class="cb-label" for="desa">Desa/Kelurahan</label>
<select id="desa" class="cb-select" disabled>
<option value="">=== PILIH DESA/KELURAHAN ===</option>
</select>
<label class="cb-label" for="nama">Nama Penerima (sesuai KTP)</label>
<input id="nama" class="cb-input" type="text" placeholder="CONTOH: BUDI SANTOSO" />
<div class="cb-actions">
<button type="button" id="resetButton" class="cb-btn cb-btn-gray">Atur Ulang</button>
<button type="button" id="searchButton" class="cb-btn cb-btn-primary">Cari Data</button>
</div>
<div class="cb-note">
<strong>Catatan:</strong> Ini adalah <em>alat bantu</em> untuk menyiapkan data Anda. Hasil resmi
hanya tersedia di situs Kemensos.
</div>
</div>
<div class="cb-col">
<h3>Cara Pakai (Singkat)</h3>
<ol style="padding-left: 1.5em;">
<li>Pilih wilayah domisili lengkap secara berurutan.</li>
<li>Ketik nama lengkap sesuai KTP.</li>
<li>Klik <strong>Cari Data</strong> untuk melihat ringkasan & tombol menuju situs resmi.</li>
</ol>
<div class="cb-disclaimer">
<em>Sanggahan:</em> Website ini <strong>bukan</strong> situs resmi Kemensos. Kami hanya menyediakan
panduan & tombol akses cepat ke layanan resmi.
</div>
</div>
</div>
<!-- Result box -->
<div id="resultBox" class="cb-result">
<h3>Ringkasan Data Anda</h3>
<div class="cb-kv">
<div>Nama</div>
<div id="r-nama">&#8211;</div>
<div>Provinsi</div>
<div id="r-prov">&#8211;</div>
<div>Kab/Kota</div>
<div id="r-kab">&#8211;</div>
<div>Kecamatan</div>
<div id="r-kec">&#8211;</div>
<div>Desa/Kel</div>
<div id="r-desa">&#8211;</div>
</div>
<p style="margin-top:1.5em; font-size: 0.95em;">
Untuk <strong>hasil resmi</strong>, lanjut ke layanan Kemensos di tab baru. Siapkan data yang sama saat
mengisi.
</p>
<div class="cb-actions">
<a id="btn-resmi" class="cb-btn cb-btn-primary" href="https://cekbansos.kemensos.go.id" target="_blank"
rel="nofollow noopener">Buka Situs Resmi Kemensos &rarr;</a>
<button type="button" id="btn-copy" class="cb-btn cb-btn-gray" aria-label="Salin ringkasan">
<span id="copy-text">Salin Ringkasan</span>
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const provinceSelect = document.getElementById('provinsi');
const regencySelect = document.getElementById('kabupaten');
const districtSelect = document.getElementById('kecamatan');
const villageSelect = document.getElementById('desa');
const nameInput = document.getElementById('nama');
const searchButton = document.getElementById('searchButton');
const resetButton = document.getElementById('resetButton');
const resultBox = document.getElementById('resultBox');
const copyButton = document.getElementById('btn-copy');
function populateSelect(selectElement, data, defaultOptionText) {
selectElement.innerHTML = `<option value="">=== ${defaultOptionText.toUpperCase()} ===</option>`;
data.forEach(item => {
const option = document.createElement('option');
option.value = item.id;
option.textContent = item.value;
selectElement.appendChild(option);
});
}
function resetSelects(...selects) {
selects.forEach(select => {
const placeholder = select.options[0].text;
select.innerHTML = `<option value="">${placeholder}</option>`;
select.disabled = true;
});
}
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return await response.json();
} catch (error) {
console.error("Gagal mengambil data:", error);
alert("Gagal memuat data wilayah. Pastikan koneksi internet Anda stabil dan coba lagi.");
return [];
}
}
(async () => {
const provinces = await fetchData('/api/provinces');
populateSelect(provinceSelect, provinces, 'Pilih Provinsi');
})();
provinceSelect.addEventListener('change', async () => {
const provinceId = provinceSelect.value;
resetSelects(regencySelect, districtSelect, villageSelect);
resultBox.style.display = 'none';
if (provinceId) {
let regencies = await fetchData(`/api/provinces/${provinceId}/regencies`);
const formattedRegencies = regencies.map(reg => {
const isCity = reg.value.toUpperCase().startsWith('KOTA');
return { id: reg.id, value: isCity ? reg.value : `KABUPATEN ${reg.value}` };
});
populateSelect(regencySelect, formattedRegencies, 'Pilih Kabupaten/Kota');
regencySelect.disabled = false;
}
});
regencySelect.addEventListener('change', async () => {
const provinceId = provinceSelect.value;
const regencyId = regencySelect.value;
resetSelects(districtSelect, villageSelect);
if (regencyId) {
const districts = await fetchData(`/api/provinces/${provinceId}/regencies/${regencyId}/districts`);
populateSelect(districtSelect, districts, 'Pilih Kecamatan');
districtSelect.disabled = false;
}
});
districtSelect.addEventListener('change', async () => {
const provinceId = provinceSelect.value;
const regencyId = regencySelect.value;
const districtId = districtSelect.value;
resetSelects(villageSelect);
if (districtId) {
const villages = await fetchData(`/api/provinces/${provinceId}/regencies/${regencyId}/districts/${districtId}/villages`);
populateSelect(villageSelect, villages, 'Pilih Desa/Kelurahan');
villageSelect.disabled = false;
}
});
searchButton.addEventListener('click', () => {
if (!provinceSelect.value || !regencySelect.value || !districtSelect.value || !villageSelect.value || !nameInput.value.trim()) {
alert('Mohon lengkapi semua data wilayah dan nama sebelum melanjutkan.');
return;
}
document.getElementById('r-nama').textContent = nameInput.value.trim().toUpperCase();
document.getElementById('r-prov').textContent = provinceSelect.options[provinceSelect.selectedIndex].text;
document.getElementById('r-kab').textContent = regencySelect.options[regencySelect.selectedIndex].text;
document.getElementById('r-kec').textContent = districtSelect.options[districtSelect.selectedIndex].text;
document.getElementById('r-desa').textContent = villageSelect.options[villageSelect.selectedIndex].text;
resultBox.style.display = 'block';
resultBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
});
resetButton.addEventListener('click', () => {
provinceSelect.selectedIndex = 0;
nameInput.value = '';
resetSelects(regencySelect, districtSelect, villageSelect);
resultBox.style.display = 'none';
});
copyButton.addEventListener('click', () => {
const summaryText = `RINGKASAN DATA SAYA:\nNama: ${document.getElementById('r-nama').textContent}\nProvinsi: ${document.getElementById('r-prov').textContent}\nKab/Kota: ${document.getElementById('r-kab').textContent}\nKecamatan: ${document.getElementById('r-kec').textContent}\nDesa/Kel: ${document.getElementById('r-desa').textContent}`;
navigator.clipboard.writeText(summaryText).then(() => {
const copyTextSpan = document.getElementById('copy-text');
copyTextSpan.textContent = "Berhasil Disalin! \u2713";
setTimeout(() => { copyTextSpan.textContent = "Salin Ringkasan"; }, 2000);
}).catch(err => {
console.error('Gagal menyalin: ', err);
alert('Gagal menyalin data secara otomatis.');
});
});
});
function sendHeight() {
if (window.parent) {
const height = document.body.scrollHeight;
window.parent.postMessage(
{
height: height,
},
"*"
);
}
}
// --- Logic for Embedding and Dynamic Resizing ---
document.addEventListener("DOMContentLoaded", () => {
// Initial animations on page load
document.querySelectorAll(".animate__animated").forEach((el, i) => {
el.style.animationDelay = `${i * 0.1}s`;
});
// Send initial height to parent window
sendHeight();
// Use a MutationObserver to watch for any changes in the page content
// and send the new height to the parent window.
const observer = new MutationObserver(() => sendHeight());
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
characterData: true,
});
});
</script>
</body>
</html>