feat: replace the navigation with a dashboard and per-area boards

This commit is contained in:
fromme committed 2026-09-13 18:08:39 +02:00
1 parent d63df2cc1b
commit bce8f58be3
26 files changed
+810 -328

No files matched your search

+15 -15
View File
@@ -10,16 +10,16 @@ use App\Repository\BookingRepository;
use App\Repository\ResourceRepository;
/**
* Builds the context behind the two fragments that make up the booking board: the month
* calendar and the floor plan.
* Builds the context behind the two fragments that make up a booking board: the month 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 (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.
* Everything here is relative to a ResourceType **and** a TimeRange. One board shows one kind of
* resource, and with part-day bookings "is this free?" has no answer without a span -- so both
* are carried through the occupancy counts and the plan colours alike, and the number in a
* calendar cell always means the same thing as the colours on the plan beside it.
*/
final readonly class BoardPresenter
{
@@ -34,7 +34,7 @@ final readonly class BoardPresenter
/**
* @return array<string, mixed>
*/
public function context(\DateTimeImmutable $selected, TimeRange $time, User $user): array
public function context(ResourceType $type, \DateTimeImmutable $selected, TimeRange $time, User $user): array
{
$selected = $selected->setTime(0, 0);
$today = new \DateTimeImmutable('today');
@@ -43,10 +43,10 @@ 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, $time);
$counts = $this->bookings->countPerDateInRange($gridStart, $gridEnd, $time, $type);
$mine = [];
foreach ($this->bookings->findForUserInRange($user, $gridStart, $gridEnd) as $booking) {
foreach ($this->bookings->findForUserInRange($user, $gridStart, $gridEnd, $type) as $booking) {
$mine[$booking->getDate()->format('Y-m-d')][] = $booking;
}
@@ -72,33 +72,33 @@ final readonly class BoardPresenter
}
$byResource = [];
foreach ($this->bookings->findForDate($selected, $time) as $booking) {
foreach ($this->bookings->findForDate($selected, $time, $type) 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 [
'type' => $type,
'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),
'resources' => $this->resources->findActiveByType($type),
'bookings_by_resource' => $byResource,
'my_bookings_today' => $mine[$selected->format('Y-m-d')] ?? [],
];
}
/**
* The query parameters that reproduce a board view, so links and HX-Push-Url agree.
* The route parameters that reproduce a board view, so links and HX-Push-Url agree.
*
* @return array<string, string>
*/
public static function urlParameters(\DateTimeImmutable $date, TimeRange $time): array
public static function urlParameters(ResourceType $type, \DateTimeImmutable $date, TimeRange $time): array
{
$parameters = ['tag' => $date->format('Y-m-d')];
$parameters = ['type' => $type->slug(), 'tag' => $date->format('Y-m-d')];
if (!$time->isAllDay()) {
$parameters['von'] = $time->start();