refactor detail-foto view to remove commented code and improve readability
This commit is contained in:
parent
dfe2eda9e7
commit
3ffa8ee33a
|
|
@ -128,31 +128,23 @@ class="detailfoto-thumb rounded-4">
|
||||||
</section>
|
</section>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<script>
|
<script>
|
||||||
// ============================================================
|
let countdown;
|
||||||
// 1. VARIABLE GLOBAL & UTILITIES
|
|
||||||
// ============================================================
|
|
||||||
let countdown; // Variabel untuk menyimpan timer
|
|
||||||
let isTimeUp = false;
|
let isTimeUp = false;
|
||||||
const durasiPaket = parseInt(document.getElementById('data-paket')?.dataset.durasi || 15);
|
const durasiPaket = parseInt(document.getElementById('data-paket')?.dataset.durasi || 15);
|
||||||
|
|
||||||
// Fungsi Update Counter (+/-) untuk Additional
|
|
||||||
function updateCounter(btn, change) {
|
function updateCounter(btn, change) {
|
||||||
const input = btn.parentElement.querySelector('input');
|
const input = btn.parentElement.querySelector('input');
|
||||||
let currentValue = parseInt(input.value) || 0;
|
let currentValue = parseInt(input.value) || 0;
|
||||||
let newValue = currentValue + change;
|
let newValue = currentValue + change;
|
||||||
|
|
||||||
if (newValue < 0) newValue = 0; // Cegah minus
|
if (newValue < 0) newValue = 0;
|
||||||
input.value = newValue;
|
input.value = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fungsi Tampilkan Kalender (Step 1 -> Step 2)
|
|
||||||
function showCalendar() {
|
function showCalendar() {
|
||||||
document.getElementById('btn-booking-wrapper').style.display = 'none';
|
document.getElementById('btn-booking-wrapper').style.display = 'none';
|
||||||
|
|
||||||
// DISABLE KOLOM KIRI
|
|
||||||
const leftColumn = document.getElementById('left-column');
|
const leftColumn = document.getElementById('left-column');
|
||||||
if (leftColumn) leftColumn.classList.add('disabled-section');
|
if (leftColumn) leftColumn.classList.add('disabled-section');
|
||||||
|
|
||||||
const calendarCol = document.getElementById('calendar-column');
|
const calendarCol = document.getElementById('calendar-column');
|
||||||
if (calendarCol) {
|
if (calendarCol) {
|
||||||
calendarCol.classList.remove('d-none');
|
calendarCol.classList.remove('d-none');
|
||||||
|
|
@ -164,57 +156,39 @@ function showCalendar() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fungsi Sembunyikan Kalender (Tombol Batalkan)
|
|
||||||
function hideCalendar() {
|
function hideCalendar() {
|
||||||
if (countdown) clearInterval(countdown);
|
if (countdown) clearInterval(countdown);
|
||||||
|
|
||||||
document.getElementById('calendar-column').classList.add('d-none');
|
document.getElementById('calendar-column').classList.add('d-none');
|
||||||
document.getElementById('btn-booking-wrapper').style.display = 'block';
|
document.getElementById('btn-booking-wrapper').style.display = 'block';
|
||||||
|
|
||||||
// ENABLE KEMBALI KOLOM KIRI
|
|
||||||
const leftColumn = document.getElementById('left-column');
|
const leftColumn = document.getElementById('left-column');
|
||||||
if (leftColumn) leftColumn.classList.remove('disabled-section');
|
if (leftColumn) leftColumn.classList.remove('disabled-section');
|
||||||
|
|
||||||
// Scroll kembali ke atas (opsional, agar user sadar kolom kiri aktif lagi)
|
|
||||||
leftColumn.scrollIntoView({
|
leftColumn.scrollIntoView({
|
||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset pilihan tanggal & jam di input hidden
|
|
||||||
document.getElementById('input_tgl_booking').value = "";
|
document.getElementById('input_tgl_booking').value = "";
|
||||||
document.getElementById('input_jam_mulai').value = "";
|
document.getElementById('input_jam_mulai').value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fungsi Timer Mundur
|
|
||||||
function startTimer(duration) {
|
function startTimer(duration) {
|
||||||
let timer = duration,
|
let timer = duration,
|
||||||
minutes, seconds;
|
minutes, seconds;
|
||||||
const display = document.querySelector('#booking-timer');
|
const display = document.querySelector('#booking-timer');
|
||||||
const submitBtn = document.querySelector('.btn-action-submit'); // Pastikan class tombol benar
|
const submitBtn = document.querySelector('.btn-action-submit');
|
||||||
|
isTimeUp = false;
|
||||||
isTimeUp = false; // Reset status setiap timer mulai
|
|
||||||
if (countdown) clearInterval(countdown);
|
if (countdown) clearInterval(countdown);
|
||||||
|
|
||||||
countdown = setInterval(function() {
|
countdown = setInterval(function() {
|
||||||
minutes = parseInt(timer / 60, 10);
|
minutes = parseInt(timer / 60, 10);
|
||||||
seconds = parseInt(timer % 60, 10);
|
seconds = parseInt(timer % 60, 10);
|
||||||
|
|
||||||
minutes = minutes < 10 ? "0" + minutes : minutes;
|
minutes = minutes < 10 ? "0" + minutes : minutes;
|
||||||
seconds = seconds < 10 ? "0" + seconds : seconds;
|
seconds = seconds < 10 ? "0" + seconds : seconds;
|
||||||
|
|
||||||
if (display) display.textContent = minutes + ":" + seconds;
|
if (display) display.textContent = minutes + ":" + seconds;
|
||||||
|
|
||||||
if (--timer < 0) {
|
if (--timer < 0) {
|
||||||
clearInterval(countdown);
|
clearInterval(countdown);
|
||||||
isTimeUp = true; // Kunci status
|
isTimeUp = true;
|
||||||
|
|
||||||
// Matikan tombol submit secara visual
|
|
||||||
if (submitBtn) {
|
if (submitBtn) {
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.classList.add('disabled');
|
submitBtn.classList.add('disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tampilkan alert
|
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Waktu Habis!',
|
title: 'Waktu Habis!',
|
||||||
text: 'Sesi booking Anda telah berakhir. Silakan pilih ulang jadwal.',
|
text: 'Sesi booking Anda telah berakhir. Silakan pilih ulang jadwal.',
|
||||||
|
|
@ -223,13 +197,12 @@ function startTimer(duration) {
|
||||||
confirmButtonColor: '#3B8181',
|
confirmButtonColor: '#3B8181',
|
||||||
allowOutsideClick: false
|
allowOutsideClick: false
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
location.reload(); // Refresh halaman
|
location.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Hitung Jam Selesai
|
|
||||||
function calculateEndTime(startTime, duration) {
|
function calculateEndTime(startTime, duration) {
|
||||||
let [hours, minutes] = startTime.split(':').map(Number);
|
let [hours, minutes] = startTime.split(':').map(Number);
|
||||||
minutes += duration;
|
minutes += duration;
|
||||||
|
|
@ -241,27 +214,14 @@ function calculateEndTime(startTime, duration) {
|
||||||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// 2. LOGIC AJAX & INTERAKSI KALENDER
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
// A. Fungsi Ganti Bulan (Tanpa Refresh)
|
|
||||||
function changeMonth(month, year) {
|
function changeMonth(month, year) {
|
||||||
const wrapper = document.getElementById('calendar-grid-wrapper');
|
const wrapper = document.getElementById('calendar-grid-wrapper');
|
||||||
|
|
||||||
// Efek loading
|
|
||||||
wrapper.style.opacity = '0.5';
|
wrapper.style.opacity = '0.5';
|
||||||
|
|
||||||
// Panggil Controller via AJAX
|
|
||||||
fetch(`/load-calendar?month=${month}&year=${year}`)
|
fetch(`/load-calendar?month=${month}&year=${year}`)
|
||||||
.then(response => response.json()) // Pastikan controller return JSON { html: "..." }
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// Ganti isi wrapper dengan HTML baru dari server
|
|
||||||
wrapper.innerHTML = data.html;
|
wrapper.innerHTML = data.html;
|
||||||
wrapper.style.opacity = '1';
|
wrapper.style.opacity = '1';
|
||||||
|
|
||||||
// PENTING: Pasang ulang listener karena elemen HTML-nya baru
|
|
||||||
reinitDateListeners();
|
reinitDateListeners();
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
|
|
@ -270,54 +230,37 @@ function changeMonth(month, year) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// B. Pasang Event Listener ke Tanggal (Re-usable)
|
|
||||||
function reinitDateListeners() {
|
function reinitDateListeners() {
|
||||||
const dateItems = document.querySelectorAll('.date-item:not(.disabled):not(.empty)');
|
const dateItems = document.querySelectorAll('.date-item:not(.disabled):not(.empty)');
|
||||||
|
|
||||||
dateItems.forEach(item => {
|
dateItems.forEach(item => {
|
||||||
item.addEventListener('click', function() {
|
item.addEventListener('click', function() {
|
||||||
// UI: Reset warna selected lama
|
|
||||||
document.querySelectorAll('.date-item').forEach(el => el.classList.remove('selected'));
|
document.querySelectorAll('.date-item').forEach(el => el.classList.remove('selected'));
|
||||||
this.classList.add('selected');
|
this.classList.add('selected');
|
||||||
|
|
||||||
// Logic: Simpan tanggal ke input hidden
|
|
||||||
const tgl = this.dataset.date;
|
const tgl = this.dataset.date;
|
||||||
const tglInput = document.getElementById('input_tgl_booking');
|
const tglInput = document.getElementById('input_tgl_booking');
|
||||||
if (tglInput) tglInput.value = tgl;
|
if (tglInput) tglInput.value = tgl;
|
||||||
|
|
||||||
// Logic: Cek Slot ke Database
|
|
||||||
checkSlotAvailability(tgl);
|
checkSlotAvailability(tgl);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// C. Cek Slot Penuh via AJAX
|
|
||||||
function checkSlotAvailability(tgl) {
|
function checkSlotAvailability(tgl) {
|
||||||
// 1. Reset semua tombol jam jadi aktif dulu
|
|
||||||
const allTimeBtns = document.querySelectorAll('.btn-time');
|
const allTimeBtns = document.querySelectorAll('.btn-time');
|
||||||
allTimeBtns.forEach(btn => {
|
allTimeBtns.forEach(btn => {
|
||||||
btn.classList.remove('disabled', 'full', 'active');
|
btn.classList.remove('disabled', 'full', 'active');
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
btn.title = "";
|
btn.title = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. Kosongkan input jam (karena user ganti tanggal)
|
|
||||||
document.getElementById('input_jam_mulai').value = "";
|
document.getElementById('input_jam_mulai').value = "";
|
||||||
const sekarang = new Date();
|
const sekarang = new Date();
|
||||||
const jamSekarang = sekarang.getHours();
|
const jamSekarang = sekarang.getHours();
|
||||||
const menitSekarang = sekarang.getMinutes();
|
const menitSekarang = sekarang.getMinutes();
|
||||||
const totalMenitSekarang = (jamSekarang * 60) + menitSekarang;
|
const totalMenitSekarang = (jamSekarang * 60) + menitSekarang;
|
||||||
|
|
||||||
// Format tanggal hari ini (YYYY-MM-DD) untuk perbandingan
|
|
||||||
const hariIni = sekarang.toISOString().split('T')[0];
|
const hariIni = sekarang.toISOString().split('T')[0];
|
||||||
|
|
||||||
// 3. LOGIKA JAM LEWAT: Jika tanggal yang diklik adalah hari ini
|
|
||||||
if (tgl === hariIni) {
|
if (tgl === hariIni) {
|
||||||
allTimeBtns.forEach(btn => {
|
allTimeBtns.forEach(btn => {
|
||||||
const [jamBtn, menitBtn] = btn.dataset.time.split(':').map(Number);
|
const [jamBtn, menitBtn] = btn.dataset.time.split(':').map(Number);
|
||||||
const totalMenitBtn = (jamBtn * 60) + menitBtn;
|
const totalMenitBtn = (jamBtn * 60) + menitBtn;
|
||||||
|
|
||||||
// Jika waktu pada tombol sudah lewat dari waktu sekarang
|
|
||||||
if (totalMenitBtn <= totalMenitSekarang) {
|
if (totalMenitBtn <= totalMenitSekarang) {
|
||||||
btn.classList.add('disabled', 'full');
|
btn.classList.add('disabled', 'full');
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
|
|
@ -325,75 +268,47 @@ function checkSlotAvailability(tgl) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 3. Panggil Server
|
|
||||||
fetch(`/cek-slot-foto?tanggal=${tgl}`)
|
fetch(`/cek-slot-foto?tanggal=${tgl}`)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
data.forEach(booking => {
|
data.forEach(booking => {
|
||||||
// Ambil jam depan saja (09:00:00 -> 09:00)
|
|
||||||
const jamPenuh = booking.jam_mulai.substring(0, 5);
|
const jamPenuh = booking.jam_mulai.substring(0, 5);
|
||||||
|
|
||||||
// Cari tombol yg punya data-time sama
|
|
||||||
const btnPenuh = document.querySelector(`.btn-time[data-time="${jamPenuh}"]`);
|
const btnPenuh = document.querySelector(`.btn-time[data-time="${jamPenuh}"]`);
|
||||||
|
|
||||||
if (btnPenuh) {
|
if (btnPenuh) {
|
||||||
btnPenuh.classList.add('disabled', 'full'); // Tambah class styling
|
btnPenuh.classList.add('disabled', 'full');
|
||||||
btnPenuh.disabled = true; // Matikan klik
|
btnPenuh.disabled = true;
|
||||||
btnPenuh.title = "Slot Sudah Terisi";
|
btnPenuh.title = "Slot Sudah Terisi";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => console.error("Gagal cek slot:", err));
|
.catch(err => console.error("Gagal cek slot:", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// 3. INISIALISASI SAAT HALAMAN DIMUAT (DOM READY)
|
|
||||||
// ============================================================
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
// 1. Jalankan Listener Tanggal (Untuk kalender mulai)
|
|
||||||
reinitDateListeners();
|
reinitDateListeners();
|
||||||
|
|
||||||
// 2. Pasang Listener Tombol Jam (Cukup sekali)
|
|
||||||
const timeButtons = document.querySelectorAll('.btn-time');
|
const timeButtons = document.querySelectorAll('.btn-time');
|
||||||
timeButtons.forEach(btn => {
|
timeButtons.forEach(btn => {
|
||||||
btn.addEventListener('click', function(e) {
|
btn.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Cek jika tombol disabled (safety)
|
|
||||||
if (this.disabled || this.classList.contains('disabled')) return;
|
if (this.disabled || this.classList.contains('disabled')) return;
|
||||||
|
|
||||||
// UI: Reset active
|
|
||||||
timeButtons.forEach(el => el.classList.remove('active'));
|
timeButtons.forEach(el => el.classList.remove('active'));
|
||||||
this.classList.add('active');
|
this.classList.add('active');
|
||||||
|
|
||||||
// Logic: Simpan Jam
|
|
||||||
const startTime = this.dataset.time;
|
const startTime = this.dataset.time;
|
||||||
document.getElementById('input_jam_mulai').value = startTime;
|
document.getElementById('input_jam_mulai').value = startTime;
|
||||||
|
|
||||||
// Logic: Hitung Jam Selesai
|
|
||||||
const endTime = calculateEndTime(startTime, durasiPaket);
|
const endTime = calculateEndTime(startTime, durasiPaket);
|
||||||
document.getElementById('input_jam_selesai').value = endTime;
|
document.getElementById('input_jam_selesai').value = endTime;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3. Validasi Submit Form
|
|
||||||
// 3. Validasi Submit Form
|
|
||||||
const bookingForm = document.getElementById('form-booking');
|
const bookingForm = document.getElementById('form-booking');
|
||||||
if (bookingForm) {
|
if (bookingForm) {
|
||||||
bookingForm.addEventListener('submit', function(e) {
|
bookingForm.addEventListener('submit', function(e) {
|
||||||
const tgl = document.getElementById('input_tgl_booking').value;
|
const tgl = document.getElementById('input_tgl_booking').value;
|
||||||
const jam = document.getElementById('input_jam_mulai').value;
|
const jam = document.getElementById('input_jam_mulai').value;
|
||||||
|
|
||||||
// CEK APAKAH WAKTU HABIS
|
|
||||||
if (isTimeUp) {
|
if (isTimeUp) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Swal.fire('Maaf!', 'Waktu booking sudah habis, halaman akan dimuat ulang.', 'error')
|
Swal.fire('Maaf!', 'Waktu booking sudah habis, halaman akan dimuat ulang.', 'error')
|
||||||
.then(() => location.reload());
|
.then(() => location.reload());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tgl || !jam) {
|
if (!tgl || !jam) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue