72 lines
2.5 KiB
PHP
72 lines
2.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Booking\BoardPresenter;
|
|
use App\Booking\DateParam;
|
|
use App\Booking\TimeRange;
|
|
use App\Htmx\HxTrait;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
|
|
/**
|
|
* The booking board: a month calendar next to the floor plan for the selected day and span.
|
|
*/
|
|
final class DashboardController extends AbstractController
|
|
{
|
|
use CurrentUserTrait;
|
|
use HxTrait;
|
|
|
|
public function __construct(private readonly BoardPresenter $board)
|
|
{
|
|
}
|
|
|
|
#[Route('/', name: 'app_dashboard', methods: ['GET'])]
|
|
public function index(Request $request): Response
|
|
{
|
|
$date = DateParam::parseOrToday($request->query->getString('tag'));
|
|
|
|
return $this->render('dashboard/index.html.twig', $this->board->context($date, self::timeOf($request), $this->currentUser()));
|
|
}
|
|
|
|
/**
|
|
* Picking a day -- or narrowing the span -- swaps the calendar and the floor plan in one
|
|
* response.
|
|
*
|
|
* This is the whole reason htmxOobResponse exists: two regions, one round trip, no
|
|
* client-side event choreography. Requests without the htmx header get a plain redirect
|
|
* rather than a bare pair of fragments, so the URL stays shareable.
|
|
*/
|
|
#[Route('/tag/{date}', name: 'app_dashboard_day', requirements: ['date' => DateParam::PATTERN], methods: ['GET'])]
|
|
public function day(Request $request, string $date): Response
|
|
{
|
|
$selected = DateParam::parseOrToday($date);
|
|
$time = self::timeOf($request);
|
|
|
|
if (!$request->headers->has('HX-Request')) {
|
|
return $this->redirectToRoute('app_dashboard', BoardPresenter::urlParameters($selected, $time));
|
|
}
|
|
|
|
return $this->htmxOobResponse(
|
|
'dashboard/index.html.twig',
|
|
['calendar', 'floorplan'],
|
|
$this->board->context($selected, $time, $this->currentUser()),
|
|
$this->generateUrl('app_dashboard', BoardPresenter::urlParameters($selected, $time)),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* A malformed or missing span falls back to the whole day rather than erroring: these are
|
|
* hand-editable query parameters, not route requirements.
|
|
*/
|
|
public static function timeOf(Request $request): TimeRange
|
|
{
|
|
return TimeRange::parse($request->query->getString('von'), $request->query->getString('bis'))
|
|
?? TimeRange::wholeDay();
|
|
}
|
|
}
|