1080 lines
40 KiB
JavaScript
1080 lines
40 KiB
JavaScript
// =======================
|
||
// DATA SETUP
|
||
// =======================
|
||
let checkout_biodata = JSON.parse(sessionStorage.getItem('checkout_biodata') || '{}');
|
||
let order_id = sessionStorage.getItem('order_id') || '[]';
|
||
// =======================
|
||
// EVENT ON LOAD
|
||
// =======================
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const checkCart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
|
||
|
||
const validChart = checkCart.length > 0 && checkCart.every(item =>
|
||
Array.isArray(item.pesanan) &&
|
||
item.pesanan.length > 0
|
||
);
|
||
if(!validChart){
|
||
window.location.href ='/';
|
||
return
|
||
}
|
||
|
||
|
||
|
||
|
||
$("#cartButton").addClass('d-none');
|
||
$("#no_order_result").val(order_id)
|
||
let currentStep = 0;
|
||
let orderDate=''
|
||
let deadline=''
|
||
let time_order=''
|
||
// Setup button step
|
||
document.querySelectorAll('.next-step').forEach(btn => {
|
||
btn.addEventListener('click', async () => {
|
||
const btnLoad = btn;
|
||
btnLoad.disabled = true;
|
||
btnLoad.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Memproses...';
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
try {
|
||
if (cart.length === 0) {
|
||
window.location.href = "/";
|
||
return;
|
||
}
|
||
if (currentStep === 0){
|
||
if(!validateStepOne()) return
|
||
isiKonfirmasi();
|
||
currentStep++; showStep(currentStep);
|
||
}else if(currentStep === 1){
|
||
const {isValid, errorMessage} =validateCartBeforeSubmit();
|
||
if (!isValid) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: errorMessage,
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return
|
||
}
|
||
let checkout_biodata = JSON.parse(sessionStorage.getItem('checkout_biodata') || '{}');
|
||
|
||
if (!checkout_biodata.nama_pemesan) {
|
||
Swal.fire({
|
||
title: 'Biodata Belum Terisi!',
|
||
text: 'Lakukan Pengisian biodata terlebih dahulu.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'oke!',
|
||
}).then(() => {
|
||
window.location.href = "/checkout";
|
||
});
|
||
return
|
||
}
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
for (const item of cart) {
|
||
for (const p of item.pesanan) {
|
||
const result = validateTanggalPemesanan(item, p.tgl);
|
||
|
||
if (!result.valid) {
|
||
alert(result.message);
|
||
return; // hentikan di sini, tidak lanjut
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (!sessionStorage.getItem('order_id')) {
|
||
await submitOrderToServer(); // async function simpan ke server
|
||
|
||
}
|
||
|
||
time_order = sessionStorage.getItem('time_order')
|
||
orderDate = new Date(time_order);
|
||
deadline = new Date(orderDate.getTime() + 10 * 60 * 1000)
|
||
updateCountdown()
|
||
currentStep++;
|
||
showStep(currentStep)
|
||
}else if(currentStep === 2){
|
||
renderCartSummary()
|
||
}
|
||
} catch (error) {
|
||
console.error(error);
|
||
Swal.fire('Error', 'Terjadi kesalahan, silakan coba lagi.', 'error');
|
||
}finally{
|
||
btnLoad.disabled = false;
|
||
btnLoad.innerHTML = 'Selanjutnya';
|
||
}
|
||
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('.prev-step').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
if (cart.length === 0) {
|
||
window.location.href = "/";
|
||
return;
|
||
}
|
||
if (currentStep > 0) {
|
||
currentStep--;
|
||
showStep(currentStep);
|
||
}
|
||
});
|
||
});
|
||
|
||
// Inisialisasi tampilan dan data
|
||
renderCartSummary();
|
||
showStep(currentStep);
|
||
isiKonfirmasi();
|
||
toggleCustomerFields()
|
||
document.getElementById('no_order_display').textContent = order_id
|
||
|
||
const countDownPayment = document.getElementById('countdownPayment')
|
||
|
||
|
||
function orderTimeCheck(){
|
||
const checkTimeOrder = sessionStorage.getItem('time_order');
|
||
if (checkTimeOrder) {
|
||
const orderTime = new Date(checkTimeOrder);
|
||
|
||
const now = new Date();
|
||
|
||
// Jika time_order tidak valid (misalnya null, NaN, atau invalid date)
|
||
if (isNaN(orderTime.getTime())) {
|
||
console.warn('Waktu order tidak valid di session.');
|
||
sessionStorage.clear(); // bisa juga removeItem satu per satu
|
||
window.location.href = "/";
|
||
return;
|
||
}
|
||
|
||
const selisihMs = now.getTime() - orderTime.getTime();
|
||
const selisihMenit = selisihMs / 1000 / 60;
|
||
|
||
if (selisihMenit > 10) {
|
||
// Bersihkan session
|
||
sessionStorage.removeItem('cart');
|
||
sessionStorage.removeItem('checkout_biodata');
|
||
sessionStorage.removeItem('order_id');
|
||
sessionStorage.removeItem('time_order');
|
||
|
||
Swal.fire({
|
||
title: 'Waktu pembayaran sudah lewat!',
|
||
text: 'Silakan lakukan pemesanan ulang.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
}).then(() => {
|
||
window.location.href = "/";
|
||
});
|
||
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
function updateCountdown(){
|
||
const now = new Date();
|
||
orderDate = new Date(time_order);
|
||
deadline = new Date(orderDate.getTime() + 10 * 60 * 1000)
|
||
const distance = deadline - now
|
||
|
||
if(distance <= 0){
|
||
countDownPayment.textContent = "Waktu Habis Lakukan Pemesanan Ulang";
|
||
return;
|
||
}
|
||
|
||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))
|
||
const seconds = Math.floor((distance % (1000 * 60)) / 1000)
|
||
|
||
countDownPayment.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
|
||
}
|
||
|
||
updateCountdown();
|
||
orderTimeCheck();
|
||
const interval = setInterval(() => {
|
||
updateCountdown()
|
||
orderTimeCheck()
|
||
if(new Date() >= deadline) clearInterval(interval)
|
||
}, 1000)
|
||
|
||
});
|
||
// =======================
|
||
// FUNGSI STEP
|
||
// =======================
|
||
const steps = document.querySelectorAll('.form-step');
|
||
const progressBar = document.getElementById('stepProgressBar');
|
||
|
||
function showStep(index) {
|
||
steps.forEach((step, i) => {
|
||
step.classList.toggle('active', i === index);
|
||
step.classList.toggle('d-none', i !== index);
|
||
});
|
||
const total = steps.length;
|
||
const progress = ((index + 1) / total) * 100;
|
||
progressBar.style.width = progress + '%';
|
||
progressBar.innerText = `Langkah ${index + 1} dari ${total}`;
|
||
for(let i = 1; i <= total; i++){
|
||
const circle = document.getElementById(`step-circle-${i}`)
|
||
if(circle){
|
||
circle.classList.toggle('active', i === index + 1)
|
||
}
|
||
}
|
||
}
|
||
|
||
// =======================
|
||
// FUNGSI BIODATA
|
||
// =======================
|
||
function toggleCustomerFields() {
|
||
const selected = $('input[name="jenis_customer"]:checked').val();
|
||
const $nama = $('#nama_pemesan');
|
||
|
||
// Sembunyikan semua section
|
||
$('.karyawan, .pasien, .umum').hide();
|
||
|
||
// Destroy jika sudah ada selectize
|
||
if ($nama[0] && $nama[0].selectize) {
|
||
$nama[0].selectize.destroy();
|
||
}
|
||
|
||
|
||
switch (selected) {
|
||
case 'Karyawan RSAB Harapan Kita':
|
||
$('.karyawan').show();
|
||
$nama.val('')
|
||
$nama.removeClass('form-control')
|
||
$("#help_nama_pemesan").removeClass('d-none')
|
||
$("#help_email_karyawan").removeClass('d-none')
|
||
selectKaryawan(); // inisialisasi ulang selectize
|
||
break;
|
||
case 'Keluarga Pasien / Penunggu Pasien':
|
||
$('.pasien').show();
|
||
$nama.addClass('form-control')
|
||
$("#help_nama_pemesan").addClass('d-none')
|
||
$("#help_email_karyawan").addClass('d-none')
|
||
break;
|
||
|
||
default: // Masyarakat Umum
|
||
$('.umum').show();
|
||
$nama.addClass('form-control')
|
||
$("#help_nama_pemesan").addClass('d-none')
|
||
$("#help_email_karyawan").addClass('d-none')
|
||
break;
|
||
}
|
||
}
|
||
$('input[name="jenis_customer"]').on('change', toggleCustomerFields);
|
||
toggleCustomerFields();
|
||
|
||
if (typeof checkout_biodata === 'object') {
|
||
if (checkout_biodata.jenis_customer) {
|
||
$(`input[name="jenis_customer"][value="${checkout_biodata.jenis_customer}"]`).prop('checked', true);
|
||
}
|
||
if(checkout_biodata.jenis_kelamin){
|
||
$(`input[name="jenis_kelamin"][value="${checkout_biodata.jenis_kelamin}"]`).prop('checked', true);
|
||
}
|
||
if(checkout_biodata.jenis_customer !== 'Karyawan RSAB Harapan Kita'){
|
||
$('#nama_pemesan').val(checkout_biodata.nama_pemesan);
|
||
}
|
||
// $('#tanggal_lahir').val(checkout_biodata.tanggal_lahir);
|
||
$('#tinggi_badan').val(checkout_biodata.tinggi_badan);
|
||
$('#berat_badan').val(checkout_biodata.berat_badan);
|
||
$('#no_whatsapp').val(checkout_biodata.no_whatsapp);
|
||
$('#nama_pasien').val(checkout_biodata.nama_pasien);
|
||
$('#ruang_perawatan').val(checkout_biodata.ruang_perawatan);
|
||
$('#no_kamar').val(checkout_biodata.no_kamar);
|
||
$('#kelas_perawatan').val(checkout_biodata.kelas_perawatan);
|
||
$('#bagian_instalasi').val(checkout_biodata.bagian_instalasi);
|
||
$('#no_ekstensien').val(checkout_biodata.no_ekstensien);
|
||
$('#email').val(checkout_biodata.email);
|
||
$('#alamat').val(checkout_biodata.alamat);
|
||
}
|
||
|
||
function isiKonfirmasi() {
|
||
const biodata = {
|
||
jenis_customer: $('input[name="jenis_customer"]:checked').val(),
|
||
nama_pemesan: $('#nama_pemesan').val(),
|
||
jenis_kelamin: $('input[name="jenis_kelamin"]:checked').val(),
|
||
id_karyawan: $('#id_karyawan').val(),
|
||
tinggi_badan: $('#tinggi_badan').val(),
|
||
berat_badan: $('#berat_badan').val(),
|
||
no_whatsapp: $('#no_whatsapp').val(),
|
||
nama_pasien: $('#nama_pasien').val(),
|
||
ruang_perawatan: $('#ruang_perawatan').val(),
|
||
no_kamar: $('#no_kamar').val(),
|
||
kelas_perawatan: $('#kelas_perawatan').val(),
|
||
bagian_instalasi: $('#bagian_instalasi').val(),
|
||
no_ekstensien: $('#no_ekstensien').val(),
|
||
email: $('#email').val(),
|
||
alamat: $('#alamat').val(),
|
||
};
|
||
|
||
sessionStorage.setItem('checkout_biodata', JSON.stringify(biodata));
|
||
checkout_biodata = biodata;
|
||
renderCartSummary();
|
||
}
|
||
|
||
// =======================
|
||
// FUNGSI CART / PESANAN
|
||
// =======================
|
||
function renderCartSummary() {
|
||
const container = document.getElementById('checkout_cart_summary');
|
||
container.innerHTML = '';
|
||
let totalKeseluruhan = 0;
|
||
const carts = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const checkout_biodata = JSON.parse(sessionStorage.getItem('checkout_biodata') || '[]');
|
||
|
||
carts.forEach((item) => {
|
||
const pesananList = Array.isArray(item.pesanan) ? item.pesanan : [];
|
||
let pesananHTML = '';
|
||
const harga = checkout_biodata.jenis_customer === 'Karyawan RSAB Harapan Kita'
|
||
? item.harga_karyawan || 0
|
||
: item.harga_public || 0;
|
||
const itemTotal = pesananList.reduce((sum, p) => sum + (p.jumlah * harga), 0);
|
||
|
||
if (checkout_biodata.jenis_customer === "Karyawan RSAB Harapan Kita") {
|
||
$('#karyawan').removeClass('d-none');
|
||
$('#pasien').addClass('d-none');
|
||
} else if (checkout_biodata.jenis_customer === "Keluarga Pasien / Penunggu Pasien") {
|
||
$('#karyawan').addClass('d-none');
|
||
$('#pasien').removeClass('d-none');
|
||
} else {
|
||
$('#karyawan').addClass('d-none');
|
||
$('#pasien').addClass('d-none');
|
||
}
|
||
|
||
|
||
totalKeseluruhan += itemTotal;
|
||
pesananList.forEach((p, i) => {
|
||
const selectedDate = new Date(p.tgl);
|
||
const now = new Date();
|
||
const isToday = selectedDate.toDateString() === now.toDateString();
|
||
const jam = now.getHours();
|
||
const disableSiang = isToday && jam >= 10;
|
||
const disableSore = isToday && jam >= 13;
|
||
const countDate = pesananList.length;
|
||
|
||
|
||
pesananHTML += `
|
||
<div class="rounded border p-3 mb-3 shadow-sm" data-item-id="${item.id}" data-index="${i}">
|
||
<div class="row g-3 align-items-center">
|
||
|
||
<!-- Note -->
|
||
<div class="col-12 col-md-2">
|
||
<button type="button" class="btn btn-outline-success" onclick="notedOrder(${item.id}, ${i})" title="Catatan">
|
||
<i class="fa-solid fa-note-sticky"></i> Catatan
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Tanggal -->
|
||
<div class="col-12 col-md-2">
|
||
<input type="text" class="form-control form-control-sm tanggal-input" id="tanggal-${item.id}-${i}" readonly placeholder="Pilih Tanggal">
|
||
</div>
|
||
|
||
<!-- Karbohidrat -->
|
||
${item.apakah_someday ? `` : `
|
||
<div class="col-12 col-md-3">
|
||
<select class="form-select form-select-sm karbohidrat-input" onChange="onKarbohidratChange(${item.id}, ${i}, this, ${item.kalori})">
|
||
<option disabled selected>Pilih Karbohidrat</option>
|
||
${(karhohidrats || []).map(k => `
|
||
<option value="${k.karbohidrat_id}" ${p.karbohidrat_id === k.karbohidrat_id ? 'selected' : ''} data-kalori=${k.nilai_kalori}>
|
||
${k.nama_karbohidrat} ${k.nilai_kalori ? `(${k.nilai_kalori} kal)` : ''}
|
||
</option>
|
||
`).join('')}
|
||
</select>
|
||
</div>`}
|
||
|
||
<!-- Waktu Makan -->
|
||
<div class="col-12 col-md-2">
|
||
<select class="form-select form-select-sm kategori-pemesanan-input"
|
||
data-item-id="${item.id}" data-index="${i}"
|
||
onchange="onKategoriChange(${item.id}, ${i}, ${isToday})"
|
||
onfocus="this.dataset.previousValue = this.value"
|
||
${item.apakah_menu_siang || item.apakah_menu_sore ? '' : 'disabled'}>
|
||
${
|
||
item.apakah_someday
|
||
? (
|
||
item.apakah_menu_siang && item.apakah_menu_sore
|
||
? `
|
||
<option value="Makan Siang" ${p.kategoriPemesanan === 'Makan Siang' ? 'selected' : ''} ${disableSiang ? 'disabled' : ''}>Makan Siang</option>
|
||
<option value="Makan Sore" ${p.kategoriPemesanan === 'Makan Sore' ? 'selected' : ''} ${disableSore ? 'disabled' : ''}>Makan Sore</option>
|
||
`
|
||
: item.apakah_menu_siang
|
||
? `<option value="Makan Siang" selected ${disableSiang ? 'disabled' : ''}>Makan Siang</option>`
|
||
: item.apakah_menu_sore
|
||
? `<option value="Makan Sore" selected ${disableSore ? 'disabled' : ''}>Makan Sore</option>`
|
||
: `<option value="" disabled selected>Tidak tersedia</option>`
|
||
)
|
||
: (
|
||
item.apakah_menu_siang && item.apakah_menu_sore
|
||
? `
|
||
<option value="Makan Siang" ${p.kategoriPemesanan === 'Makan Siang' ? 'selected' : ''}>Makan Siang</option>
|
||
<option value="Makan Sore" ${p.kategoriPemesanan === 'Makan Sore' ? 'selected' : ''}>Makan Sore</option>
|
||
`
|
||
: item.apakah_menu_siang
|
||
? `<option value="Makan Siang" selected>Makan Siang</option>`
|
||
: item.apakah_menu_sore
|
||
? `<option value="Makan Sore" selected>Makan Sore</option>`
|
||
: `<option value="" disabled selected>Tidak tersedia</option>`
|
||
)
|
||
}
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Jumlah -->
|
||
<div class="col-6 col-md-2">
|
||
<div class="d-flex align-items-center justify-content-between">
|
||
|
||
<button class="btn btn-sm btn-outline-success" onclick="decrement(${item.id}, ${i})" ${p.jumlah > 1 ? '' : 'disabled'}>
|
||
<i class="fa fa-minus"></i>
|
||
</button>
|
||
<input type="text" class="form-control form-control-sm text-center mx-2 jumlah-input"
|
||
value="${p.jumlah}" readonly style="width: 60px;" id="jumlah-${item.id}-${i}">
|
||
<button class="btn btn-sm btn-outline-success" onclick="increment(${item.id}, ${i})">
|
||
<i class="fa fa-plus"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tombol Hapus -->
|
||
<div class="col-6 col-md-1 text-end">
|
||
${countDate > 1
|
||
? `<button class="btn btn-sm btn-danger" onclick="removeOrderDate(${item.id}, ${i}, ${countDate})" title="Hapus">
|
||
<i class="fa fa-trash"></i>
|
||
</button>`
|
||
: ''
|
||
}
|
||
</div>
|
||
${item.kalori
|
||
? `<div class="mb-2 small text-muted">Total Kalori: <strong id="kalori_${item.id}_${i}">${p?.resultKalori ? p?.resultKalori : item?.kalori}</strong> kal</div>`
|
||
: ''}
|
||
</div>
|
||
</div>
|
||
|
||
`;
|
||
});
|
||
|
||
const itemHTML = `
|
||
<div class="card mb-3 shadow-sm position-relative">
|
||
<button type="button" class="btn btn-sm btn-danger position-absolute top-0 end-0 m-2" onClick="removeCartItem(${item.id})" style="z-index:1;">
|
||
Hapus
|
||
</button>
|
||
<div class="d-flex flex-column flex-md-row">
|
||
|
||
<div class="p-2 d-flex justify-content-center align-items-center" style="flex: 0 0 300px;">
|
||
<img src="gambar/${item.foto || 'default.jpg'}" alt="${item.nama_menu}"
|
||
class="img-fluid rounded" style="max-height: 280px; width: 100%; object-fit: cover;">
|
||
</div>
|
||
|
||
<div class="flex-grow-1 position-relative">
|
||
|
||
<div class="card-body">
|
||
<!-- Judul menu -->
|
||
<h4 class="card-title mb-2 fw-bold text-primary">${item.nama_menu}</h4>
|
||
|
||
<!-- Harga -->
|
||
<div class="badge bg-success-subtle text-success fw-bold fs-6 mb-2">
|
||
${checkout_biodata?.jenis_customer === "Karyawan RSAB Harapan Kita"
|
||
? '<span class="me-1">Harga Karyawan</span>'
|
||
: '<span class="me-1">Harga</span>'
|
||
}
|
||
Rp ${parseInt(harga).toLocaleString('id-ID')}
|
||
</div>
|
||
|
||
<!-- Kalori -->
|
||
${item?.kalori ? `<div class="text-muted small mb-1"><i class="fas fa-fire me-1"></i>Kalori: ${item.kalori} kal</div>` : ''}
|
||
|
||
<!-- Deskripsi -->
|
||
${item.deskripsi ? `<p class="card-text text-muted small mb-2">${item.deskripsi}</p>` : ''}
|
||
|
||
<!-- Info tanggal & jenis menu -->
|
||
<div class="d-flex flex-column gap-1 mb-2">
|
||
<div class="small text-muted">
|
||
<i class="fas fa-calendar-check me-1"></i>
|
||
${item.apakah_someday
|
||
? 'Tersedia setiap hari (Senin – Minggu)'
|
||
: (item.tgl_tersedia ? `Tersedia pada tanggal: ${item.tgl_tersedia}` : 'Tidak ada info tanggal tersedia')
|
||
}
|
||
</div>
|
||
<div class="small text-muted">
|
||
<i class="fas fa-utensils me-1"></i>
|
||
<strong>${item.apakah_someday ? 'Sameday' : 'Menu Normal'}</strong>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Petunjuk -->
|
||
<div class="alert alert-info small p-2 mb-2">
|
||
<strong>Petunjuk:</strong> Isi tanggal pemesanan, pilih karbohidrat, dan catatan tambahan (opsional).
|
||
</div>
|
||
|
||
<!-- Form pesanan -->
|
||
${pesananHTML}
|
||
|
||
<!-- Tombol & total -->
|
||
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mt-3">
|
||
<button class="btn btn-sm btn-success" onclick="addOrderDate(${item.id}, ${item.apakah_menu_sore})">
|
||
<i class="fas fa-plus me-1"></i>Tambah Tanggal
|
||
</button>
|
||
|
||
<div class="fw-bold">
|
||
Total: <span class="text-success">Rp ${itemTotal.toLocaleString('id-ID')}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
container.insertAdjacentHTML('beforeend', itemHTML);
|
||
pesananList.forEach((p, i) => initFlatpickrTersedia(item, i));
|
||
});
|
||
|
||
container.insertAdjacentHTML('beforeend', `
|
||
<div class="text-end mt-4">
|
||
<hr>
|
||
<h5><strong>Total Keseluruhan:</strong> <span class="text-success">Rp ${totalKeseluruhan.toLocaleString('id-ID')}</span></h5>
|
||
</div>
|
||
`);
|
||
|
||
document.getElementById('no_order_price').textContent = 'Rp ' + totalKeseluruhan.toLocaleString('id-ID');
|
||
}
|
||
|
||
// =======================
|
||
// EVENT HANDLER FIELD
|
||
// =======================
|
||
function onJumlahChange(itemId, index) {
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const input = document.querySelector(`div[data-item-id='${itemId}'][data-index='${index}'] .jumlah-input`);
|
||
if (!isNaN(input.value)) {
|
||
cart.find(item => item.id === itemId).pesanan[index].jumlah = parseInt(input.value);
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
isiKonfirmasi();
|
||
}
|
||
}
|
||
|
||
function onTanggalChange(itemId, index) {
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const input = document.querySelector(`div[data-item-id='${itemId}'][data-index='${index}'] .tanggal-input`);
|
||
cart.find(item => item.id === itemId).pesanan[index].tgl = input.value;
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
renderCartSummary();
|
||
}
|
||
|
||
function onKarbohidratChange(itemId, index, el, kalori){
|
||
const selectedOption = el.options[el.selectedIndex];
|
||
const kaloriOption = parseInt(selectedOption.getAttribute('data-kalori')) || 0;
|
||
|
||
const kaloriMenuInt = kalori || 0;
|
||
|
||
const totalKalori = kaloriOption + kaloriMenuInt;
|
||
const kaloriEl = document.getElementById(`kalori_${itemId}_${index}`);
|
||
|
||
if (kaloriEl) {
|
||
kaloriEl.textContent = totalKalori ;
|
||
}
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const input = document.querySelector(`div[data-item-id='${itemId}'][data-index='${index}'] .karbohidrat-input`);
|
||
cart.find(item => item.id === itemId).pesanan[index].karbohidrat_id = parseInt(input.value);
|
||
cart.find(item => item.id === itemId).pesanan[index].resultKalori = totalKalori;
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
}
|
||
|
||
function onKategoriChange(itemId, index, isToday) {
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const selectEl = document.querySelector(`.kategori-pemesanan-input[data-item-id='${itemId}'][data-index='${index}']`);
|
||
const kategori = selectEl.value;
|
||
let now = new Date();
|
||
let jam = now.getHours();
|
||
|
||
if (kategori === "Makan Siang" && isToday && jam >= 10) {
|
||
alert("Pemesanan Makan Siang hanya bisa dilakukan sebelum jam 10:00.");
|
||
} else if (kategori === "Makan Sore" && isToday && jam >= 13) {
|
||
alert("Pemesanan Makan Sore hanya bisa dilakukan sebelum jam 13:00.");
|
||
}
|
||
|
||
const item = cart.find(item => item.id === itemId);
|
||
if (item && item.pesanan && item.pesanan[index]) {
|
||
item.pesanan[index].kategoriPemesanan = kategori;
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
// renderCartSummary();
|
||
}
|
||
}
|
||
|
||
|
||
// =======================
|
||
// TAMBAH / HAPUS PESANAN
|
||
// =======================
|
||
function addOrderDate(itemId, sore) {
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const item = cart.find(i => i.id === itemId);
|
||
if (item && Array.isArray(item.pesanan)) {
|
||
item.pesanan.push({
|
||
tgl: '',
|
||
jumlah: 1,
|
||
kategoriPemesanan: sore ? 'Makan Sore' : 'Makan Siang'
|
||
});
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
renderCartSummary();
|
||
}
|
||
}
|
||
|
||
function removeOrderDate(itemId, index, count) {
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const item = cart.find(i => i.id === itemId);
|
||
|
||
if(count == 1){
|
||
cart = cart.filter(i => i.id !== itemId);
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
}else if(item && Array.isArray(item.pesanan) && item.pesanan.length > index) {
|
||
item.pesanan.splice(index, 1);
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
}
|
||
renderCartSummary();
|
||
}
|
||
|
||
|
||
function removeCartItem(itemId){
|
||
let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
cart = cart.filter(i => i.id !== itemId);
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
renderCartSummary()
|
||
}
|
||
|
||
// validasi step one dan sebelum submit
|
||
function validateStepOne() {
|
||
const jenisCustomer = document.querySelector('input[name="jenis_customer"]:checked');
|
||
const jenisKelamin = document.querySelector('input[name="jenis_kelamin"]:checked');
|
||
const namaPemesan = document.getElementById('nama_pemesan').value.trim();
|
||
const noWA = document.getElementById('no_whatsapp').value.trim();
|
||
const email = document.getElementById('email').value.trim();
|
||
|
||
if (!jenisCustomer) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan pilih jenis customer.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
|
||
if (!namaPemesan) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan isi nama pemesan.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
|
||
if (!jenisKelamin) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan pilih jenis kelamin.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
|
||
if (!noWA) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan isi nomor WhatsApp.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
if (!email) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan isi email terlebih dahulu.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
|
||
// Validasi tambahan sesuai jenis customer
|
||
const selected = jenisCustomer.value;
|
||
if (selected === 'Karyawan RSAB Harapan Kita') {
|
||
const bagian = document.getElementById('bagian_instalasi').value.trim();
|
||
if (!bagian) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan lengkapi data karyawan.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
} else if (selected === 'Keluarga Pasien / Penunggu Pasien') {
|
||
const namaPasien = document.getElementById('nama_pasien').value.trim();
|
||
const ruang = document.getElementById('ruang_perawatan').value;
|
||
const noKamar = document.getElementById('no_kamar').value.trim();
|
||
const kelas = document.getElementById('kelas_perawatan').value;
|
||
if (!namaPasien || !ruang || !noKamar || !kelas) {
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silakan lengkapi data pasien.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false;
|
||
}
|
||
}else if(selected === "Masyarakat Umum"){
|
||
const alamat = document.getElementById('alamat').value;
|
||
if(!alamat){
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'Silahkan lengkapi alamat.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
return false
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
function validateCartBeforeSubmit() {
|
||
const cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
let isValid = true;
|
||
let errorMessage = "";
|
||
|
||
cart.forEach((item, index) => {
|
||
const pesananList = item.pesanan || [];
|
||
pesananList.forEach((pesanan, i) => {
|
||
if (!pesanan.tgl) {
|
||
isValid = false;
|
||
errorMessage = `Tanggal belum diisi pada item "${item.nama_menu}" (baris ${i + 1})`;
|
||
} else if (!pesanan.kategoriPemesanan) {
|
||
isValid = false;
|
||
errorMessage = `Kategori pemesanan belum dipilih pada item "${item.nama_menu}" (baris ${i + 1})`;
|
||
} else if (!pesanan.jumlah || pesanan.jumlah <= 0) {
|
||
isValid = false;
|
||
errorMessage = `Jumlah harus lebih dari 0 pada item "${item.nama_menu}" (baris ${i + 1})`;
|
||
}else if(!pesanan.karbohidrat_id && !item?.apakah_someday){
|
||
isValid = false;
|
||
errorMessage = `Karbohidrat belum diisi pada item "${item.nama_menu}" (baris ${i + 1})`
|
||
}
|
||
});
|
||
});
|
||
|
||
return { isValid, errorMessage };
|
||
}
|
||
|
||
|
||
function hitungTotalHarga(){
|
||
const biodata = JSON.parse(sessionStorage.getItem('checkout_biodata') || '{}');
|
||
const cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
let total =0;
|
||
|
||
cart.forEach(item => {
|
||
const harga = biodata.jenis_customer === "Karyawan RSAB Harapan Kita" ? item.harga_karyawan : item.harga_public || 0
|
||
|
||
const itemTotal = item.pesanan?.reduce((sum, p) => sum + (p.jumlah * harga), 0);
|
||
total += itemTotal
|
||
})
|
||
|
||
return total;
|
||
}
|
||
|
||
|
||
function copyNoRek() {
|
||
const text = document.getElementById('noRekText').innerText;
|
||
navigator.clipboard.writeText(text).then(() => {
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Disalin!',
|
||
text: 'Nomor rekening berhasil disalin: ' + text,
|
||
showConfirmButton: false,
|
||
timer: 1500
|
||
});
|
||
}).catch(err => {
|
||
console.error('Gagal menyalin: ', err);
|
||
Swal.fire({
|
||
icon: 'warning',
|
||
text: 'Gagal menyalin teks: ' + text,
|
||
showConfirmButton: false,
|
||
timer: 2000
|
||
});
|
||
});
|
||
}
|
||
|
||
function copyNoOrder() {
|
||
const text = document.getElementById('no_order_display').innerText;
|
||
navigator.clipboard.writeText(text).then(() => {
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Disalin!',
|
||
text: 'Nomor order berhasil disalin: ' + text,
|
||
showConfirmButton: false,
|
||
timer: 1500
|
||
});
|
||
}).catch(err => {
|
||
console.error('Gagal menyalin: ', err);
|
||
Swal.fire({
|
||
icon: 'warning',
|
||
text: 'Gagal menyalin teks: ' + text,
|
||
showConfirmButton: false,
|
||
timer: 2000
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
function initFlatpickrTersedia(item, i) {
|
||
const now = new Date();
|
||
const jamFlat = now.getHours();
|
||
const menitFlat = now.getMinutes();
|
||
const totalMenitFlatSekarang = jamFlat * 60 + menitFlat;
|
||
|
||
const menitBatasFlat = 13 * 60;
|
||
|
||
const lewatBatasNormal = totalMenitFlatSekarang >= menitBatasFlat;
|
||
const tglString = Array.isArray(item?.tgl_tersedia)
|
||
? item?.tgl_tersedia.join(',') // kalau array → gabung jadi string
|
||
: String(item?.tgl_tersedia);
|
||
// Ambil string tgl_tersedia dan ubah jadi array tanggal lengkap
|
||
const dayNumbers = (tglString || "")
|
||
.split(',')
|
||
.map(s => s.trim())
|
||
.filter(s => s !== '' && !isNaN(s))
|
||
.map(s => parseInt(s));
|
||
|
||
|
||
// Generate tanggal dalam format YYYY-MM-DD untuk 3 bulan ke depan
|
||
let availableDates = [];
|
||
const bulanKeDepan = 3;
|
||
|
||
for (let bulanOffset = 0; bulanOffset < bulanKeDepan; bulanOffset++) {
|
||
const baseDate = new Date(now.getFullYear(), now.getMonth() + bulanOffset, 1);
|
||
const year = baseDate.getFullYear();
|
||
const month = String(baseDate.getMonth() + 1).padStart(2, '0');
|
||
|
||
dayNumbers.forEach(day => {
|
||
const dayStr = String(day).padStart(2, '0');
|
||
const fullDateStr = `${year}-${month}-${dayStr}`;
|
||
const fullDate = new Date(`${fullDateStr}T13:00:00`);
|
||
|
||
// Jika bukan menu someday, cek aturan H-1 dan jam batas
|
||
if (item.apakah_someday) {
|
||
availableDates.push(fullDateStr);
|
||
} else {
|
||
|
||
const selisihHari = Math.floor((fullDate - now) / (1000 * 60 * 60 * 24));
|
||
if (selisihHari >= 1 || (selisihHari === 1 && !lewatBatasNormal)) {
|
||
availableDates.push(fullDateStr);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
|
||
let minTanggal = 'today';
|
||
|
||
// Jika item adalah someday dan waktu sekarang sudah lewat 13:00
|
||
if (item?.apakah_someday && totalMenitFlatSekarang >= 13 * 60) {
|
||
const besok = new Date(now);
|
||
besok.setDate(now.getDate() + 1);
|
||
minTanggal = besok.toISOString().split("T")[0]; // format YYYY-MM-DD
|
||
}
|
||
|
||
|
||
flatpickr(`#tanggal-${item.id}-${i}`, {
|
||
dateFormat: "Y-m-d",
|
||
...(item?.apakah_someday ? {minDate: minTanggal} : {enable:availableDates}),
|
||
defaultDate: item.pesanan[i]?.tgl || null,
|
||
disableMobile: true,
|
||
onChange: function(selectedDates, dateStr) {
|
||
onTanggalChange(item.id, i, dateStr);
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
function increment(itemId, index) {
|
||
const input = document.getElementById(`jumlah-${itemId}-${index}`);
|
||
input.value = parseInt(input.value || "0") + 1;
|
||
onJumlahChange(itemId, index); // Tetap panggil function milikmu
|
||
}
|
||
|
||
function decrement(itemId, index) {
|
||
const input = document.getElementById(`jumlah-${itemId}-${index}`);
|
||
let current = parseInt(input.value || "0");
|
||
|
||
if (current > 1) {
|
||
input.value = current - 1;
|
||
onJumlahChange(itemId, index);
|
||
}else{
|
||
return
|
||
}
|
||
}
|
||
|
||
|
||
|
||
function toggleBuktiPembayaran() {
|
||
const metode = document.getElementById("cara_pembayaran").value;
|
||
const buktiSection = document.getElementById("bukti_section");
|
||
const buktiInput = document.getElementById("bukti_pembayaran");
|
||
const billing_section = document.getElementById("billing_section");
|
||
|
||
buktiInput.required = true;
|
||
if (metode === "billing") {
|
||
buktiSection.style.display = "none";
|
||
billing_section.style.display = "block";
|
||
buktiInput.required = false;
|
||
$("#modalActionMethodBillingOrder").modal('show')
|
||
} else {
|
||
buktiSection.style.display = "block";
|
||
billing_section.style.display = "none";
|
||
buktiInput.required = true;
|
||
$("#modalActionMethodBillingOrder").modal('hide')
|
||
}
|
||
}
|
||
|
||
|
||
function validateTanggalPemesanan(item, tglDipilih) {
|
||
const now = new Date();
|
||
const jam = now.getHours();
|
||
const menit = now.getMinutes();
|
||
const totalMenit = jam * 60 + menit;
|
||
const batasWaktu = 13 * 60;
|
||
const tglSekarang = now.toISOString().split("T")[0];
|
||
|
||
if (item.apakah_someday && totalMenit >= batasWaktu && tglDipilih === tglSekarang) {
|
||
return {
|
||
valid: false,
|
||
message: `Maaf, Anda tidak bisa memilih hari ini (${tglDipilih}) untuk menu sameday karena sudah lewat jam 13:00`
|
||
};
|
||
}
|
||
|
||
return { valid: true };
|
||
}
|
||
|
||
function notedOrder(id, i) {
|
||
const cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const item = cart.find(item => item.id === id);
|
||
const note = item?.pesanan?.[i]?.catatan || '';
|
||
|
||
$("#note_order").val(note);
|
||
$("#submitNote").data('id', id).data('index', i);
|
||
$("#notedPOrder").modal('show');
|
||
}
|
||
|
||
|
||
document.querySelectorAll('.auto-expand').forEach(function(textarea){
|
||
textarea.addEventListener('input', function () {
|
||
this.style.height = 'auto';
|
||
this.style.height = this.scrollHeight + 'px';
|
||
});
|
||
})
|
||
|
||
document.getElementById('submitNote').addEventListener('click', function(e){
|
||
e.preventDefault()
|
||
const id = $(this).data('id')
|
||
const index = $(this).data('index')
|
||
const noted = $("#note_order").val()
|
||
const cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
|
||
const item =cart.find(item => item.id === id)
|
||
|
||
if(item && item.pesanan && item.pesanan[index]){
|
||
item.pesanan[index].catatan = noted
|
||
sessionStorage.setItem('cart', JSON.stringify(cart));
|
||
$("#notedPOrder").modal('hide')
|
||
}else{
|
||
Swal.fire({
|
||
title: 'Perhatian!',
|
||
text: 'gagal menyimpan catatan.',
|
||
icon: 'warning',
|
||
confirmButtonText: 'Oke'
|
||
})
|
||
}
|
||
});
|
||
|
||
|
||
function selectKaryawan(){
|
||
const $el = $('#nama_pemesan');
|
||
|
||
// 1. destroy jika sudah ada
|
||
if ($el[0] && $el[0].selectize) {
|
||
$el[0].selectize.destroy();
|
||
}
|
||
$el.selectize({
|
||
valueField: 'label', // sama dengan labelField
|
||
labelField: 'label',
|
||
searchField: ['label'],
|
||
create: function(input) {
|
||
return {
|
||
label: input,
|
||
value: input
|
||
};
|
||
},
|
||
createOnBlur: true,
|
||
placeholder: "Cari nama karyawan...",
|
||
maxItems: 1,
|
||
load: function (query, callback) {
|
||
$.ajax({
|
||
url: '/karyawan',
|
||
data: { search: query },
|
||
success: res => callback(res.data || []),
|
||
error: () => callback([])
|
||
});
|
||
},
|
||
render: {
|
||
option: (item, escape) =>
|
||
`<div class="p-1"><div class="fw-semibold">${escape(item.label)}</div></div>`,
|
||
item: (item, escape) => `<div>${escape(item.label)}</div>`
|
||
}
|
||
});
|
||
}
|
||
|
||
selectUnitInstalasi()
|
||
function selectUnitInstalasi(){
|
||
const bagian_instalasi = $('#bagian_instalasi');
|
||
|
||
// 1. destroy jika sudah ada
|
||
if (bagian_instalasi[0] && bagian_instalasi[0].selectize) {
|
||
bagian_instalasi[0].selectize.destroy();
|
||
}
|
||
bagian_instalasi.selectize({
|
||
valueField: 'label',
|
||
labelField: 'label',
|
||
searchField: ['label'],
|
||
create: false,
|
||
sortField: [],
|
||
placeholder: "Cari unit instalasi...",
|
||
maxItems:1,
|
||
load: function (query, callback) {
|
||
$.ajax({
|
||
url: '/unit-instalasi',
|
||
data: { search: query },
|
||
success: function (response) {
|
||
if (response.error === 0 && Array.isArray(response.data)) {
|
||
callback(response.data);
|
||
} else {
|
||
callback();
|
||
}
|
||
},
|
||
error: function () {
|
||
callback();
|
||
}
|
||
});
|
||
},
|
||
render: {
|
||
option: function (item, escape) {
|
||
|
||
return `<div class="p-1">
|
||
<div class="fw-semibold" style="font-size: 0.85rem;">${escape(item.label)}</div>
|
||
</div>`;
|
||
},
|
||
item: function (item, escape) {
|
||
return `<div>${escape(item?.label)}</div>`;
|
||
}
|
||
}
|
||
});
|
||
}
|