diff --git a/src/Controller/Groups/AbstractAccommodationController.php b/src/Controller/Groups/Booking/AbstractController.php
similarity index 91%
rename from src/Controller/Groups/AbstractAccommodationController.php
rename to src/Controller/Groups/Booking/AbstractController.php
index f8f0168..c41efaf 100644
--- a/src/Controller/Groups/AbstractAccommodationController.php
+++ b/src/Controller/Groups/Booking/AbstractController.php
@@ -2,15 +2,15 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Booking;
use App\Exception\AccommodationSessionNotFoundException;
use App\Form\Model\AccommodationBookingDto;
-use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SymfonyAbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
-abstract class AbstractAccommodationController extends AbstractController
+abstract class AbstractController extends SymfonyAbstractController
{
protected function validateStepAccess(AccommodationBookingDto $dto, int $expectedStep): ?RedirectResponse
{
diff --git a/src/Controller/Groups/IndexController.php b/src/Controller/Groups/Booking/IndexController.php
similarity index 96%
rename from src/Controller/Groups/IndexController.php
rename to src/Controller/Groups/Booking/IndexController.php
index e006b24..96f5cf9 100644
--- a/src/Controller/Groups/IndexController.php
+++ b/src/Controller/Groups/Booking/IndexController.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Booking;
use App\Htmx\HxTrait;
use App\Model\AccommodationBookingQueryParams;
@@ -14,7 +14,7 @@ use Symfony\Component\HttpFoundation\Session\FlashBagAwareSessionInterface;
use Symfony\Component\HttpKernel\Attribute\MapQueryString;
use Symfony\Component\Routing\Attribute\Route;
-class IndexController extends AbstractAccommodationController
+class IndexController extends AbstractController
{
use HxTrait;
diff --git a/src/Controller/Groups/Step1Controller.php b/src/Controller/Groups/Booking/Step1Controller.php
similarity index 99%
rename from src/Controller/Groups/Step1Controller.php
rename to src/Controller/Groups/Booking/Step1Controller.php
index 9096b6d..c5bd371 100644
--- a/src/Controller/Groups/Step1Controller.php
+++ b/src/Controller/Groups/Booking/Step1Controller.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Booking;
use App\BpnConnect\ContingentsClient;
use App\BpnConnect\Exception\BpnConnectException;
@@ -24,7 +24,7 @@ use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
-class Step1Controller extends AbstractAccommodationController
+class Step1Controller extends AbstractController
{
use HxTrait;
diff --git a/src/Controller/Groups/Step2Controller.php b/src/Controller/Groups/Booking/Step2Controller.php
similarity index 98%
rename from src/Controller/Groups/Step2Controller.php
rename to src/Controller/Groups/Booking/Step2Controller.php
index a3a89e8..6585f71 100644
--- a/src/Controller/Groups/Step2Controller.php
+++ b/src/Controller/Groups/Booking/Step2Controller.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Booking;
use App\Entity\Groups\AdditionalService;
use App\Entity\Groups\BoardService;
@@ -19,7 +19,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
-class Step2Controller extends AbstractAccommodationController
+class Step2Controller extends AbstractController
{
use HxTrait;
diff --git a/src/Controller/Groups/Step3Controller.php b/src/Controller/Groups/Booking/Step3Controller.php
similarity index 96%
rename from src/Controller/Groups/Step3Controller.php
rename to src/Controller/Groups/Booking/Step3Controller.php
index 0a5cee2..19600de 100644
--- a/src/Controller/Groups/Step3Controller.php
+++ b/src/Controller/Groups/Booking/Step3Controller.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Booking;
use App\Entity\Groups\Accommodation;
use App\Exception\AccommodationSessionNotFoundException;
@@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
-class Step3Controller extends AbstractAccommodationController
+class Step3Controller extends AbstractController
{
public function __construct(
private readonly AccommodationBookingService $bookingService,
diff --git a/src/Controller/Groups/Step4Controller.php b/src/Controller/Groups/Booking/Step4Controller.php
similarity index 95%
rename from src/Controller/Groups/Step4Controller.php
rename to src/Controller/Groups/Booking/Step4Controller.php
index 7e46c69..e613422 100644
--- a/src/Controller/Groups/Step4Controller.php
+++ b/src/Controller/Groups/Booking/Step4Controller.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Booking;
use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AdditionalService;
@@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
-class Step4Controller extends AbstractAccommodationController
+class Step4Controller extends AbstractController
{
use HxTrait;
@@ -80,7 +80,7 @@ class Step4Controller extends AbstractAccommodationController
$inquiryForm = $this->createForm(AccommodationInquiryConfirmationType::class);
- return $this->render('groups/booking/_step4_inquiry_confirmation_modal.html.twig', [
+ return $this->render('groups/booking/modal_inquiry_confirmation.html.twig', [
'inquiryForm' => $inquiryForm,
]);
}
@@ -107,7 +107,7 @@ class Step4Controller extends AbstractAccommodationController
return $this->htmxRedirect($request, $this->generateUrl('app_groups_booking_success'));
}
- return $this->render('groups/booking/_step4_booking_confirmation_modal.html.twig', [
+ return $this->render('groups/booking/modal_booking_confirmation.html.twig', [
'confirmationForm' => $confirmationForm,
]);
}
diff --git a/src/Controller/Groups/OfferController.php b/src/Controller/Groups/Offer/IndexController.php
similarity index 86%
rename from src/Controller/Groups/OfferController.php
rename to src/Controller/Groups/Offer/IndexController.php
index 3ec954a..7c5ef90 100644
--- a/src/Controller/Groups/OfferController.php
+++ b/src/Controller/Groups/Offer/IndexController.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Controller\Groups;
+namespace App\Controller\Groups\Offer;
use App\Entity\Groups\AccommodationBooking;
use App\Form\Model\OfferAcceptDto;
@@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
-class OfferController extends AbstractController
+class IndexController extends AbstractController
{
use HxTrait;
@@ -38,35 +38,35 @@ class OfferController extends AbstractController
* authorizes the session for this booking, and redirects to the plain
* (session-gated) offer page — nothing downstream needs the signature again.
*/
- #[Route(path: '/groups/booking/offer/{uuid}', name: 'app_groups_booking_offer', methods: ['GET'])]
+ #[Route(path: '/groups/booking/offer/{uuid}', name: 'app_groups_offer', methods: ['GET'])]
public function access(string $uuid, Request $request): Response
{
$booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]);
if (null === $booking || false === $this->linkSigner->isValidLinkRequest($request, $booking)) {
- return $this->render('groups/booking/offer_unavailable.html.twig');
+ return $this->render('groups/offer/unavailable.html.twig');
}
if (!$this->isCustomerVisible($booking)) {
- return $this->render('groups/booking/offer_unavailable.html.twig');
+ return $this->render('groups/offer/unavailable.html.twig');
}
$this->linkSigner->authorizeSession($request, $booking);
- return new RedirectResponse($this->generateUrl('app_groups_booking_offer_view', ['uuid' => $uuid]));
+ return new RedirectResponse($this->generateUrl('app_groups_offer_view', ['uuid' => $uuid]));
}
- #[Route(path: '/groups/booking/offer/{uuid}/view', name: 'app_groups_booking_offer_view', methods: ['GET'])]
+ #[Route(path: '/groups/booking/offer/{uuid}/view', name: 'app_groups_offer_view', methods: ['GET'])]
public function view(string $uuid, Request $request): Response
{
$booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]);
if (null === $booking || false === $this->linkSigner->isSessionAuthorized($request, $booking)) {
- return $this->render('groups/booking/offer_unavailable.html.twig');
+ return $this->render('groups/offer/unavailable.html.twig');
}
if (!$this->isCustomerVisible($booking)) {
- return $this->render('groups/booking/offer_unavailable.html.twig');
+ return $this->render('groups/offer/unavailable.html.twig');
}
$accommodation = $booking->getAccommodation() ?? throw $this->createNotFoundException('Booking has no accommodation.');
@@ -78,14 +78,14 @@ class OfferController extends AbstractController
priceBreakdown: $priceBreakdown,
);
- return $this->render('groups/booking/offer.html.twig', [
+ return $this->render('groups/offer/view.html.twig', [
'booking' => $booking,
'priceBreakdown' => $priceBreakdown,
'ctx' => $ctx,
]);
}
- #[Route(path: '/groups/booking/offer/{uuid}/confirm', name: 'app_groups_booking_offer_confirm', methods: ['GET', 'POST'])]
+ #[Route(path: '/groups/booking/offer/{uuid}/confirm', name: 'app_groups_offer_confirm', methods: ['GET', 'POST'])]
public function confirm(string $uuid, Request $request): Response
{
$booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]);
@@ -115,7 +115,7 @@ class OfferController extends AbstractController
return $this->redirectToOfferPage($request, $uuid);
}
- return $this->render('groups/booking/_offer_accept_confirmation_modal.html.twig', [
+ return $this->render('groups/offer/modal_accept_confirmation.html.twig', [
'booking' => $booking,
'confirmationForm' => $confirmationForm,
]);
@@ -138,7 +138,7 @@ class OfferController extends AbstractController
*/
private function redirectToOfferPage(Request $request, string $uuid): Response
{
- $url = $this->generateUrl('app_groups_booking_offer_view', ['uuid' => $uuid]);
+ $url = $this->generateUrl('app_groups_offer_view', ['uuid' => $uuid]);
return $this->htmxRedirect($request, $url);
}
diff --git a/src/Service/AccommodationBookingLinkSigner.php b/src/Service/AccommodationBookingLinkSigner.php
index 8b608ca..34a1d3c 100644
--- a/src/Service/AccommodationBookingLinkSigner.php
+++ b/src/Service/AccommodationBookingLinkSigner.php
@@ -34,7 +34,7 @@ class AccommodationBookingLinkSigner
}
$url = $this->urlGenerator->generate(
- 'app_groups_booking_offer',
+ 'app_groups_offer',
['uuid' => $booking->getUuid(), self::TIMESTAMP_PARAM => $issuedAt->getTimestamp()],
UrlGeneratorInterface::ABSOLUTE_URL,
);
diff --git a/templates/email/_price_breakdown.html.twig b/templates/email/_price_breakdown.html.twig
index 67c5668..b5be216 100644
--- a/templates/email/_price_breakdown.html.twig
+++ b/templates/email/_price_breakdown.html.twig
@@ -1,5 +1,5 @@
{#- Prices only — travel dates and group size belong to _stay_details.html.twig and the
- PDF's own data block. Mirrors groups/booking/_offer_summary.html.twig, but with inline
+ PDF's own data block. Mirrors groups/offer/_summary.html.twig, but with inline
styles: neither the email layout nor dompdf ships table styling or Tailwind.
Context: booking, priceBreakdown, currency (set in AccommodationBookingService and
AccommodationBookingPdfGenerator). -#}
diff --git a/templates/groups/booking/_step4_personal_data_recap.html.twig b/templates/groups/booking/_step4_personal_data_recap.html.twig
deleted file mode 100644
index 051f09d..0000000
--- a/templates/groups/booking/_step4_personal_data_recap.html.twig
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
Persönliche Daten
-
-
- Gruppenname:
- {{ dto.groupName }}
-
-
- Name:
- {{ dto.salutation }} {{ dto.firstName }} {{ dto.lastName }}
-
-
- E-Mail:
- {{ dto.email }}
-
-
- Telefon:
- {{ dto.phone }}
-
-
- Adresse:
- {{ dto.street }}, {{ dto.zip }} {{ dto.city }}
-
- {% if dto.remarks %}
-
- Anmerkungen:
- {{ dto.remarks }}
-
- {% endif %}
-
-
diff --git a/templates/groups/booking/_step4_services_recap.html.twig b/templates/groups/booking/_step4_services_recap.html.twig
deleted file mode 100644
index ca4c190..0000000
--- a/templates/groups/booking/_step4_services_recap.html.twig
+++ /dev/null
@@ -1,42 +0,0 @@
-{% set selectedBoardService = null %}
-{% for service in ctx.boardServices %}
- {% if service.id == dto.selectedBoardServiceId %}
- {% set selectedBoardService = service %}
- {% endif %}
-{% endfor %}
-
-{% set selectedAdditionalServices = ctx.additionalServices|filter(service => service.id in dto.selectedAdditionalServiceIds) %}
-
-
-
Ausgewählte Leistungen
-
-
-
Verpflegung:
- {% if selectedBoardService %}
- {{ selectedBoardService.label }}
- {% if selectedBoardService.price > 0 %}
- — {{ (selectedBoardService.price / 100)|format_currency(ctx.accommodation.currency) }} pro Person und Nacht
- {% endif %}
- {% if selectedBoardService.description %}
-
{{ selectedBoardService.description|nl2br }}
- {% endif %}
- {% else %}
- Selbstversorgung
- {% endif %}
-
-
- {% if selectedAdditionalServices is not empty %}
-
-
Zusatzleistungen:
-
- {% for service in selectedAdditionalServices %}
- -
- {{ service.label }}
- — {{ (service.price / 100)|format_currency(ctx.accommodation.currency) }} {{ service.type.label|trans }}
-
- {% endfor %}
-
-
- {% endif %}
-
-
diff --git a/templates/groups/booking/_step4_booking_confirmation_modal.html.twig b/templates/groups/booking/modal_booking_confirmation.html.twig
similarity index 100%
rename from templates/groups/booking/_step4_booking_confirmation_modal.html.twig
rename to templates/groups/booking/modal_booking_confirmation.html.twig
diff --git a/templates/groups/booking/_step4_inquiry_confirmation_modal.html.twig b/templates/groups/booking/modal_inquiry_confirmation.html.twig
similarity index 100%
rename from templates/groups/booking/_step4_inquiry_confirmation_modal.html.twig
rename to templates/groups/booking/modal_inquiry_confirmation.html.twig
diff --git a/templates/groups/booking/step_4.html.twig b/templates/groups/booking/step_4.html.twig
index fbf508d..f1150f2 100644
--- a/templates/groups/booking/step_4.html.twig
+++ b/templates/groups/booking/step_4.html.twig
@@ -40,8 +40,80 @@
} %}
{% endif %}
- {% include 'groups/booking/_step4_services_recap.html.twig' with { 'dto': dto, 'ctx': ctx } %}
- {% include 'groups/booking/_step4_personal_data_recap.html.twig' with { 'dto': dto } %}
+ {% set selectedBoardService = null %}
+ {% for service in ctx.boardServices %}
+ {% if service.id == dto.selectedBoardServiceId %}
+ {% set selectedBoardService = service %}
+ {% endif %}
+ {% endfor %}
+
+ {% set selectedAdditionalServices = ctx.additionalServices|filter(service => service.id in dto.selectedAdditionalServiceIds) %}
+
+
+
Ausgewählte Leistungen
+
+
+
Verpflegung:
+ {% if selectedBoardService %}
+ {{ selectedBoardService.label }}
+ {% if selectedBoardService.price > 0 %}
+ — {{ (selectedBoardService.price / 100)|format_currency(ctx.accommodation.currency) }} pro Person und Nacht
+ {% endif %}
+ {% if selectedBoardService.description %}
+
{{ selectedBoardService.description|nl2br }}
+ {% endif %}
+ {% else %}
+ Selbstversorgung
+ {% endif %}
+
+
+ {% if selectedAdditionalServices is not empty %}
+
+
Zusatzleistungen:
+
+ {% for service in selectedAdditionalServices %}
+ -
+ {{ service.label }}
+ — {{ (service.price / 100)|format_currency(ctx.accommodation.currency) }} {{ service.type.label|trans }}
+
+ {% endfor %}
+
+
+ {% endif %}
+
+
+
+
+
Persönliche Daten
+
+
+ Gruppenname:
+ {{ dto.groupName }}
+
+
+ Name:
+ {{ dto.salutation }} {{ dto.firstName }} {{ dto.lastName }}
+
+
+ E-Mail:
+ {{ dto.email }}
+
+
+ Telefon:
+ {{ dto.phone }}
+
+
+ Adresse:
+ {{ dto.street }}, {{ dto.zip }} {{ dto.city }}
+
+ {% if dto.remarks %}
+
+ Anmerkungen:
+ {{ dto.remarks }}
+
+ {% endif %}
+
+
diff --git a/templates/groups/booking/_offer_summary.html.twig b/templates/groups/offer/_summary.html.twig
similarity index 100%
rename from templates/groups/booking/_offer_summary.html.twig
rename to templates/groups/offer/_summary.html.twig
diff --git a/templates/groups/booking/_offer_accept_confirmation_modal.html.twig b/templates/groups/offer/modal_accept_confirmation.html.twig
similarity index 93%
rename from templates/groups/booking/_offer_accept_confirmation_modal.html.twig
rename to templates/groups/offer/modal_accept_confirmation.html.twig
index 9d69f1e..2f053b1 100644
--- a/templates/groups/booking/_offer_accept_confirmation_modal.html.twig
+++ b/templates/groups/offer/modal_accept_confirmation.html.twig
@@ -12,7 +12,7 @@
{{ form_start(confirmationForm, {
- 'action': path('app_groups_booking_offer_confirm', { uuid: booking.uuid }),
+ 'action': path('app_groups_offer_confirm', { uuid: booking.uuid }),
'attr': {
'hx-target': '#htmx-modal',
'hx-swap': 'outerHTML',
diff --git a/templates/groups/booking/offer_unavailable.html.twig b/templates/groups/offer/unavailable.html.twig
similarity index 100%
rename from templates/groups/booking/offer_unavailable.html.twig
rename to templates/groups/offer/unavailable.html.twig
diff --git a/templates/groups/booking/offer.html.twig b/templates/groups/offer/view.html.twig
similarity index 98%
rename from templates/groups/booking/offer.html.twig
rename to templates/groups/offer/view.html.twig
index 9e6b2da..f8a8001 100644
--- a/templates/groups/booking/offer.html.twig
+++ b/templates/groups/offer/view.html.twig
@@ -37,7 +37,7 @@
- {% include 'groups/booking/_offer_summary.html.twig' with {
+ {% include 'groups/offer/_summary.html.twig' with {
booking: booking,
ctx: ctx,
currency: currency,
@@ -78,7 +78,7 @@