732 lines
32 KiB
PHP
732 lines
32 KiB
PHP
@extends('layouts.admin.app')
|
|
|
|
@push('styles')
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.3.0/flowbite.min.css" rel="stylesheet" />
|
|
<style>
|
|
.modal-container {
|
|
height: 90vh;
|
|
margin: 5vh auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: white;
|
|
border-radius: 0.5rem;
|
|
max-width: 800px;
|
|
width: 95%;
|
|
}
|
|
|
|
.modal-header {
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 1px solid #e5e7eb;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 1.5rem;
|
|
overflow-y: auto;
|
|
flex: 1;
|
|
}
|
|
|
|
.timeline-container {
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.time-slot {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0.75rem;
|
|
margin-bottom: 0.5rem;
|
|
border-radius: 0.5rem;
|
|
background-color: #f9fafb;
|
|
border-left: 4px solid transparent;
|
|
}
|
|
|
|
.time-slot.available {
|
|
border-left-color: #10B981;
|
|
}
|
|
|
|
.time-slot.reserved {
|
|
border-left-color: #EF4444;
|
|
}
|
|
|
|
.time-slot .time {
|
|
min-width: 100px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.time-slot .status {
|
|
margin-left: 1rem;
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 9999px;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.time-slot .status.available {
|
|
background-color: #D1FAE5;
|
|
color: #065F46;
|
|
}
|
|
|
|
.time-slot .status.reserved {
|
|
background-color: #FEE2E2;
|
|
color: #991B1B;
|
|
}
|
|
|
|
.time-slot .details {
|
|
margin-left: 1.5rem;
|
|
font-size: 0.875rem;
|
|
color: #6B7280;
|
|
}
|
|
|
|
/* Custom scrollbar */
|
|
.modal-body::-webkit-scrollbar {
|
|
width: 6px;
|
|
}
|
|
|
|
.modal-body::-webkit-scrollbar-track {
|
|
background: #f1f1f1;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.modal-body::-webkit-scrollbar-thumb {
|
|
background: #8B0000;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.modal-body::-webkit-scrollbar-thumb:hover {
|
|
background: #6d0000;
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
<div class="container mx-auto px-4 py-8">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-2xl font-bold text-gray-800">Manajemen Reservasi</h1>
|
|
{{-- <button type="button" onclick="openModal('addReservationModal')" class="bg-[#8B0000] text-white px-4 py-2 rounded-lg hover:bg-red-800">
|
|
<i class="fas fa-plus mr-2"></i>Tambah Reservasi
|
|
</button> --}}
|
|
</div>
|
|
|
|
@if(session('success'))
|
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4" role="alert">
|
|
<span class="block sm:inline">{{ session('success') }}</span>
|
|
</div>
|
|
@endif
|
|
|
|
@if ($errors->any())
|
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4">
|
|
<ul>
|
|
@foreach ($errors->all() as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="bg-white rounded-lg shadow overflow-hidden">
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tanggal & Waktu</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Pelanggan</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Harga</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
@foreach($reservations as $reservation)
|
|
<tr>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="text-sm text-gray-900">{{ $reservation->date->format('d M Y') }}</div>
|
|
<div class="text-sm text-gray-500">
|
|
{{ Carbon\Carbon::parse($reservation->start_time)->format('H:i') }} -
|
|
{{ Carbon\Carbon::parse($reservation->end_time)->format('H:i') }}
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="text-sm text-gray-900">{{ $reservation->name }}</div>
|
|
<div class="text-sm text-gray-500">{{ $reservation->user->email }}</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
Rp {{ number_format($reservation->total_harga, 0, ',', '.') }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span class="px-2 py-1 inline-flex text-xs leading-5 font-semibold rounded-full
|
|
{{ $reservation->status === 'confirmed' ? 'bg-green-100 text-green-800' :
|
|
($reservation->status === 'pending' ? 'bg-yellow-100 text-yellow-800' :
|
|
($reservation->status === 'completed' ? 'bg-blue-100 text-blue-800' : 'bg-red-100 text-red-800')) }}">
|
|
{{ ucfirst($reservation->status) }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
<button onclick="openEditModal('{{ $reservation->id }}')" class="text-blue-600 hover:text-blue-900 mr-3">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button onclick="openDetailModal('{{ $reservation->id }}')" class="text-green-600 hover:text-green-900 mr-3">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
<form action="{{ route('admin.reservations.destroy', $reservation) }}" method="POST" class="inline">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="text-red-600 hover:text-red-900" onclick="return confirm('Apakah Anda yakin ingin menghapus reservasi ini?')">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Tambah Reservasi -->
|
|
<div id="addReservationModal" class="modal fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-40">
|
|
<div class="bg-white rounded-lg p-8 max-w-2xl w-full m-4" onclick="event.stopPropagation();">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-xl font-bold">Tambah Reservasi Baru</h2>
|
|
<button type="button" onclick="closeModal('addReservationModal')" class="text-gray-600 hover:text-gray-800">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<form action="{{ route('admin.reservations.store') }}" method="POST">
|
|
@csrf
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Pelanggan</label>
|
|
<select name="user_id" class="w-full border rounded px-3 py-2" required>
|
|
<option value="">Pilih Pelanggan</option>
|
|
@foreach($users as $user)
|
|
<option value="{{ $user->id }}">{{ $user->name }} ({{ $user->email }})</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Tanggal</label>
|
|
<div class="relative">
|
|
<input type="date" name="date" id="reservation_date"
|
|
class="w-full border rounded px-3 py-2"
|
|
required min="{{ date('Y-m-d') }}">
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Meja</label>
|
|
<select name="meja_id" id="meja_id" class="w-full border rounded px-3 py-2" required>
|
|
<option value="">Pilih Meja</option>
|
|
@foreach($tables as $table)
|
|
<option value="{{ $table->id }}">{{ $table->nomor_meja }} ({{ ucfirst($table->kategori) }} - {{ $table->kapasitas }} Orang)</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Waktu</label>
|
|
<div class="flex space-x-2">
|
|
<div class="w-1/2">
|
|
<input type="text" name="start_time" id="start_time" required value="{{ old('start_time') }}" class="hidden">
|
|
<button type="button"
|
|
onclick="showTimeModal('start')"
|
|
class="w-full px-4 py-2 bg-gray-50 border border-gray-300 rounded-lg text-left"
|
|
id="start_time_button">
|
|
Waktu Mulai
|
|
</button>
|
|
</div>
|
|
<div class="w-1/2">
|
|
<input type="text" name="end_time" id="end_time" required value="{{ old('end_time') }}" class="hidden">
|
|
<button type="button"
|
|
onclick="showTimeModal('end')"
|
|
class="w-full px-4 py-2 bg-gray-50 border border-gray-300 rounded-lg text-left"
|
|
id="end_time_button">
|
|
Waktu Selesai
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Nama Pemesan</label>
|
|
<input type="text" name="name" class="w-full border rounded px-3 py-2" required>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Nomor Telepon</label>
|
|
<input type="text" name="phone" class="w-full border rounded px-3 py-2" required>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Jumlah Orang</label>
|
|
<input type="number" name="people" class="w-full border rounded px-3 py-2" required min="1">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Total Harga</label>
|
|
<input type="number" name="total_harga" class="w-full border rounded px-3 py-2" required min="0" step="1000">
|
|
</div>
|
|
|
|
<div class="col-span-2">
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Catatan</label>
|
|
<textarea name="notes" class="w-full border rounded px-3 py-2" rows="3"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6 flex justify-end">
|
|
<button type="button" onclick="closeModal('addReservationModal')" class="bg-gray-300 text-gray-700 px-4 py-2 rounded mr-2">Batal</button>
|
|
<button type="submit" class="bg-[#8B0000] text-white px-4 py-2 rounded">Simpan</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Edit Status -->
|
|
<div id="editStatusModal" class="modal fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
|
<div class="bg-white rounded-lg p-8 max-w-md w-full m-4" onclick="event.stopPropagation();">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-xl font-bold">Update Reservasi</h2>
|
|
<button type="button" onclick="closeModal('editStatusModal')" class="text-gray-600 hover:text-gray-800">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<form id="editStatusForm" method="POST">
|
|
@csrf
|
|
@method('PUT')
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Status</label>
|
|
<select name="status" id="edit_status" class="w-full border rounded px-3 py-2" required>
|
|
<option value="pending">Pending</option>
|
|
<option value="confirmed">Confirmed</option>
|
|
{{-- <option value="completed">Completed</option>
|
|
<option value="cancelled">Cancelled</option> --}}
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2">Meja</label>
|
|
<select name="meja_id" id="edit_meja_id" class="w-full border rounded px-3 py-2" required>
|
|
@foreach($tables as $table)
|
|
<option value="{{ $table->id }}">
|
|
Meja {{ $table->nomor_meja }} ({{ ucfirst($table->kategori) }} - {{ $table->kapasitas }} Orang)
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6 flex justify-end">
|
|
<button type="button" onclick="closeModal('editStatusModal')" class="bg-gray-300 text-gray-700 px-4 py-2 rounded mr-2">Batal</button>
|
|
<button type="submit" class="bg-[#8B0000] text-white px-4 py-2 rounded">Simpan Perubahan</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Detail Reservasi -->
|
|
<div id="detailModal" class="modal fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
|
<div class="bg-white rounded-lg p-8 max-w-lg w-full m-4" onclick="event.stopPropagation();">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-xl font-bold">Detail Reservasi</h2>
|
|
<button type="button" onclick="closeModal('detailModal')" class="text-gray-600 hover:text-gray-800">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="space-y-4" id="reservationDetails">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Tanggal</p>
|
|
<p class="text-base" id="detail_date"></p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Waktu</p>
|
|
<p class="text-base" id="detail_time"></p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Nama Pemesan</p>
|
|
<p class="text-base" id="detail_name"></p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Email</p>
|
|
<p class="text-base" id="detail_email"></p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Nomor Meja</p>
|
|
<p class="text-base" id="detail_table"></p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Total Harga</p>
|
|
<p class="text-base" id="detail_price"></p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold text-gray-600">Status</p>
|
|
<p class="text-base"><span id="detail_status" class="px-2 py-1 text-xs rounded-full"></span></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6 flex justify-end">
|
|
<button type="button" onclick="closeModal('detailModal')" class="bg-gray-300 text-gray-700 px-4 py-2 rounded">Tutup</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Jadwal -->
|
|
<div id="scheduleModal" class="modal fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
|
<div class="bg-white rounded-lg p-6 max-w-lg w-full m-4">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-xl font-bold" id="scheduleModalTitle">Jadwal Meja</h2>
|
|
<button type="button" onclick="closeScheduleModal()" class="text-gray-600 hover:text-gray-800">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="mb-4 space-y-4">
|
|
<div class="flex items-center justify-between">
|
|
<div class="text-sm text-gray-600" id="selectedDateDisplay"></div>
|
|
<select id="schedule_filter" class="border rounded-lg px-3 py-1 text-sm" onchange="updateScheduleView()">
|
|
<option value="all">Semua</option>
|
|
<option value="available">Tersedia</option>
|
|
<option value="reserved">Dipesan</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="loadingIndicator" class="hidden">
|
|
<div class="flex items-center justify-center p-4">
|
|
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-[#8B0000]"></div>
|
|
<span class="ml-2">Memuat jadwal...</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="space-y-2 max-h-[400px] overflow-y-auto" id="scheduleTimeSlots">
|
|
<!-- Time slots will be populated here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@push('scripts')
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.3.0/flowbite.min.js"></script>
|
|
<script>
|
|
// Make reservations data available globally for the modals
|
|
window.reservations = @json($reservations);
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const dateInput = document.getElementById('reservation_date');
|
|
const mejaSelect = document.getElementById('meja_id');
|
|
const startTimeInput = document.getElementById('start_time');
|
|
const endTimeInput = document.getElementById('end_time');
|
|
const startTimeButton = document.getElementById('start_time_button');
|
|
const endTimeButton = document.getElementById('end_time_button');
|
|
const loadingIndicator = document.getElementById('loadingIndicator');
|
|
let availableTimeSlots = [];
|
|
let currentTimeType = null;
|
|
|
|
// Add openDetailModal function
|
|
window.openDetailModal = function(reservationId) {
|
|
const reservation = window.reservations.find(r => r.id == reservationId);
|
|
if (!reservation) {
|
|
console.error('Reservation not found');
|
|
return;
|
|
}
|
|
|
|
// Format date
|
|
const date = new Date(reservation.date);
|
|
const formattedDate = date.toLocaleDateString('id-ID', {
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric'
|
|
});
|
|
|
|
// Format time
|
|
const startTime = reservation.start_time ? reservation.start_time.substring(0, 5) : '';
|
|
|
|
// Format price
|
|
const formattedPrice = new Intl.NumberFormat('id-ID', {
|
|
style: 'currency',
|
|
currency: 'IDR',
|
|
minimumFractionDigits: 0,
|
|
maximumFractionDigits: 0
|
|
}).format(reservation.total_harga);
|
|
|
|
// Update modal content
|
|
document.getElementById('detail_date').textContent = formattedDate;
|
|
document.getElementById('detail_time').textContent = startTime;
|
|
document.getElementById('detail_name').textContent = reservation.name;
|
|
document.getElementById('detail_email').textContent = reservation.user.email;
|
|
document.getElementById('detail_table').textContent = `Meja ${reservation.meja.nomor_meja} (${reservation.meja.kategori})`;
|
|
document.getElementById('detail_price').textContent = formattedPrice;
|
|
|
|
// Update status with appropriate styling
|
|
const statusElement = document.getElementById('detail_status');
|
|
statusElement.textContent = reservation.status.charAt(0).toUpperCase() + reservation.status.slice(1);
|
|
|
|
// Apply status styling
|
|
statusElement.className = 'px-2 py-1 text-xs rounded-full ' +
|
|
(reservation.status === 'confirmed' ? 'bg-green-100 text-green-800' :
|
|
(reservation.status === 'pending' ? 'bg-yellow-100 text-yellow-800' :
|
|
(reservation.status === 'completed' ? 'bg-blue-100 text-blue-800' : 'bg-red-100 text-red-800')));
|
|
|
|
// Open the modal
|
|
openModal('detailModal');
|
|
};
|
|
|
|
// Update openEditModal function
|
|
window.openEditModal = function(reservationId) {
|
|
const reservation = window.reservations.find(r => r.id == reservationId);
|
|
if (!reservation) {
|
|
console.error('Reservation not found');
|
|
return;
|
|
}
|
|
|
|
// Set up the form action URL
|
|
const form = document.getElementById('editStatusForm');
|
|
form.action = `{{ url('/admin/reservations') }}/${reservationId}`;
|
|
|
|
// Set current status in select
|
|
document.getElementById('edit_status').value = reservation.status;
|
|
|
|
// Set current meja in select
|
|
document.getElementById('edit_meja_id').value = reservation.meja_id;
|
|
|
|
// Open the modal
|
|
openModal('editStatusModal');
|
|
};
|
|
|
|
function updateAvailableTimeSlots() {
|
|
const date = dateInput.value;
|
|
const mejaId = mejaSelect.value;
|
|
|
|
if (!date || !mejaId) {
|
|
return;
|
|
}
|
|
|
|
loadingIndicator.classList.remove('hidden');
|
|
document.getElementById('scheduleTimeSlots').innerHTML = '';
|
|
|
|
fetch(`/admin/reservations/time-slots?date=${date}&meja_id=${mejaId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
loadingIndicator.classList.add('hidden');
|
|
console.log('Server response:', data); // Debug log
|
|
|
|
if (data.success) {
|
|
availableTimeSlots = data.data || [];
|
|
displaySchedule();
|
|
} else {
|
|
throw new Error(data.message || 'Terjadi kesalahan saat memuat jadwal');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
loadingIndicator.classList.add('hidden');
|
|
document.getElementById('scheduleTimeSlots').innerHTML = `
|
|
<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50">
|
|
<p>Error: ${error.message || 'Terjadi kesalahan saat memuat jadwal'}</p>
|
|
<p class="mt-2">Silakan coba lagi atau hubungi administrator.</p>
|
|
</div>`;
|
|
});
|
|
}
|
|
|
|
window.showTimeModal = function(type) {
|
|
const date = document.getElementById('reservation_date').value;
|
|
const mejaId = document.getElementById('meja_id').value;
|
|
|
|
if (!date || !mejaId) {
|
|
alert('Pilih tanggal dan meja terlebih dahulu');
|
|
return;
|
|
}
|
|
|
|
if (type === 'end' && !startTimeInput.value) {
|
|
alert('Pilih waktu mulai terlebih dahulu');
|
|
return;
|
|
}
|
|
|
|
currentTimeType = type;
|
|
document.getElementById('scheduleModalTitle').textContent =
|
|
type === 'start' ? 'Pilih Waktu Mulai' : 'Pilih Waktu Selesai';
|
|
|
|
document.getElementById('selectedDateDisplay').textContent =
|
|
new Date(date).toLocaleDateString('id-ID', {
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric'
|
|
});
|
|
|
|
updateAvailableTimeSlots();
|
|
openModal('scheduleModal');
|
|
}
|
|
|
|
function displaySchedule() {
|
|
const container = document.getElementById('scheduleTimeSlots');
|
|
container.innerHTML = '';
|
|
const filter = document.getElementById('schedule_filter').value;
|
|
|
|
console.log('Displaying schedule with filter:', filter); // Debug log
|
|
console.log('Available time slots:', availableTimeSlots); // Debug log
|
|
|
|
let hasDisplayedSlots = false;
|
|
|
|
// Generate time slots from 10:00 to 22:00
|
|
for (let hour = 10; hour < 22; hour++) {
|
|
for (const minutes of ['00', '30']) {
|
|
const time = `${hour.toString().padStart(2, '0')}:${minutes}`;
|
|
|
|
// Find the slot in our available slots data
|
|
const slot = availableTimeSlots.find(s => s.start_time === time);
|
|
if (!slot) continue;
|
|
|
|
const isAvailable = slot.is_available;
|
|
|
|
// Skip based on filter
|
|
if ((filter === 'available' && !isAvailable) ||
|
|
(filter === 'reserved' && isAvailable)) {
|
|
continue;
|
|
}
|
|
|
|
// For end time selection, skip times before or equal to start time
|
|
if (currentTimeType === 'end' && time <= startTimeInput.value) {
|
|
continue;
|
|
}
|
|
|
|
const timeSlot = createTimeSlot(time, isAvailable, slot.end_time_options);
|
|
container.appendChild(timeSlot);
|
|
hasDisplayedSlots = true;
|
|
}
|
|
}
|
|
|
|
if (!hasDisplayedSlots) {
|
|
container.innerHTML = `
|
|
<div class="p-4 text-sm text-gray-700 bg-gray-100 rounded-lg">
|
|
${filter === 'all' ?
|
|
'Tidak ada slot waktu yang tersedia untuk tanggal ini.' :
|
|
`Tidak ada slot waktu yang ${filter === 'available' ? 'tersedia' : 'dipesan'} untuk tanggal ini.`
|
|
}
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
function createTimeSlot(time, isAvailable, endTimeOptions = []) {
|
|
const slot = document.createElement('div');
|
|
slot.className = `flex items-center justify-between p-3 rounded-lg ${
|
|
isAvailable ? 'bg-green-50' : 'bg-red-50'
|
|
}`;
|
|
|
|
const timeInfo = document.createElement('div');
|
|
timeInfo.className = 'flex items-center space-x-4';
|
|
|
|
const timeText = document.createElement('span');
|
|
timeText.className = 'text-lg font-medium';
|
|
timeText.textContent = time;
|
|
|
|
const status = document.createElement('span');
|
|
status.className = `px-2 py-1 rounded-full text-sm ${
|
|
isAvailable ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
|
|
}`;
|
|
status.textContent = isAvailable ? 'Tersedia' : 'Dipesan';
|
|
|
|
timeInfo.appendChild(timeText);
|
|
timeInfo.appendChild(status);
|
|
slot.appendChild(timeInfo);
|
|
|
|
if (isAvailable) {
|
|
const button = document.createElement('button');
|
|
button.className = 'px-4 py-2 bg-[#8B0000] text-white rounded-lg hover:bg-red-800 transition-colors';
|
|
button.textContent = 'Pilih';
|
|
button.onclick = () => selectTime(time, endTimeOptions);
|
|
slot.appendChild(button);
|
|
}
|
|
|
|
return slot;
|
|
}
|
|
|
|
function selectTime(time, endTimeOptions = []) {
|
|
if (currentTimeType === 'start') {
|
|
startTimeInput.value = time;
|
|
startTimeButton.textContent = time;
|
|
endTimeInput.value = '';
|
|
endTimeButton.textContent = 'Waktu Selesai';
|
|
currentEndTimeOptions = endTimeOptions;
|
|
} else {
|
|
endTimeInput.value = time;
|
|
endTimeButton.textContent = time;
|
|
}
|
|
|
|
closeModal('scheduleModal');
|
|
}
|
|
|
|
window.updateScheduleView = function() {
|
|
displaySchedule();
|
|
}
|
|
|
|
window.closeScheduleModal = function() {
|
|
closeModal('scheduleModal');
|
|
}
|
|
|
|
// Modal handling functions
|
|
window.openModal = function(modalId) {
|
|
const modal = document.getElementById(modalId);
|
|
modal.classList.remove('hidden');
|
|
modal.classList.add('flex');
|
|
}
|
|
|
|
window.closeModal = function(modalId) {
|
|
const modal = document.getElementById(modalId);
|
|
modal.classList.add('hidden');
|
|
modal.classList.remove('flex');
|
|
}
|
|
|
|
// Form validation
|
|
document.querySelector('form').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const startTime = startTimeInput.value;
|
|
const endTime = endTimeInput.value;
|
|
|
|
if (!startTime || !endTime) {
|
|
alert('Mohon pilih waktu mulai dan selesai');
|
|
return;
|
|
}
|
|
|
|
if (endTime <= startTime) {
|
|
alert('Waktu selesai harus setelah waktu mulai');
|
|
return;
|
|
}
|
|
|
|
this.submit();
|
|
});
|
|
|
|
// Initialize time inputs if there are existing values
|
|
if (startTimeInput.value) {
|
|
startTimeButton.textContent = startTimeInput.value;
|
|
}
|
|
if (endTimeInput.value) {
|
|
endTimeButton.textContent = endTimeInput.value;
|
|
}
|
|
|
|
// Add event listeners for date and table selection
|
|
dateInput?.addEventListener('change', () => {
|
|
// Reset time selections when date changes
|
|
startTimeInput.value = '';
|
|
endTimeInput.value = '';
|
|
startTimeButton.textContent = 'Waktu Mulai';
|
|
endTimeButton.textContent = 'Waktu Selesai';
|
|
});
|
|
|
|
mejaSelect?.addEventListener('change', () => {
|
|
// Reset time selections when table changes
|
|
startTimeInput.value = '';
|
|
endTimeInput.value = '';
|
|
startTimeButton.textContent = 'Waktu Mulai';
|
|
endTimeButton.textContent = 'Waktu Selesai';
|
|
});
|
|
});
|
|
</script>
|
|
@endpush
|
|
@endsection
|