Aplikasi LogSheet Cekin Net POC

System Pencatatan Log Callsign CekIn Net POC

ONLINE
Roll Call
RC 1
0Total
1RC Aktif
0Belum Lengkap
Peserta Check-in
Daftar Hadiah
Undian
🎁
Siap mengundi…
Riwayat Undian
Belum ada undian
Rekap & Laporan
Panduan NCS
FAQ
Identitas Event
Petugas NCS
Backup & Restore

Simpan cadangan data log & undian ke file, atau pulihkan dari file backup.

Zona Bahaya

Data tersimpan lokal di browser ini Β· Ekspor Excel secara berkala

`); w.document.close(); }; /* ================= PANDUAN & FAQ ================= */ const PANDUAN=[ ['πŸš€ Persiapan Sebelum Bertugas','Isi nama Channel DPD, Ketua Panitia, dan Petugas NCS di menu Set. Pastikan database callsign termuat (badge hijau di pojok kanan atas menampilkan jumlah callsign).'], ['πŸ“’ Sistem Roll Call','Setiap babak pemanggilan = satu RC. Tekan οΌ‹ setelah babak selesai (butuh minimal 1 peserta di RC saat ini). Tombol βˆ’ hanya untuk melihat RC lama β€” panel ungu = mode lihat, input tetap masuk RC kerja.'], ['βœ… Check-in Peserta','Ketik callsign (mis. OC62) β€” pilih dari saran yang muncul, lalu tekan Check-in. Untuk Simpatisan/Calon Anggota tanpa callsign: ketik nama lengkap lalu tekan Simpatisan.'], ['🚫 Anti-Duplikat','Setiap peserta hanya tercatat 1Γ—. Anggota dicek via callsign, Simpatisan via nama. Sistem otomatis menolak duplikat.'], ['🎁 Undian Berhadiah','Tambah hadiah + jumlah undiannya (mis. HT Baofeng Γ—3). Sistem menghabiskan hadiah pertama dulu sebelum lanjut ke hadiah berikutnya. Setiap peserta maksimal menang 1Γ—.'], ['πŸ“Š Ekspor Laporan','Ekspor Excel tiap 20–30 data agar aman, atau Cetak/PDF di akhir acara. Laporan memuat identitas DPD, ketua, petugas, seluruh peserta, dan riwayat undian.'] ]; const FAQ=[ ['Apakah data hilang kalau tutup aplikasi?','Tidak. Data tersimpan di penyimpanan browser (localStorage). Tapi jangan bersihkan data browser β€” dan rutin ekspor Excel.'], ['Apakah bisa dipakai offline?','Bisa. Setelah database callsign termuat sekali, check-in tetap jalan tanpa internet.'], ['Apakah undiannya benar-benar acak?','Ya, menggunakan random bawaan browser terhadap pool peserta yang belum pernah menang.'], ['Bagaimana urutan hadiah?','Berurutan sesuai daftar: hadiah pertama habis dulu, baru lanjut hadiah berikutnya.'], ['Apakah aplikasi berbayar?','Gratis.'] ]; $('#panduanList').innerHTML=PANDUAN.map(x=>`
${x[0]}

${x[1]}

`).join(''); $('#faqList').innerHTML=FAQ.map(x=>`
${x[0]}

${x[1]}

`).join(''); /* ================= SETTING ================= */ function renderSetting(){ $('#sDpd').value=setting.dpd||'';$('#sKetua').value=setting.ketua||'';$('#sKetuaCs').value=setting.ketuaCs||''; } $('#btnSaveSet').onclick=()=>{ setting={dpd:$('#sDpd').value.trim(),ketua:$('#sKetua').value.trim(),ketuaCs:$('#sKetuaCs').value.trim().toUpperCase()}; saveAll();toast('Pengaturan disimpan βœ“','ok'); }; function renderNcs(){ const box=$('#listNcs'); if(!ncsList.length){box.innerHTML='
Belum ada petugas
';return;} box.innerHTML=ncsList.map((n,i)=>`
${esc(n.nama)}
${esc(n.cs||'')}
`).join(''); box.querySelectorAll('.h-x').forEach(b=>b.onclick=()=>{ncsList.splice(+b.dataset.i,1);saveAll();renderNcs();}); } $('#btnAddNcs').onclick=()=>{ const n=$('#sNcsNama').value.trim(),c=$('#sNcsCs').value.trim().toUpperCase(); if(!n){toast('Isi nama petugas','err');return;} ncsList.push({nama:n,cs:c});saveAll(); $('#sNcsNama').value='';$('#sNcsCs').value=''; renderNcs();toast('Petugas ditambahkan βœ“','ok'); }; $('#btnResetAll').onclick=()=>confirmBox('Reset SEMUA data?','Seluruh log peserta, hadiah, riwayat undian, dan pengaturan akan dihapus permanen dari browser ini.',()=>{ records=[];rc=1;hadiah=[];riwayat=[];lastWinners=new Set(); saveAll();renderList();renderHadiah();renderHist();toast('Semua data direset','ok'); }); /* ================= BACKUP / RESTORE ================= */ $('#btnBackup').onclick=()=>{ const data={ver:1,exportedAt:new Date().toISOString(),setting,ncsList,records,rc,hadiah,riwayat}; const blob=new Blob([JSON.stringify(data,null,1)],{type:'application/json'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download='backup_logsheet_'+new Date().toISOString().slice(0,10)+'.json'; a.click();URL.revokeObjectURL(a.href); toast('Backup tersimpan βœ“','ok'); }; $('#btnRestore').onclick=()=>$('#restoreFile').click(); $('#restoreFile').addEventListener('change',e=>{ const f=e.target.files[0];if(!f)return; const rd=new FileReader(); rd.onload=()=>{ try{ const d=JSON.parse(rd.result); if(!d.records||!Array.isArray(d.records))throw new Error('format'); confirmBox('Pulihkan backup?',`Data saat ini akan DIGANTI dengan backup (${d.records.length} peserta, ${(d.riwayat||[]).length} undian). Lanjutkan?`,()=>{ records=d.records;rc=d.rc||1;hadiah=d.hadiah||[];riwayat=d.riwayat||[]; setting=d.setting||setting;ncsList=d.ncsList||ncsList; lastWinners=new Set(riwayat.map(r=>r.cs)); saveAll();renderList();renderHadiah();renderHist();renderSetting();renderNcs();renderRC(); toast('Restore berhasil βœ“','ok'); }); }catch(err){toast('File backup tidak valid','err');} e.target.value=''; }; rd.readAsText(f); }); /* ================= NET STATUS ================= */ addEventListener('online',()=>refreshNetBadge(navigator.onLine)); addEventListener('offline',()=>refreshNetBadge(false)); /* ================= INIT ================= */ // Desktop: pindahkan nav ke atas konten (sebelum .wrap) if(matchMedia('(min-width:1024px)').matches){ const nav=document.getElementById('bnav'),wrap=document.querySelector('.wrap'); if(nav&&wrap)wrap.parentNode.insertBefore(nav,wrap); } window.__navMoved=matchMedia('(min-width:1024px)').matches; renderRC();renderList();renderHadiah();renderHist();renderSetting();renderNcs();renderRekap(); loadDB();