feat: add booking time ranges and repeating series
This commit is contained in:
1 parent
59feca2f8e
commit
d433d271d0
29 files changed
+2135
-180
No files matched your search
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Booking;
|
||||
|
||||
use App\Entity\Booking;
|
||||
use App\Entity\ResourceType;
|
||||
use App\Entity\User;
|
||||
use App\Repository\BookingRepository;
|
||||
@@ -15,7 +14,12 @@ use App\Repository\ResourceRepository;
|
||||
* calendar and the floor plan.
|
||||
*
|
||||
* Both are always rendered from the same context so that one htmx round trip can swap both --
|
||||
* picking a day updates the grid and the plan in a single out-of-band response.
|
||||
* picking a day (or a time span) updates the grid and the plan in a single out-of-band response.
|
||||
*
|
||||
* Everything here is relative to a TimeRange. With part-day bookings "is this desk free?" has no
|
||||
* answer on its own, only "is it free between 09:00 and 13:00?", so the span the user picked is
|
||||
* carried through the occupancy counts and the plan colours alike -- the number in a calendar
|
||||
* cell always means the same thing as the colours on the plan.
|
||||
*/
|
||||
final readonly class BoardPresenter
|
||||
{
|
||||
@@ -30,7 +34,7 @@ final readonly class BoardPresenter
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function context(\DateTimeImmutable $selected, User $user): array
|
||||
public function context(\DateTimeImmutable $selected, TimeRange $time, User $user): array
|
||||
{
|
||||
$selected = $selected->setTime(0, 0);
|
||||
$today = new \DateTimeImmutable('today');
|
||||
@@ -39,7 +43,7 @@ final readonly class BoardPresenter
|
||||
$gridStart = $monthStart->modify('monday this week');
|
||||
$gridEnd = $gridStart->modify(\sprintf('+%d days', self::WEEKS * 7 - 1));
|
||||
|
||||
$counts = $this->bookings->countPerDateInRange($gridStart, $gridEnd);
|
||||
$counts = $this->bookings->countPerDateInRange($gridStart, $gridEnd, $time);
|
||||
|
||||
$mine = [];
|
||||
foreach ($this->bookings->findForUserInRange($user, $gridStart, $gridEnd) as $booking) {
|
||||
@@ -68,29 +72,39 @@ final readonly class BoardPresenter
|
||||
}
|
||||
|
||||
$byResource = [];
|
||||
foreach ($this->bookings->findForDate($selected) as $booking) {
|
||||
$byResource[$booking->getResource()->getId()] = $booking;
|
||||
foreach ($this->bookings->findForDate($selected, $time) as $booking) {
|
||||
// Several bookings can overlap the span on one resource once times are in play; the
|
||||
// first is enough to colour the shape, and the tooltip lists them all.
|
||||
$byResource[$booking->getResource()->getId()][] = $booking;
|
||||
}
|
||||
|
||||
return [
|
||||
'selected_date' => $selected,
|
||||
'selected_time' => $time,
|
||||
'month_start' => $monthStart,
|
||||
'weeks' => $weeks,
|
||||
'is_past' => $selected < $today,
|
||||
'desks' => $this->resources->findActiveByType(ResourceType::DESK),
|
||||
'parking' => $this->resources->findActiveByType(ResourceType::PARKING),
|
||||
'bookings_by_resource' => $byResource,
|
||||
'my_bookings_today' => $this->mineOn($selected, $mine),
|
||||
'my_bookings_today' => $mine[$selected->format('Y-m-d')] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, list<Booking>> $mine
|
||||
* The query parameters that reproduce a board view, so links and HX-Push-Url agree.
|
||||
*
|
||||
* @return list<Booking>
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function mineOn(\DateTimeImmutable $date, array $mine): array
|
||||
public static function urlParameters(\DateTimeImmutable $date, TimeRange $time): array
|
||||
{
|
||||
return $mine[$date->format('Y-m-d')] ?? [];
|
||||
$parameters = ['tag' => $date->format('Y-m-d')];
|
||||
|
||||
if (!$time->isAllDay()) {
|
||||
$parameters['von'] = $time->start();
|
||||
$parameters['bis'] = $time->end();
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user