301 lines
13 KiB
PHP
301 lines
13 KiB
PHP
@extends('navbar')
|
|
|
|
@section('content')
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>Booking Pemotretan</title>
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet" />
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
<!-- Moment.js harus di-load sebelum FullCalendar -->
|
|
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.min.js"></script>
|
|
<!-- FullCalendar -->
|
|
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@3.2.0/dist/fullcalendar.min.js"></script>
|
|
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@3.2.0/dist/fullcalendar.min.css" rel="stylesheet" />
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<link rel="stylesheet" href="{{ asset('css/booking.css') }}" />
|
|
</head>
|
|
|
|
<body>
|
|
@if (session('error'))
|
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
{{ session('error') }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="container py-4">
|
|
<div class="scrolling-wrapper d-flex flex-nowrap overflow-auto gap-3 pb-3">
|
|
@foreach ($pricelists as $item)
|
|
<div class="col" style="min-width: 280px;">
|
|
<div class="card h-100 shadow-sm rounded-4">
|
|
<div class="position-relative">
|
|
<span class="badge bg-danger position-absolute top-0 start-0 m-2">{{ $item->kategori }}</span>
|
|
<img src="{{ asset($item->gambar) }}" class="card-img-top" alt="{{ $item->judul }}"
|
|
style="height: 200px; object-fit: cover;" />
|
|
</div>
|
|
<div class="card-body d-flex flex-column">
|
|
<h5 class="card-title fw-bold">{{ $item->judul }}</h5>
|
|
<p class="card-text text-muted">{{ $item->deskripsi }}</p>
|
|
|
|
@php
|
|
$pakets = is_string($item->paket) ? json_decode($item->paket, true) : $item->paket;
|
|
@endphp
|
|
|
|
@if(!empty($pakets))
|
|
<ul class="list-unstyled mb-3">
|
|
@foreach ($pakets as $p)
|
|
<li class="mb-1">
|
|
<span class="fw-semibold">{{ $p['value'] }}</span> <br />
|
|
{{ $p['keterangan'] ?? '-' }}<br />
|
|
<small class="text-primary">Rp {{ number_format($p['harga'], 0, ',', '.') }}</small>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
@else
|
|
<p class="text-muted small">Belum ada paket tersedia</p>
|
|
@endif
|
|
|
|
<div class="mt-auto d-flex justify-content-between align-items-center">
|
|
<span class="text-primary fw-bold">Mulai Rp
|
|
{{ number_format($item->harga, 0, ',', '.') }}</span>
|
|
<button class="btn btn-warning rounded-pill"
|
|
onclick="bukaModal('{{ strtolower($item->judul) }}')">Pesan</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container-fluid my-5 px-0 mx-0 gradient-bg">
|
|
<div class="row align-items-center justify-content-center">
|
|
<!-- Kiri -->
|
|
<div class="col-lg-5 col-md-6 text-center text-md-start ps-5">
|
|
<h1 class="fw-bold text-danger">Jadwal Pemotretan</h1>
|
|
<h3 class="text-secondary">Lihat dan atur jadwal pemotretan Anda di sini.</h3>
|
|
<p class="text-muted">Pesan studio dengan mudah dan sesuaikan jadwal sesuai kebutuhan Anda.</p>
|
|
|
|
<!-- Legenda -->
|
|
<div class="mt-4">
|
|
<h6 class="fw-bold">Legenda:</h6>
|
|
<div class="d-flex align-items-center mb-2">
|
|
<span class="me-2 rounded-circle d-inline-block" style="width: 16px; height: 16px; background-color: #dc3545;"></span>
|
|
<span>Sesi Pemotretan</span>
|
|
</div>
|
|
<div class="d-flex align-items-center mb-2">
|
|
<span class="me-2 rounded-circle d-inline-block" style="width: 16px; height: 16px; background-color: #ffc107;"></span>
|
|
<span>Booking Pending</span>
|
|
</div>
|
|
<div class="d-flex align-items-center">
|
|
<span class="me-2 rounded-circle d-inline-block border" style="width: 16px; height: 16px; background-color: #ffffff;"></span>
|
|
<span>Hari Kosong</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Kanan: Kalender -->
|
|
<div class="col-lg-6 col-md-6 px-4 pt-4">
|
|
<div id="calendar-container" class="p-4 bg-white rounded shadow pb-4">
|
|
<div id="calendar"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Booking -->
|
|
<div class="modal fade" id="modalBooking" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Booking <span id="judul-produk"></span></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="bookingForm" method="POST" action="{{ route('booking.store') }}">
|
|
@csrf
|
|
<input type="hidden" id="produk" name="produk" />
|
|
<input type="hidden" id="customer_id" name="customer_id" value="{{ Auth::id() }}" />
|
|
|
|
<div class="mb-3">
|
|
<label for="paket" class="form-label">Pilih Paket:</label>
|
|
<select id="paket" name="paket" class="form-select" required onchange="updateHarga()"></select>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="tanggal_pemotretan" class="form-label">Tanggal Pemotretan:</label>
|
|
<input type="date" id="tanggal_pemotretan" name="tanggal_pemotretan" class="form-control" required
|
|
min="{{ \Carbon\Carbon::today()->format('Y-m-d') }}" />
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="payment_method" class="form-label">Metode Pembayaran:</label>
|
|
<select id="payment_method" name="payment_method" class="form-select" required>
|
|
<option value="cash">Bayar di Tempat</option>
|
|
<option value="transfer">Transfer Bank</option>
|
|
</select>
|
|
</div>
|
|
|
|
<input type="hidden" id="total_harga" name="total_harga" />
|
|
<input type="hidden" id="durasi_booking" name="durasi_booking" />
|
|
|
|
<button type="button" class="btn btn-primary w-100" onclick="tampilkanKonfirmasi()">Submit Booking</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Konfirmasi -->
|
|
<div class="modal fade" id="modalKonfirmasi" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Konfirmasi Booking</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p><strong>Nama:</strong> <span id="confirm-nama">{{ Auth::user()->name ?? '' }}</span></p>
|
|
<p><strong>Produk:</strong> <span id="confirm-produk"></span></p>
|
|
<p><strong>Paket:</strong> <span id="confirm-paket"></span></p>
|
|
<p><strong>Tanggal:</strong> <span id="confirm-tanggal"></span></p>
|
|
<p><strong>Total Harga:</strong> <span id="confirm-harga"></span></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
|
|
<button type="button" class="btn btn-primary" onclick="submitBooking()">Konfirmasi</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Mapping produk berdasarkan judul (lowercase) ke data pricelist lengkap
|
|
const pricelistsMap = @json(
|
|
$pricelists->mapWithKeys(function ($item) {
|
|
return [strtolower($item->judul) => [
|
|
'paket' => is_string($item->paket) ? json_decode($item->paket, true) : $item->paket,
|
|
'durasi_booking' => $item->durasi_booking
|
|
]];
|
|
})
|
|
);
|
|
|
|
var userName = @json(Auth::user()->name ?? '');
|
|
|
|
function bukaModal(produk) {
|
|
produk = produk.toLowerCase().trim();
|
|
document.getElementById("judul-produk").innerText = produk.charAt(0).toUpperCase() + produk.slice(1);
|
|
document.getElementById("produk").value = produk;
|
|
|
|
const paketSelect = document.getElementById("paket");
|
|
paketSelect.innerHTML = "";
|
|
|
|
const produkData = pricelistsMap[produk] || { paket: [] };
|
|
const paket = produkData.paket || [];
|
|
const durasiBooking = produkData.durasi_booking || 'slot';
|
|
|
|
// Simpan durasi_booking ke hidden input
|
|
document.getElementById("durasi_booking").value = durasiBooking;
|
|
|
|
if (paket.length > 0) {
|
|
paket.forEach(p => {
|
|
let option = document.createElement("option");
|
|
option.value = p.value;
|
|
option.textContent = p.label;
|
|
option.dataset.harga = p.harga;
|
|
paketSelect.appendChild(option);
|
|
});
|
|
} else {
|
|
let option = document.createElement("option");
|
|
option.textContent = "Paket tidak tersedia";
|
|
option.disabled = true;
|
|
paketSelect.appendChild(option);
|
|
}
|
|
|
|
// Slot waktu dihilangkan, jadi tidak tampilkan apa-apa
|
|
|
|
updateHarga();
|
|
|
|
var bookingModal = new bootstrap.Modal(document.getElementById("modalBooking"));
|
|
bookingModal.show();
|
|
}
|
|
|
|
function updateHarga() {
|
|
let harga = document.querySelector("#paket option:checked")?.dataset.harga || 0;
|
|
document.getElementById("total_harga").value = harga;
|
|
}
|
|
|
|
function tampilkanKonfirmasi() {
|
|
let produk = document.getElementById("produk").value;
|
|
let paketSelect = document.getElementById("paket");
|
|
let paketText = paketSelect.options[paketSelect.selectedIndex].text;
|
|
let tanggal = document.getElementById("tanggal_pemotretan").value;
|
|
let harga = document.querySelector("#paket option:checked").dataset.harga;
|
|
let durasiBooking = document.getElementById("durasi_booking").value;
|
|
|
|
if (!tanggal) {
|
|
alert("Mohon isi tanggal pemotretan.");
|
|
return;
|
|
}
|
|
|
|
document.getElementById("confirm-nama").innerText = userName;
|
|
document.getElementById("confirm-produk").innerText = produk.charAt(0).toUpperCase() + produk.slice(1);
|
|
document.getElementById("confirm-paket").innerText = paketText;
|
|
document.getElementById("confirm-tanggal").innerText = tanggal;
|
|
document.getElementById("confirm-harga").innerText = formatRupiah(harga);
|
|
|
|
let konfirmasiModal = new bootstrap.Modal(document.getElementById("modalKonfirmasi"));
|
|
konfirmasiModal.show();
|
|
}
|
|
|
|
function submitBooking() {
|
|
document.getElementById("bookingForm").submit();
|
|
}
|
|
|
|
function formatRupiah(angka) {
|
|
let number_string = angka.toString(),
|
|
sisa = number_string.length % 3,
|
|
rupiah = number_string.substr(0, sisa),
|
|
ribuan = number_string.substr(sisa).match(/\d{3}/g);
|
|
|
|
if (ribuan) {
|
|
let separator = sisa ? '.' : '';
|
|
rupiah += separator + ribuan.join('.');
|
|
}
|
|
return 'Rp ' + rupiah;
|
|
}
|
|
|
|
// FullCalendar initialization (tidak berubah)
|
|
$(function () {
|
|
$('#calendar').fullCalendar({
|
|
events: '/bookings',
|
|
eventRender: function(event, element) {
|
|
if (event.status === 'booked') {
|
|
element.css('background-color', '#dc3545'); // merah untuk booked
|
|
} else {
|
|
element.css('background-color', '#ffc107'); // kuning untuk available
|
|
}
|
|
},
|
|
dayClick: function(date) {
|
|
// Kalau mau klik tanggal untuk buka modal, bisa diaktifkan sini
|
|
},
|
|
header: {
|
|
left: 'prev,next today',
|
|
center: 'title',
|
|
right: 'month,agendaWeek,agendaDay'
|
|
},
|
|
selectable: true,
|
|
selectHelper: true
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
|
|
@endsection
|