document.addEventListener('DOMContentLoaded', function() { // Global variable for countdown interval let countdownInterval = null; // Elements for RFID modal const rfidStatusModal = document.getElementById('rfidStatusModal'); const closeRfidModal = document.getElementById('closeRfidModal'); const modalTitle = document.getElementById('modalTitle'); // Ini untuk RFID Modal const modalMessage = document.getElementById('modalMessage'); // Ini untuk RFID Modal const modalGelangCode = document.getElementById('modalGelangCode'); const modalUserData = document.getElementById('modalUserData'); const modalActionButton = document.getElementById('modalActionButton'); const modalCancelButton = document.getElementById('modalCancelButton'); // Elements for Logout Confirmation Modal const logoutConfirmModal = document.getElementById('logoutConfirmModal'); const closeLogoutModal = document.getElementById('closeLogoutModal'); const logoutModalTitle = document.getElementById('logoutModalTitle'); // <<< New ID const logoutModalMessage = document.getElementById('logoutModalMessage'); // <<< New ID const confirmLogoutBtn = document.getElementById('confirmLogoutBtn'); const cancelLogoutBtn = document.getElementById('cancelLogoutBtn'); // Store scanned RFID code globally for actions let currentScannedRfid = null; let currentKunjunganId = null; // To store kunjungan_id for ending session // Function to show a specific modal function showSpecificModal(modalElement) { modalElement.classList.add('show'); } // Function to hide a specific modal function hideSpecificModal(modalElement) { modalElement.classList.remove('show'); } // Event listeners for RFID modal close closeRfidModal.addEventListener('click', () => { hideSpecificModal(rfidStatusModal); clearRfidTemp(); // Clear temp RFID when RFID modal is closed by close button }); modalCancelButton.addEventListener('click', () => { hideSpecificModal(rfidStatusModal); clearRfidTemp(); // Clear temp RFID when RFID modal is closed by cancel button }); // Event listeners for Logout modal close closeLogoutModal.addEventListener('click', () => hideSpecificModal(logoutConfirmModal)); cancelLogoutBtn.addEventListener('click', () => hideSpecificModal(logoutConfirmModal)); // Handle clicks outside the modal content for both modals window.addEventListener('click', function(event) { if (event.target == rfidStatusModal) { hideSpecificModal(rfidStatusModal); // Clear temp RFID if the RFID modal is closed by clicking outside clearRfidTemp(); } if (event.target == logoutConfirmModal) { hideSpecificModal(logoutConfirmModal); } }); // Check authentication first checkAuthentication(); // Handle Logout Button const logoutButton = document.getElementById('logoutButton'); if (logoutButton) { logoutButton.addEventListener('click', function() { // Show the logout confirmation modal instead of direct logout showSpecificModal(logoutConfirmModal); }); } // Handle confirmation inside the logout modal confirmLogoutBtn.addEventListener('click', async function() { const originalHtml = confirmLogoutBtn.innerHTML; // Simpan HTML asli confirmLogoutBtn.innerHTML = ' Keluar...'; // Ikon spinner Font Awesome confirmLogoutBtn.disabled = true; cancelLogoutBtn.disabled = true; // Disable cancel button too try { const response = await fetch('../api/logout.php', { method: 'POST', headers: { 'Content-Type': 'application/json', } }); const result = await response.json(); if (result.status === 'success') { window.location.href = 'login.html'; } else { alert('Gagal logout: ' + (result.message || 'Pesan tidak diketahui.')); // Re-enable and reset button on failure confirmLogoutBtn.innerHTML = originalHtml; confirmLogoutBtn.disabled = false; cancelLogoutBtn.disabled = false; hideSpecificModal(logoutConfirmModal); // Hide modal on failure } } catch (error) { console.error('Error during logout:', error); alert('Terjadi kesalahan saat logout. Silakan coba lagi.'); // Re-enable and reset button on failure confirmLogoutBtn.innerHTML = originalHtml; confirmLogoutBtn.disabled = false; cancelLogoutBtn.disabled = false; hideSpecificModal(logoutConfirmModal); // Hide modal on failure // Redirect anyway in case of serious network error window.location.href = 'login.html'; } }); // Function to check authentication and get user info async function checkAuthentication() { try { const response = await fetch('../api/dashboard.php'); const result = await response.json(); if (result.status === 'error') { // Redirect to login if not authenticated window.location.href = result.redirect || 'login.html'; return; } if (result.status === 'success') { // Update username in the header const usernameElement = document.getElementById('adminUsername'); if (usernameElement && result.data.username) { usernameElement.textContent = result.data.username; } // Load active visitors data fetchActiveVisitors(); // Set up periodic refresh for active visitors if (window.activeVisitorsInterval) { clearInterval(window.activeVisitorsInterval); } window.activeVisitorsInterval = setInterval(fetchActiveVisitors, 30000); // Refresh every 30 seconds // Start RFID polling startRfidPolling(); } } catch (error) { console.error('Auth check error:', error); // Redirect to login on error window.location.href = 'login.html'; } } // Function to format seconds into HH:MM (and handle negative for overdue) function formatTime(seconds) { let prefix = ''; if (seconds < 0) { prefix = 'Telat '; seconds = Math.abs(seconds); } const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); let formatted = ''; if (h > 0) { formatted += h + ' jam '; } formatted += m + ' menit'; return prefix + formatted.trim(); } // Function to update countdowns for all visitors function updateAllCountdowns() { document.querySelectorAll('.countdown-timer').forEach(timerElement => { const waktuMasukTimestamp = parseInt(timerElement.dataset.waktuMasuk); const totalDurasiDetik = parseInt(timerElement.dataset.totalDurasi); const waktuSekarangMs = Date.now(); const waktuMasukMs = waktuMasukTimestamp * 1000; const waktuSelesaiMs = waktuMasukMs + (totalDurasiDetik * 1000); const sisaDetik = Math.floor((waktuSelesaiMs - waktuSekarangMs) / 1000); timerElement.textContent = formatTime(sisaDetik); if (sisaDetik <= 0) { timerElement.classList.remove('warning-time'); timerElement.classList.add('time-over'); timerElement.textContent = formatTime(sisaDetik); } else if (sisaDetik <= (10 * 60)) { timerElement.classList.add('warning-time'); timerElement.classList.remove('time-over'); } else { timerElement.classList.remove('warning-time', 'time-over'); } }); } // Function to fetch and display active visitors async function fetchActiveVisitors() { const activeVisitorsList = document.getElementById('activeVisitorsList'); activeVisitorsList.innerHTML = `
Memuat data pengunjung aktif...
Nama Pengunjung | No. HP | Kode Gelang | Durasi Tersisa | Wahana Terakhir | Waktu Masuk Kunjungan |
---|---|---|---|---|---|
${visitor.nama_anak} | ${displayNoHp} | ${visitor.kode_gelang} | ${visitor.wahana_terakhir} | ${displayWaktuMasuk} |
Tidak ada pengunjung yang sedang bermain di wahana saat ini.
Arahkan ke halaman Tambah Pengunjung untuk proses pendaftaran.
`; modalActionButton.textContent = 'Daftarkan Pengunjung'; modalActionButton.className = 'modal-action-btn'; // Reset class modalActionButton.dataset.status = 'available'; // Set status for action modalActionButton.onclick = async () => { // Make async to await clearRfidTemp await clearRfidTemp(); // <<< Call clearRfidTemp HERE before redirect window.location.href = `tambah_pengunjung.html?kode_gelang=${result.data.kode_gelang}`; }; showSpecificModal(rfidStatusModal); // Use showSpecificModal } else if (result.status === 'in_use') { modalTitle.textContent = 'Gelang Sedang Digunakan'; modalMessage.innerHTML = `Gelang dengan kode ${result.data.kode_gelang} berstatus: DIGUNAKAN.`; modalGelangCode.textContent = ``; // Clear this line const userData = result.data; modalUserData.innerHTML = `Nama Pengunjung: ${userData.nama}
Kode Gelang: ${userData.kode_gelang}
Sisa Waktu: ${userData.sisa_waktu}
`; modalActionButton.textContent = 'Akhiri Sesi Bermain'; modalActionButton.className = 'modal-action-btn logout-btn'; // Use red style modalActionButton.dataset.status = 'in_use'; // Set status for action currentKunjunganId = userData.id_kunjungan; // Store kunjungan_id modalActionButton.onclick = async () => { await endSession(userData.kode_gelang); await clearRfidTemp(); // <<< Call clearRfidTemp HERE after ending session }; showSpecificModal(rfidStatusModal); // Use showSpecificModal } else if (result.status === 'error' && result.message === 'Gelang tidak dikenali') { modalTitle.textContent = 'Gelang Tidak Terdaftar'; modalMessage.innerHTML = `Kode gelang ${kodeGelang} TIDAK TERDAFTAR di sistem.`; modalGelangCode.textContent = 'Silakan daftarkan gelang ini terlebih dahulu.'; modalUserData.innerHTML = `Arahkan ke halaman Tambah Pengunjung untuk mendaftarkan gelang baru.
`; modalActionButton.style.display = 'none'; // Hide action button showSpecificModal(rfidStatusModal); // Use showSpecificModal } else { // This case handles 'Belum ada gelang yang di-scan' or other generic errors modalTitle.textContent = 'Status Gelang RFID'; modalMessage.innerHTML = `Terjadi kesalahan saat memeriksa status gelang: ${result.message || 'Pesan tidak diketahui.'}`; modalGelangCode.textContent = `Kode Gelang: ${kodeGelang}`; modalUserData.innerHTML = ''; modalActionButton.style.display = 'none'; // Hide action button showSpecificModal(rfidStatusModal); // Use showSpecificModal } } catch (error) { console.error('Error checking RFID status:', error); modalTitle.textContent = 'Error Jaringan/Server'; modalMessage.innerHTML = `Terjadi kesalahan saat berkomunikasi dengan server. Coba lagi.`; modalGelangCode.textContent = `Kode Gelang: ${kodeGelang}`; modalUserData.innerHTML = ''; modalActionButton.style.display = 'none'; showSpecificModal(rfidStatusModal); // Use showSpecificModal } finally { // If the modal is shown due to 'unknown' or generic error, ensure polling restarts after close if (rfidPollingInterval === null) { // Only restart if it was stopped setTimeout(() => { startRfidPolling(); }, 1000); // Wait a bit before restarting polling } } } async function endSession(kodeGelang) { try { const response = await fetch('../api/tambah_pengunjung.php?action=end_session', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `kode_gelang=${encodeURIComponent(kodeGelang)}` }); const result = await response.json(); if (result.status === 'success') { alert(result.message); hideSpecificModal(rfidStatusModal); // Hide RFID modal fetchActiveVisitors(); // Refresh dashboard data } else { alert('Gagal mengakhiri sesi: ' + (result.message || 'Pesan tidak diketahui.')); } } catch (error) { console.error('Error ending session:', error); alert('Terjadi kesalahan saat mengakhiri sesi.'); } finally { currentScannedRfid = null; // Reset scanned RFID state // clearRfidTemp(); // Moved this call to modalActionButton.onclick } } // Function to clear rfid_temp table via API async function clearRfidTemp() { try { const response = await fetch('../api/tambah_pengunjung.php?action=clear_temp', { method: 'POST' }); const result = await response.json(); if (result.status === 'success') { console.log('RFID temp cleared successfully.'); } else { console.error('Failed to clear RFID temp:', result.message); } } catch (error) { console.error('Network error clearing RFID temp:', error); } } });