feat: loading indicator on initial page load

This commit is contained in:
Björn Fromme
2025-12-16 13:44:25 +01:00
parent a576fa2d23
commit 59b9a42009
2 changed files with 44 additions and 15 deletions
@@ -37,26 +37,46 @@ class IndexController extends AbstractController
) {
}
/**
* Entry point for starting a new booking.
*
* Renders a loading page that triggers the actual initialization via HTMX.
* This provides immediate visual feedback while BusProNet API calls are made.
*/
#[Route(
path: '/bookings/create',
name: 'app_booking_create',
)]
public function index(#[MapQueryString] ?BookingQueryParams $params): Response
{
if (null === $params) {
throw $this->createNotFoundException('Invalid booking parameters provided');
}
return $this->render('booking/create/index.html.twig', [
'params' => $params,
]);
}
/**
* Initializes a fresh booking session and redirects to the login page.
*
* This endpoint provides a clean way to start the booking flow with just
* dateId and hotelId parameters. It clears any existing booking session,
* creates a fresh BookingDto, and redirects to the login page where users
* can authenticate (for prepopulation) or continue as guest.
* This endpoint is triggered via HTMX from the loading page. It clears any
* existing booking session, creates a fresh BookingDto, and redirects to
* the login page where users can authenticate or continue as guest.
*
* Optionally accepts an agency code parameter. If provided and valid, the
* corresponding agency ID is stored in the booking. If not provided or invalid,
* defaults to agency code '0001'.
*/
#[Route(
path: '/bookings/create',
path: '/bookings/create/init',
name: 'app_booking_create_init',
)]
public function init(Request $request, #[MapQueryString] ?BookingQueryParams $params): Response
{
if (null === $params) {
throw $this->createNotFoundException('Invalid booking parameters provided');
return $this->htmxRedirect($request, $this->generateUrl('app_booking_create_error'));
}
$dateId = $params->dateId;
@@ -85,15 +105,9 @@ class IndexController extends AbstractController
);
// Redirect to login page (optional authentication before Step 1)
return $this->redirectToRoute('app_login');
} catch (TravelNotFoundException) {
throw $this->createNotFoundException(sprintf('Travel not found for date ID %d', $dateId));
} catch (HotelNotFoundException) {
throw $this->createNotFoundException(sprintf('Hotel not found for hotel ID %d', $hotelId));
} catch (HotelNotInTravelException) {
throw $this->createNotFoundException(sprintf('Hotel ID %d is not available for travel ID %d', $hotelId, $dateId));
} catch (NoRoomsAvailableException) {
throw $this->createNotFoundException('No rooms available for this travel.');
return $this->htmxRedirect($request, $this->generateUrl('app_login'));
} catch (TravelNotFoundException|HotelNotFoundException|HotelNotInTravelException|NoRoomsAvailableException) {
return $this->htmxRedirect($request, $this->generateUrl('app_booking_create_error'));
}
}
+15
View File
@@ -0,0 +1,15 @@
{% extends 'layout_booking.html.twig' %}
{% block content %}
<div class="flex-1 flex items-center justify-center"
hx-get="{{ path('app_booking_create_init', {
date_id: params.dateId,
hotel_id: params.hotelId,
agency: params.agency,
theme: params.theme,
r: params.returnUrl
}) }}"
hx-trigger="load"
hx-swap="none">
</div>
{% endblock %}