bookingService ->getOrCreateBookingCreateDto($request); // Validate step access $this->validateStepAccess($bookingCreateDto, 2); // Ensure correct number of participants $this->ensureCorrectNumberOfParticipants($bookingCreateDto); $participantsCount = $this->getParticipantsCount($bookingCreateDto); $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); $form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [ 'attr' => ['novalidate' => 'novalidate'], 'validation_groups' => ['booking_create_step_2'], ]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $bookingCreateDto->currentStep = 3; $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); return $this->redirectToRoute('app_booking_create_step_3'); } $roomAssignmentCounts = $this->bookingService->getRoomAssignmentCounts($bookingCreateDto); return $this->render('booking/create_step_2.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'participantsCount' => $participantsCount, 'assignmentCounts' => $roomAssignmentCounts, 'form' => $form->createView(), ]); } /** * Handles HTMX requests for dynamic form updates when room selections change by submitting the form * without validation and returning a freshly rendered instance. */ #[Route('/bookings/create/participants/refresh', name: 'app_booking_create_step_2_refresh', methods: ['POST'])] public function refreshParticipantForm(Request $request): Response { $bookingCreateDto = $this->bookingService->getOrCreateBookingCreateDto($request); $participantsCount = $this->getParticipantsCount($bookingCreateDto); // Process form data without validation to capture current state $form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [ 'attr' => ['novalidate' => 'novalidate'], 'validation_groups' => false, ]); $form->handleRequest($request); $roomAssignmentCounts = $this->bookingService->getRoomAssignmentCounts($bookingCreateDto); // The DTO is now updated with the latest selection. // We can now render the blocks with the fresh data. return $this->htmxOobResponse( 'booking/create_step_2.html.twig', ['participants_form', 'booking_summary'], [ 'form' => $form->createView(), 'bookingCreateDto' => $bookingCreateDto, 'participantsCount' => $participantsCount, 'assignmentCounts' => $roomAssignmentCounts, ] ); } private function getParticipantsCount(BookingCreateDto $bookingCreateDto): int { return $this ->bookingService ->getParticipantsCount($bookingCreateDto->roomSelections, $bookingCreateDto->travelData); } private function ensureCorrectNumberOfParticipants(BookingCreateDto $bookingCreateDto): void { $participantsCount = $this->getParticipantsCount($bookingCreateDto); $participants = $bookingCreateDto->participants; $bookingCreateDto->participants = []; for ($i = 0; $i < $participantsCount; ++$i) { $participant = $participants[$i] ?? new ParticipantDto(); $participant->index = $i; $bookingCreateDto->participants[$i] = $participant; } } }