Reservasi-Cafe/app/Http/Controllers/Admin/ReservationController.php

277 lines
11 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Reservasi;
use App\Models\Meja;
use App\Models\User;
use Illuminate\Http\Request;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class ReservationController extends Controller
{
public function index()
{
$reservations = Reservasi::with(['user', 'meja'])
->orderBy('date', 'desc')
->orderBy('start_time', 'desc')
->get();
$users = User::where('role', 'user')->get();
// Get all tables regardless of status
$tables = Meja::orderBy('nomor_meja')->get();
return view('admin.reservations', compact('reservations', 'users', 'tables'));
}
public function store(Request $request)
{
$request->validate([
'user_id' => 'required|exists:users,id',
'meja_id' => 'required|exists:meja,id',
'name' => 'required|string|max:255',
'phone' => 'required|string|max:20',
'date' => 'required|date|after_or_equal:today',
'start_time' => 'required|date_format:H:i',
'end_time' => 'required|date_format:H:i|after:start_time',
'notes' => 'nullable|string',
'total_harga' => 'required|numeric|min:0'
]);
// Check if the time slot is available
if (!Reservasi::isTimeSlotAvailable(
$request->meja_id,
$request->date,
$request->start_time,
$request->end_time
)) {
return back()->withErrors(['time' => 'Waktu yang dipilih sudah dipesan']);
}
try {
// Create reservation
$reservation = Reservasi::create([
'user_id' => $request->user_id,
'meja_id' => $request->meja_id,
'name' => $request->name,
'phone' => $request->phone,
'date' => $request->date,
'start_time' => $request->start_time,
'end_time' => $request->end_time,
'notes' => $request->notes,
'status' => 'pending',
'total_harga' => $request->total_harga
]);
// Update table status if reservation is for today
if ($request->date == now()->format('Y-m-d')) {
Meja::where('id', $request->meja_id)
->update(['status' => 'dipesan']);
}
return redirect()->back()->with('success', 'Reservasi berhasil ditambahkan');
} catch (\Exception $e) {
Log::error('Error creating reservation:', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return back()->withErrors(['error' => 'Terjadi kesalahan saat membuat reservasi. Silakan coba lagi.'])->withInput();
}
}
public function update(Request $request, Reservasi $reservation)
{
$request->validate([
'status' => 'required|in:pending,confirmed,completed,cancelled',
'meja_id' => 'required|exists:meja,id'
]);
// Update both status and table
$reservation->update([
'status' => $request->status,
'meja_id' => $request->meja_id
]);
// Update table status based on reservation status
if ($reservation->date == now()->format('Y-m-d')) {
if ($request->status === 'confirmed') {
$reservation->meja()->update(['status' => 'dipesan']);
} elseif (in_array($request->status, ['completed', 'cancelled'])) {
$reservation->meja()->update(['status' => 'tersedia']);
}
}
if ($request->ajax()) {
return response()->json([
'success' => true,
'message' => 'Reservasi berhasil diperbarui'
]);
}
return redirect()->back()->with('success', 'Reservasi berhasil diperbarui');
}
public function destroy(Reservasi $reservation)
{
try {
// Set table status back to available if reservation was for today
if ($reservation->date == now()->format('Y-m-d') && $reservation->meja) {
$reservation->meja()->update(['status' => 'tersedia']);
}
$reservation->delete();
return redirect()->back()->with('success', 'Reservasi berhasil dihapus');
} catch (\Exception $e) {
Log::error('Error deleting reservation:', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return back()->withErrors(['error' => 'Terjadi kesalahan saat menghapus reservasi.']);
}
}
public function getAvailableTimeSlots(Request $request)
{
try {
Log::info('Admin getAvailableTimeSlots called with request:', [
'all_params' => $request->all(),
'date' => $request->date,
'meja_id' => $request->meja_id
]);
$request->validate([
'meja_id' => 'required|exists:meja,id',
'date' => 'required|date|after_or_equal:today',
]);
Log::info('Validation passed, getting reservations');
// Get existing reservations for this table and date
$reservations = Reservasi::where('meja_id', $request->meja_id)
->whereDate('date', $request->date)
->whereNotIn('status', ['cancelled'])
->get();
Log::info('Found existing reservations', [
'count' => $reservations->count(),
'reservations' => $reservations->toArray()
]);
$timeSlots = [];
$startHour = 10; // 10:00
$endHour = 22; // 22:00
$interval = 30; // 30 minutes interval
Log::info('Starting to generate time slots');
// Create a helper function to check if a time slot is reserved
$isTimeSlotReserved = function($checkTime) use ($reservations) {
$checkDateTime = Carbon::parse($checkTime);
foreach ($reservations as $reservation) {
$reservationStart = Carbon::parse($reservation->start_time);
$reservationEnd = Carbon::parse($reservation->end_time);
if ($checkDateTime->between($reservationStart, $reservationEnd, true)) {
return true;
}
}
return false;
};
// Generate all possible time slots
for ($hour = $startHour; $hour < $endHour; $hour++) {
for ($minute = 0; $minute < 60; $minute += $interval) {
$currentTime = sprintf('%02d:%02d', $hour, $minute);
// Check if this time slot is already reserved
$isReserved = $isTimeSlotReserved($currentTime);
if (!$isReserved) {
$endTimeOptions = [];
// Generate possible end times (30 minutes to 4 hours after start time)
for ($duration = 30; $duration <= 240; $duration += 30) {
$potentialEndTime = Carbon::parse($currentTime)->addMinutes($duration);
// Don't add end times past closing time
if ($potentialEndTime->format('H:i') > '22:00') {
continue;
}
// Check if any time between start and potential end time is reserved
$hasConflict = false;
$checkTime = Carbon::parse($currentTime);
while ($checkTime < $potentialEndTime) {
if ($isTimeSlotReserved($checkTime->format('H:i'))) {
$hasConflict = true;
break;
}
$checkTime->addMinutes(30);
}
if (!$hasConflict) {
$endTimeOptions[] = $potentialEndTime->format('H:i');
}
}
// Only add start time if it has at least one valid end time option
if (count($endTimeOptions) > 0) {
$timeSlots[] = [
'start_time' => $currentTime,
'end_time_options' => $endTimeOptions,
'is_available' => true
];
}
} else {
// Add reserved time slot
$timeSlots[] = [
'start_time' => $currentTime,
'end_time_options' => [],
'is_available' => false
];
}
}
}
// If date is today, remove past time slots
if ($request->date == Carbon::today()->format('Y-m-d')) {
$currentTime = Carbon::now();
Log::info('Filtering past time slots for today', [
'current_time' => $currentTime->format('H:i'),
'before_count' => count($timeSlots)
]);
$timeSlots = array_filter($timeSlots, function($slot) use ($currentTime) {
return Carbon::parse($slot['start_time'])->gt($currentTime);
});
Log::info('After filtering past slots', [
'after_count' => count($timeSlots)
]);
}
$timeSlots = array_values($timeSlots);
Log::info('Generated available time slots', [
'count' => count($timeSlots),
'first_few_slots' => array_slice($timeSlots, 0, 3)
]);
return response()->json([
'success' => true,
'data' => $timeSlots
]);
} catch (\Exception $e) {
Log::error('Error in admin getAvailableTimeSlots', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan saat memuat jadwal: ' . $e->getMessage()
], 500);
}
}
}