TKK_E32222685/WEB-playground/assets/js/tambah_pengunjung.js

598 lines
21 KiB
JavaScript

// 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 = `
<strong>${durationText}</strong><br>
<span style="color: #6B46C1; font-size: 1.1em;">${priceText}</span>
`;
} 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 = `
<p><strong>Nama:</strong> ${nama}</p>
<p><strong>Kode Gelang:</strong> ${kodeGelang}</p>
<p><strong>Sisa Waktu:</strong> <span class="${colorClass}">${sisaWaktu}</span></p>
<p class="status-info ${statusWaktu === 'tersisa' ? 'text-green-600' : 'text-red-600'}">
${statusWaktu === 'tersisa' ? 'Waktu masih tersisa' : 'Waktu sudah habis'}
</p>
`;
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
});