Hello everyone, I have a question. In this component, reservations are saved, and these reservations need to be confirmed by a verification code. Reservations are initially saved as unconfirmed with is_confirmed set to false. When the user enters the code received by email, it is then set to is_confirmed = true. Now, regarding the issue, I want to handle the deletion of unconfirmed reservations within 15 minutes of creation if they are not confirmed with cron job. I initially considered using a cron job for this, but I'm not sure if it's the best solution. I wanted to ask if anyone has any ideas on how to handle this. My goal is that if a reservation is not confirmed, the corresponding available time slot should be returned to the available times, allowing someone else to choose it. I'm unsure whether using a cron job is the best approach or if an if statement with a Rule would be more appropriate.
This is component
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Blacklist;
use App\Models\Reservation;
use App\Mail\ReservationMail;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Mail;
use App\Models\AvailableBusinessHour;
class Booking extends Component
{
public $full_name;
public $email;
public $phone_number;
public $reservation;
public $selectedService;
public $available_business_hour_id;
public $selectedBusinessHourId;
public $verification_code;
public $successMessage;
public $successMessageVisible;
public $successMessageTimeout = 3000;
public $verificationCodeSubmitted = false;
public $successMessageClosed = false;
public function getAvailableBusinessHours()
{
return AvailableBusinessHour::whereDoesntHave('reservation')
->where(function ($query) {
$query->where('day', '>', now()->format('Y-m-d'))
->orWhere(function ($query) {
$query->where('day', '=', now()->format('Y-m-d'))
->where('from', '>', now()->format('H:i'));
});
})
->orderBy('day')
->orderBy('from')
->get();
}
public function render()
{
$this->available_business_hour_id = $this->getAvailableBusinessHours();
return view('livewire.booking', [
'emptyOption' => 'Vyber si čas rezervace',
]);
}
public function store()
{
$this->validate([
'full_name' => 'required|string|max:250',
'email' => [
'required',
'email',
'max:250',
Rule::unique('blacklist', 'email')->where(function ($query) {
return $query->where('email', $this->email);
}),
],
'phone_number' => 'required|phone:CZ',
'selectedService' => 'required',
'selectedBusinessHourId' => 'required|unique:reservations,available_business_hour_id'
], [
'email.unique' => 'Pod tímto e-mailem došlo k vytvoření podezřelého počtu rezervací a byl dán na blacklist, pokud se chcete zarezervovat tak pouze telefonicky.',
'selectedBusinessHourId.unique' => 'Tento termín byl již obsazen, vyber jiný pokud je nějaký dostupný.',
'selectedBusinessHourId.required' => 'Výběr času objednání je povinné pole.',
'phone_number.phone' => 'Chybný formát telefonního čísla.',
'selectedService.required' => 'Toto je povinné pole',
]);
$selectedBusinessHour = AvailableBusinessHour::find($this->selectedBusinessHourId);
if (!$selectedBusinessHour) {
$this->addError('selectedBusinessHourId', 'Vybraný čas není dostupný.');
return;
}
if (
$selectedBusinessHour->day < now()->format('Y-m-d') ||
($selectedBusinessHour->day == now()->format('Y-m-d') && $selectedBusinessHour->from < now()->format('H:i'))
) {
$this->addError('selectedBusinessHourId', 'Tento termín již není dostupný, vyberte jiný.');
return;
}
$verification_code = rand(100000, 999999);
$existingReservation = Reservation::where('available_business_hour_id', $this->selectedBusinessHourId)
->where('is_confirmed', false)
->first();
if ($existingReservation) {
$this->addError('selectedBusinessHourId', 'Tento termín byl již obsazen, vyberte jiný pokud je nějaký dostupný.');
return;
}
$isBlacklisted = Blacklist::where('email', $this->email)->exists();
if ($isBlacklisted) {
$this->addError('email', 'Tento e-mail je na blacklistu a nelze provést rezervaci.');
return;
}
$reservation = Reservation::create([
'full_name' => $this->full_name,
'email' => $this->email,
'phone_number' => $this->phone_number,
'service' => $this->selectedService,
'available_business_hour_id' => $this->selectedBusinessHourId,
'day' => $selectedBusinessHour['day'],
'from' => $selectedBusinessHour['from'],
'to' => $selectedBusinessHour['to'],
'verification_code' => $verification_code
]);
session(['verification_code' => $verification_code, 'current_reservation_id' => $reservation->id]);
$this->sendReservationConfirmationMail($reservation);
$this->dispatch('show-verification-modal');
$this->dispatch('update-success-message', ['closed' => $this->successMessageClosed]);
$this->reset(['full_name', 'email', 'phone_number', 'available_business_hour_id']);
}
public function sendReservationConfirmationMail($reservation)
{
Mail::to($reservation->email)->send(new ReservationMail($reservation));
}
public function services()
{
return ["Stříhání vlasů", "Stříhání + úprava vousů", "Barvení vousů", "Junior střih", "Úprava vousů"];
}
public function confirmReservation()
{
$this->validate([
'verification_code' => 'required|digits:6',
], [
'verification_code.required' => 'Zadejte prosím verifikační kód.',
'verification_code.digits' => 'Verifikační kód musí mít 6 čísel.',
]);
$user_entered_code = $this->verification_code;
$reservation = Reservation::where('verification_code', $user_entered_code)
->where('is_confirmed', false)
->where('id', session('current_reservation_id'))
->latest()
->first();
if ($reservation) {
$reservation->update(['is_confirmed' => true]);
$this->reset(['verification_code']);
$this->successMessage = 'Rezervace proběhla úspěšně.';
$this->successMessageVisible = true;
$this->dispatch('hide-verification-modal');
$this->dispatch('update-success-message', ['closed' => $this->successMessageClosed]);
} else {
$this->addError('verification_code', 'Neplatný verifikační kód nebo rezervace již byla potvrzena.');
}
}
}