Black Friday: coupon FRIDAY24 for 40% off Yearly/Lifetime membership! Read more here

Reservations: Get Available Time Slots by Date

2024-05-26

If you want to pick the date and see the available un-booked time slots with Radio options, this example is for you.

Notice: This free snippet comes from our more complex Premium example Appointment System with Public Form.

First, in the Filament Resource, we create a DatePicker with live() behavior and a Radio with options set dynamically.

app/Filament/Resources/ReservationResource.php:

// ...
 
use App\Services\ReservationService;
 
// ...
 
public static function form(Form $form): Form
{
$dateFormat = 'Y-m-d';
 
return $form
->schema([
DatePicker::make('date')
->minDate(now()->format($dateFormat))
->maxDate(now()->addWeeks(2)->format($dateFormat))
->required()
->live(),
Radio::make('start_time')
->options(fn (Get $get) => (new ReservationService())->getAvailableTimesForDate($get('date')))
->hidden(fn (Get $get) => ! $get('date'))
->required()
->columnSpan(2),
]);
}

To pick the available time slots, we have a separate method in a Service class:

app/Services/ReservationService.php:

use App\Models\Reservation;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
 
class ReservationService
{
public function getAvailableTimesForDate(string $date): array
{
$date = Carbon::parse($date);
$startPeriod = $date->copy()->hour(9);
$endPeriod = $date->copy()->hour(17);
$times = CarbonPeriod::create($startPeriod, '1 hour', $endPeriod);
$availableReservations = [];
 
$reservations = Reservation::whereDate('start_time', $date)
->pluck('start_time')
->toArray();
 
$availableTimes = $times->filter(function ($time) use ($reservations) {
return ! in_array($time, $reservations);
})->toArray();
 
foreach ($availableTimes as $time) {
$key = $time->format('H');
$availableReservations[$key] = $time->format('H:i');
}
 
return $availableReservations;
}
}

You can flexibly change some parts here: for example, the limitation of 9 to 17 hours.

Finally, we need to save the data correctly, so we mutate it before saving:

app/Filament/Resources/ReservationResource/Pages/CreateReservation.php:

use Carbon\Carbon;
 
// ...
 
class CreateReservation extends CreateRecord
{
// ...
 
protected function mutateFormDataBeforeCreate(array $data): array
{
$date = Carbon::parse($data['date']);
$startTime = $date->hour($data['start_time']);
$endTime = $startTime->copy()->addHour();
 
$dateTimeFormat = 'Y-m-d H:i:s';
 
return [
'user_id' => auth()->id(),
'start_time' => $startTime->format($dateTimeFormat),
'end_time' => $endTime->format($dateTimeFormat),
];
}
}

Saving of the data is based on this DB Migration:

Schema::create('reservations', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(User::class)->constrained()->cascadeOnDelete();
 
$table->datetime('start_time');
$table->datetime('end_time');
$table->timestamps();
});

A few of our Premium Examples: