Initial commit
This commit is contained in:
commit
c909d539bc
7178 files changed
+756624
No files matched your search
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Slot;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class CalendarService
|
||||
{
|
||||
/**
|
||||
* Build calendar grid for Mon–Fri with your six daily times.
|
||||
*
|
||||
* @param Carbon $start Monday of the week you want to display
|
||||
* @param Carbon $now Current time (use 'Europe/London')
|
||||
* @param bool $applyShortNotice If true, mark ≤ 120 min as closed (student view)
|
||||
* @return array{headers: array<int, array{date:string,label:string}>, rows: array<int, array{time:string,label:string,cells:array<int,array{date:string,time:string,slot:int|null,status:string,class:string,name:?string}>}>, times: string[]}
|
||||
*/
|
||||
public function build(Carbon $start, Carbon $now, bool $applyShortNotice): array
|
||||
{
|
||||
$end = $start->copy()->addDays(6);
|
||||
|
||||
$weekdays = [1,2,3,4,5]; // Mon..Fri
|
||||
$times = ['09:00:00','10:00:00','11:00:00','14:00:00','15:00:00','16:00:00'];
|
||||
|
||||
// Get all slots with bookings in the visible week
|
||||
$slots = Slot::with(['bookings' => function ($q) use ($start, $end) {
|
||||
$q->whereBetween('date', [$start->toDateString(), $end->toDateString()]);
|
||||
}])->get();
|
||||
|
||||
// Map slots by weekday/time for O(1) lookup in the loop
|
||||
$map = [];
|
||||
foreach ($slots as $s) {
|
||||
$map[(int)$s->weekday][$s->time] = $s;
|
||||
}
|
||||
|
||||
// Column headers
|
||||
$headers = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$d = $start->copy()->addDays($i);
|
||||
$headers[] = [
|
||||
'date' => $d->toDateString(),
|
||||
'label' => $d->format('D d M'),
|
||||
];
|
||||
}
|
||||
|
||||
// Rows (each time)
|
||||
$rows = [];
|
||||
foreach ($times as $time) {
|
||||
$cells = [];
|
||||
foreach ($weekdays as $wd) {
|
||||
$date = $start->copy()->addDays($wd - 1)->toDateString();
|
||||
$slot = $map[$wd][$time] ?? null;
|
||||
$booking = $slot ? $slot->bookings->firstWhere('date', $date) : null;
|
||||
|
||||
// Compute short-notice closure only when required (students)
|
||||
$sessionStart = Carbon::createFromFormat('Y-m-d H:i:s', "{$date} {$time}", $now->timezone);
|
||||
$minutesUntil = $now->diffInMinutes($sessionStart, false);
|
||||
$tooSoon = $applyShortNotice ? ($minutesUntil <= 120) : false;
|
||||
|
||||
// Decide status + cell class
|
||||
$status = 'closed';
|
||||
$class = 'bg-gray-100';
|
||||
$name = null;
|
||||
|
||||
if ($booking) {
|
||||
if ($booking->status === 'booked') { $status = 'booked'; $class = 'bg-red-200'; }
|
||||
elseif ($booking->status === 'blocked') { $status = 'blocked'; $class = 'bg-yellow-200'; }
|
||||
} elseif (!$slot) {
|
||||
$status = 'not_seeded'; // slot wasn’t seeded for this weekday/time
|
||||
} elseif ($minutesUntil < 0 || $tooSoon) {
|
||||
$status = 'closed';
|
||||
} else {
|
||||
$status = 'free';
|
||||
$class = 'bg-green-100';
|
||||
}
|
||||
|
||||
if ($booking && $booking->student_name) {
|
||||
$name = $booking->student_name;
|
||||
}
|
||||
|
||||
$cells[] = [
|
||||
'date' => $date,
|
||||
'time' => $time,
|
||||
'slot' => $slot?->id,
|
||||
'status' => $status, // free | booked | blocked | closed | not_seeded
|
||||
'class' => $class,
|
||||
'name' => $name,
|
||||
];
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'time' => $time,
|
||||
'label' => substr($time, 0, 5),
|
||||
'cells' => $cells,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'headers' => $headers,
|
||||
'rows' => $rows,
|
||||
'times' => $times,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user