📅 Kalender Munfiq — PLPK Kedawung
Jadwal jemput KOIN: tgl 1–8 setiap bulan • Cetak kalender personal
Opsi Cetak Kalender
Tips: Pilih tahun, bulan, dan munfiq yang ingin dicetak. Kalender akan otomatis menandai tanggal jemput KOIN.
s/d
Akan di-highlight pada kalender
Tips: Gunakan kertas A4 portrait untuk standard, A5 untuk saku
Preview Kalender
Tambah/Update Munfiq
Daftar Munfiq
| Nama | Alamat | Kontak | Preferensi | Catatan | Aksi |
|---|
⚙️ Pengaturan Aplikasi
Maksimal 2MB, akan ditampilkan di header
📦 Kelola Data
Data tersimpan lokal di perangkat ini. Gunakan fitur ekspor untuk backup dan impor untuk restore data.
`;
html += monthHTMLBlock({ titleLeft: esc(m.name), monthIdx: leftMi, year, pickStart, pickEnd, waQR, formQR, waLink, formURL });
if (rightMi !== undefined) {
html += monthHTMLBlock({ titleLeft: esc(m.name), monthIdx: rightMi, year, pickStart, pickEnd, waQR, formQR, waLink, formURL });
} else {
html += ``;
}
html += `
` : '';
const qrWAHTML = waQR ? `WA

${logo ? logo : ''}
${esc(m.name)} — Kalender ${year}
${qrWAHTML}
Ranting ${esc(state.settings.ranting || 'Kedawung')} • PLPK: ${esc(state.settings.plpk || '')} • WA: ${esc(state.settings.wa || '-')} • Jemput: tgl ${pickStart}–${pickEnd}
`;
let grid = ``;
for (const mi of monthsSel) {
grid += `
`;
}
grid += `
`;
html += `${months[mi]} ${year}
${tableHTML(year, mi, pickStart, pickEnd)}${header}${grid}
`;
}
html += '';
w.document.write(html);
w.document.close();
w.addEventListener('load', () => setTimeout(() => w.print(), 400));
}function buildWALink() {
const n = (state.settings.wa || '').replace(/\D/g, '');
if (!n) return '';
const msg = encodeURIComponent('Assalamu'alaikum, PLPK. Saya munfiq Kedawung ingin konfirmasi/jadwal jemput. Terima kasih.');
return `https://wa.me/${n}?text=${msg}`;
}function makeQRDataURL(text) {
return new Promise(resolve => {
if (!text || !window.QRCode) {
resolve('');
return;
}
QRCode.toDataURL(text, { width: 128, margin: 1 }, (err, url) => resolve(err ? '' : url));
});
}// Import/Export functionality
document.getElementById('exportJSON').addEventListener('click', () => {
const blob = new Blob([JSON.stringify(state, null, 2)], { type: 'application/json' });
downloadBlob(blob, `kalender-munfiq-${new Date().toISOString().split('T')[0]}.json`);
showToast('✅ Data berhasil diekspor ke file JSON', 'success');
});document.getElementById('importBtn').addEventListener('click', () => {
const f = document.getElementById('importFile').files[0];
if (!f) {
showToast('⚠️ Pilih file JSON terlebih dahulu', 'warning');
return;
}
const r = new FileReader();
r.onload = () => {
try {
const data = JSON.parse(r.result);
if (!data || !data.settings || !Array.isArray(data.munfiq)) {
throw new Error('Format file tidak valid');
}
if (!confirm('Impor akan mengganti semua data yang ada. Lanjutkan?')) return;
state = data;
saveState();
renderSettings();
showToast('✅ Data berhasil diimpor dari file', 'success');
} catch(e) {
showToast('❌ Gagal impor: ' + e.message, 'error');
}
};
r.readAsText(f);
});document.getElementById('wipeBtn').addEventListener('click', () => {
if (!confirm('⚠️ Hapus SEMUA data aplikasi?')) return;
if (!confirm('Yakin? Tindakan ini tidak dapat dibatalkan!')) return;
localStorage.removeItem(STORAGE_KEY);
state = defaultState();
saveState();
renderSettings();
showToast('✅ Semua data telah direset', 'success');
});// Utility functions
function uid() {
return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
}function esc(s) {
return (s ?? '').toString().replace(/[&<>"']/g, m => ({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[m]));
}function downloadBlob(blob, filename) {
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(a.href);
a.remove();
}// Initialize
(function() {
// Sync pickup range
document.getElementById('calPickStart').value = state.settings.pickupStart || 1;
document.getElementById('calPickEnd').value = state.settings.pickupEnd || 8;
// Initial preview
renderMiniPreview();
// Welcome message
if (state.munfiq.length === 0) {
setTimeout(() => {
showToast('👋 Selamat datang! Mulai dengan menambah data munfiq di tab Munfiq', 'success', 5000);
}, 1000);
}
// Add version info
console.log('%c📅 Kalender Munfiq v2.0', 'color: #00a884; font-size: 14px; font-weight: bold');
console.log('Dibuat untuk PLPK Ranting Kedawung');
})();
