// Tambah Pengunjung JavaScript
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('addVisitorForm');
const namaAnakInput = document.getElementById('namaAnak');
const scanStatusDiv = document.getElementById('scanStatus');
const kodeGelangInput = document.getElementById('kodeGelang');
const noHpOrtuInput = document.getElementById('noHpOrtu');
const durationSelect = document.getElementById('durasi');
const priceDisplay = document.getElementById('priceDisplay');
const errorMessage = document.getElementById('errorMessage');
const successMessage = document.getElementById('successMessage');
const submitBtn = document.getElementById('submitBtn');
const loadingSpinner = document.getElementById('loadingSpinner');
const btnText = document.getElementById('btnText');
const endSessionModal = document.getElementById('endSessionModal');
const endSessionBtn = document.getElementById('endSessionBtn');
const cancelEndBtn = document.getElementById('cancelEndBtn');
const currentUserInfo = document.getElementById('currentUserInfo');
const unknownRfidModal = document.getElementById('unknownRfidModal'); // Get the new modal from HTML
const displayUnknownRfidCode = document.getElementById('displayUnknownRfidCode');
const closeUnknownRfidModalBtn = document.getElementById('closeUnknownRfidModalBtn');
// Price configuration
const prices = {
30: 15000, // 30 menit
60: 25000, // 1 jam
90: 35000, // 1.5 jam
120: 45000, // 2 jam
180: 60000, // 3 jam
240: 75000 // 4 jam
};
let currentKodeGelang = null;
let isFormEnabled = false;
let scanInterval = null;
// Start scanning process
function startScanning() {
if (scanInterval) {
clearInterval(scanInterval);
}
scanInterval = setInterval(async () => {
try {
const response = await fetch('../api/tambah_pengunjung.php?action=get_scanned_rfid');
const result = await response.json();
if (result.status === 'success' && result.data.scanned && result.data.kode_gelang) {
// Stop scanning while processing
clearInterval(scanInterval);
scanInterval = null;
// Check RFID status
await handleRfidScan(result.data.kode_gelang);
}
} catch (error) {
console.log('Background scan check failed:', error);
}
}, 2000);
}
// Handle RFID scan result
async function handleRfidScan(kodeGelang) {
try {
const response = await fetch('../api/tambah_pengunjung.php?action=check_rfid');
const result = await response.json();
// Sembunyikan pesan sukses/error yang mungkin ada sebelumnya
successMessage.style.display = 'none';
errorMessage.style.display = 'none';
if (result.status === 'available') {
// Gelang tersedia - bisa digunakan
kodeGelangInput.value = result.data.kode_gelang;
kodeGelangInput.classList.add('success');
kodeGelangInput.classList.remove('error');
currentKodeGelang = result.data.kode_gelang;
// Hide scan info
const scanInfo = document.querySelector('.scan-info');
if (scanInfo) scanInfo.style.display = 'none';
// Enable form
setFormEnabled(true);
showSuccess('Gelang berhasil di-scan, silakan isi data pengunjung.'); // Tambahkan pesan sukses
} else if (result.status === 'in_use') {
// Gelang sedang digunakan - tampilkan modal
setFormEnabled(false); // Nonaktifkan form utama
kodeGelangInput.classList.remove('success');
kodeGelangInput.classList.add('error');
showEndSessionModal(result.data); // Ini akan mengatur currentKodeGelang
} else if (result.status === 'error') {
// Gelang tidak dikenali (termasuk "Belum ada gelang yang di-scan" jika rfid_temp kosong)
setFormEnabled(false); // Nonaktifkan form utama
kodeGelangInput.classList.remove('success');
kodeGelangInput.classList.add('error');
// Tentukan pesan dan modal yang tampil
if (result.message === 'Gelang tidak dikenali') {
showUnknownRfidModal(kodeGelang); // Tampilkan modal gelang tidak dikenali
} else {
// Ini akan menangani 'Belum ada gelang yang di-scan' atau error lain dari check_rfid
showError(result.message || 'Terjadi kesalahan saat memeriksa gelang.');
}
// Penting: Clear temp dan restart scanning setelah menampilkan modal error/unknown
await clearRfidTemp();
setTimeout(() => {
startScanning();
}, 1000); // Tunggu sebentar sebelum restart
}
} catch (error) {
console.error('Error checking RFID:', error);
showError('Error memeriksa status gelang: ' + error.message); // Tampilkan detail error
// Clear temp dan restart scanning jika ada error koneksi
await clearRfidTemp();
setTimeout(() => {
startScanning();
}, 1000);
}
}
// Format currency
function formatCurrency(amount) {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
minimumFractionDigits: 0
}).format(amount);
}
// Format duration
function formatDuration(minutes) {
if (minutes < 60) {
return `${minutes} menit`;
} else {
const hours = minutes / 60;
return hours % 1 === 0 ? `${hours} jam` : `${hours} jam`;
}
}
// Update price display
function updatePriceDisplay() {
const selectedDuration = durationSelect.value;
if (selectedDuration) {
const duration = parseInt(selectedDuration);
const price = prices[duration];
const durationText = formatDuration(duration);
const priceText = formatCurrency(price);
priceDisplay.innerHTML = `
${durationText}
${priceText}
`;
} else {
priceDisplay.textContent = 'Pilih durasi untuk melihat harga';
}
}
// Enable/disable form
function setFormEnabled(enabled) {
isFormEnabled = enabled;
submitBtn.disabled = !enabled || !currentKodeGelang;
if (enabled) {
namaAnakInput.focus();
}
}
// Show end session modal
function showEndSessionModal(userData) {
const nama = userData.nama;
const kodeGelang = userData.kode_gelang;
const sisaWaktu = userData.sisa_waktu;
const statusWaktu = userData.status_waktu;
const colorClass = userData.color_class;
currentUserInfo.innerHTML = `
Nama: ${nama}
Kode Gelang: ${kodeGelang}
Sisa Waktu: ${sisaWaktu}
${statusWaktu === 'tersisa' ? 'Waktu masih tersisa' : 'Waktu sudah habis'}
`; endSessionModal.style.display = 'flex'; currentKodeGelang = kodeGelang; } // Hide end session modal function hideEndSessionModal() { endSessionModal.style.display = 'none'; currentKodeGelang = null; } // Show unknown RFID modal function showUnknownRfidModal(kodeGelang) { displayUnknownRfidCode.textContent = kodeGelang; unknownRfidModal.style.display = 'flex'; // currentKodeGelang = kodeGelang; // Bisa disimpan atau tidak, tergantung kebutuhan lebih lanjut } // Hide unknown RFID modal function hideUnknownRfidModal() { unknownRfidModal.style.display = 'none'; } // Clear RFID temp async function clearRfidTemp() { try { await fetch('../api/tambah_pengunjung.php?action=clear_temp', { method: 'POST' }); } catch (error) { console.error('Error clearing temp:', error); } } // End play session async function endPlaySession() { if (!currentKodeGelang) return; try { setLoading(true); const formData = new FormData(); formData.append('action', 'end_session'); formData.append('kode_gelang', currentKodeGelang); const response = await fetch('../api/tambah_pengunjung.php', { method: 'POST', body: formData }); const result = await response.json(); if (result.status === 'success') { showSuccess(result.message); hideEndSessionModal(); // Clear form and restart scanning resetForm(); setTimeout(() => { startScanning(); }, 2000); } else { showError(result.message); } } catch (error) { console.error('Error ending session:', error); showError('Error mengakhiri sesi permainan'); } finally { setLoading(false); } } // Reset form to initial state function resetForm() { form.reset(); // Reset all visual states document.querySelectorAll('.form-input, .form-select').forEach(field => { field.classList.remove('error', 'success'); }); // Reset kodeGelang input kodeGelangInput.value = ''; kodeGelangInput.classList.remove('error', 'success'); // Reset price display priceDisplay.textContent = 'Pilih durasi untuk melihat harga'; // Show scan info again const scanInfo = document.querySelector('.scan-info'); if (scanInfo) scanInfo.style.display = 'block'; // Reset form state setFormEnabled(false); currentKodeGelang = null; // Penting: Reset currentKodeGelang // NEW: Hide all modals and messages hideEndSessionModal(); hideUnknownRfidModal(); // Sembunyikan modal baru errorMessage.style.display = 'none'; successMessage.style.display = 'none'; } // Setup event listeners durationSelect.addEventListener('change', updatePriceDisplay); // Nama anak validation namaAnakInput.addEventListener('input', function() { const nama = this.value.trim(); if (nama.length >= 2) { this.classList.remove('error'); this.classList.add('success'); } else if (nama.length > 0) { this.classList.add('error'); this.classList.remove('success'); } else { this.classList.remove('error', 'success'); } }); // Phone number validation noHpOrtuInput.addEventListener('input', function() { let value = this.value.replace(/\D/g, ''); // Remove non-digits // Format phone number as user types if (value.startsWith('0')) { // Indonesian format starting with 0 if (value.length > 4) { value = value.substring(0, 4) + '-' + value.substring(4); } if (value.length > 9) { value = value.substring(0, 9) + '-' + value.substring(9); } } else if (value.startsWith('62')) { // Indonesian format starting with 62 if (value.length > 3) { value = value.substring(0, 3) + '-' + value.substring(3); } if (value.length > 8) { value = value.substring(0, 8) + '-' + value.substring(8); } } this.value = value; // Validation const cleanNumber = value.replace(/\D/g, ''); if (cleanNumber.length >= 10 && cleanNumber.length <= 15) { this.classList.remove('error'); this.classList.add('success'); } else if (cleanNumber.length > 0) { this.classList.add('error'); this.classList.remove('success'); } else { this.classList.remove('error', 'success'); } }); // Form validation function validateForm() { const namaAnak = namaAnakInput.value.trim(); const noHpOrtu = noHpOrtuInput.value.replace(/\D/g, ''); const selectedDuration = durationSelect.value; const kodeGelang = kodeGelangInput.value.trim(); let isValid = true; let errorMsg = ''; // Reset all field states document.querySelectorAll('.form-input, .form-select').forEach(field => { field.classList.remove('error'); }); // RFID validation first if (!kodeGelang) { isValid = false; errorMsg = 'Silakan scan gelang terlebih dahulu'; kodeGelangInput.classList.add('error'); return { isValid, errorMsg }; } // Nama anak validation if (namaAnak.length < 2) { isValid = false; errorMsg = 'Nama anak harus minimal 2 karakter'; namaAnakInput.classList.add('error'); } // Phone number validation if (noHpOrtu.length < 10 || noHpOrtu.length > 15) { isValid = false; errorMsg = 'Nomor HP harus 10-15 digit'; noHpOrtuInput.classList.add('error'); } // Duration validation if (!selectedDuration) { isValid = false; errorMsg = 'Silakan pilih durasi bermain'; durationSelect.classList.add('error'); } return { isValid, errorMsg }; } // Show error message function showError(message) { errorMessage.textContent = message; errorMessage.style.display = 'block'; successMessage.style.display = 'none'; // Scroll to top to show error document.querySelector('.login-right').scrollTop = 0; setTimeout(() => { errorMessage.style.display = 'none'; }, 5000); } // Show success message function showSuccess(message) { successMessage.textContent = message; successMessage.style.display = 'block'; errorMessage.style.display = 'none'; // Scroll to top to show success document.querySelector('.login-right').scrollTop = 0; setTimeout(() => { successMessage.style.display = 'none'; }, 3000); } // Set loading state function setLoading(loading) { if (loading) { submitBtn.disabled = true; loadingSpinner.style.display = 'inline-block'; btnText.textContent = 'Mendaftarkan...'; } else { // Tombol daftar harus tetap disabled jika form tidak enabled atau kode gelang belum valid submitBtn.disabled = !isFormEnabled || !currentKodeGelang; loadingSpinner.style.display = 'none'; btnText.textContent = 'Daftarkan Pengunjung'; } } // Form submission form.addEventListener('submit', async function(e) { e.preventDefault(); const validation = validateForm(); if (!validation.isValid) { showError(validation.errorMsg); return; } setLoading(true); // Prepare form data const formData = new FormData(); formData.append('action', 'add_visitor'); formData.append('kodeGelang', currentKodeGelang); formData.append('namaAnak', namaAnakInput.value.trim()); formData.append('noHpOrtu', noHpOrtuInput.value.replace(/\D/g, '')); formData.append('durasi', parseInt(durationSelect.value)); try { const response = await fetch('../api/tambah_pengunjung.php', { method: 'POST', body: formData }); // Check if response is ok if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const contentType = response.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { const text = await response.text(); console.error('Non-JSON response:', text); throw new Error('Server returned non-JSON response'); } const result = await response.json(); if (result.status === 'success') { showSuccess(result.message); // Stop scanning if (scanInterval) { clearInterval(scanInterval); scanInterval = null; } // Redirect after 2 seconds setTimeout(() => { window.location.href = 'dashboard.html'; }, 2000); } else { showError(result.message || 'Terjadi kesalahan saat mendaftarkan pengunjung'); // Handle specific field errors if (result.field === 'namaAnak') { namaAnakInput.classList.add('error'); namaAnakInput.focus(); } else if (result.field === 'noHpOrtu') { noHpOrtuInput.classList.add('error'); noHpOrtuInput.focus(); } else if (result.field === 'durasi') { durationSelect.classList.add('error'); durationSelect.focus(); } } } catch (error) { console.error('Error:', error); showError('Terjadi kesalahan koneksi. Silakan coba lagi.'); } finally { setLoading(false); } }); // End session modal handlers endSessionBtn.addEventListener('click', endPlaySession); cancelEndBtn.addEventListener('click', function() { hideEndSessionModal(); // Clear temp and start new scanning clearRfidTemp().then(() => { setTimeout(() => { startScanning(); }, 500); }); }); // Close modal when clicking outside endSessionModal.addEventListener('click', function(e) { if (e.target === endSessionModal) { hideEndSessionModal(); // Clear temp and start new scanning clearRfidTemp().then(() => { setTimeout(() => { startScanning(); }, 500); }); } }); // Close unknown RFID modal handlers closeUnknownRfidModalBtn.addEventListener('click', function() { hideUnknownRfidModal(); // Clear temp dan restart scanning setelah modal ditutup clearRfidTemp().then(() => { setTimeout(() => { startScanning(); }, 500); }); }); // Close unknown RFID modal when clicking outside unknownRfidModal.addEventListener('click', function(e) { if (e.target === unknownRfidModal) { hideUnknownRfidModal(); // Clear temp dan restart scanning setelah modal ditutup clearRfidTemp().then(() => { setTimeout(() => { startScanning(); }, 500); }); } }); // Clear temp when page is about to unload window.addEventListener('beforeunload', function() { if (scanInterval) { clearInterval(scanInterval); } // Clear temp data navigator.sendBeacon('../api/tambah_pengunjung.php?action=clear_temp'); }); // Clear temp when page loses focus window.addEventListener('blur', function() { clearRfidTemp(); }); // Check authentication status async function checkAuth() { try { const response = await fetch('../api/dashboard.php'); const result = await response.json(); if (result.status === 'error' && result.redirect) { window.location.href = result.redirect; } } catch (error) { console.error('Auth check failed:', error); } } // Initialize page checkAuth(); resetForm(); // Panggil resetForm untuk mengatur UI ke keadaan awal startScanning(); // Kemudian baru mulai scanning updatePriceDisplay(); // Pastikan harga tampil jika ada default selected });