'\d+'])] #[IsGranted('ROLE_USER')] public function start(int $id, Request $request): Response { /** @var User $user */ $user = $this->getUser(); $this->bookingSessionService->clearBookingDto($request, BookingDto::MODE_EDIT); $this->dataLoader->invalidateBookingCache($id, $user); return $this->redirectToRoute('app_booking_edit', ['id' => $id]); } /** * Display participant cards overview. */ #[Route('/bookings/{id}/edit', name: 'app_booking_edit', requirements: ['id' => '\d+'])] #[IsGranted('ROLE_USER')] public function index(int $id, Request $request): Response { /** @var User $user */ $user = $this->getUser(); // Load form data from session (or API on first load) try { $bookingDto = $this->dataLoader->loadFormData($request, $id, $user); } catch (TravelNotFoundException) { $this->addFlash('error', 'Reisedaten sind nicht (mehr) verfügbar'); return $this->redirectToRoute('app_bookings'); } if (null === $bookingDto) { $this->addFlash('error', 'Buchungsdaten nicht (mehr) verfügbar'); return $this->redirectToRoute('app_bookings'); } // Show flash message if draft was restored if (true === $this->dataLoader->wasDraftRestored()) { $this->addFlash('info', 'Dein zuvor gespeicherter Entwurf wurde wiederhergestellt.'); } // Fetch booking data for display (surcharges, canceled status, etc.) $bookingData = $this->dataLoader->fetchBookingData($id, $user); if (null === $bookingData || $bookingData instanceof Notification) { $this->addFlash('error', 'Buchungsdaten nicht (mehr) verfügbar'); return $this->redirectToRoute('app_bookings'); } // Create validation form (same pattern as CreateStep2Controller) $form = $this->createForm(BookingEditType::class, $bookingDto); $form->handleRequest($request); // Handle form submission (clicking "Buchung aktualisieren") if ($form->isSubmitted() && $form->isValid()) { return $this->submitService->handleSubmission($request, $bookingDto, $id, $user); } $bookingEditContext = $this->editContextFactory->createOverviewContext( $bookingDto, $bookingData, $this->fingerprintService->isDirty($bookingDto), $form->isSubmitted(), $form->isSubmitted() && false === $form->isValid(), ); $templateData = [ 'form' => $form->createView(), 'bookingEditContext' => $bookingEditContext, ]; return $this->render('booking/edit/index.html.twig', $templateData); } /** * Reloads booking data from API, discarding all session changes. * * GET: Returns modal HTML for confirmation * POST: Clears session and redirects to reload the booking */ #[Route( path: '/bookings/{id}/edit/reload', name: 'app_booking_edit_reload', requirements: ['id' => '\d+'] )] #[IsGranted('ROLE_USER')] public function reloadFromApi(int $id, Request $request): Response { if (Request::METHOD_POST === $request->getMethod()) { // Clear session to discard all changes $this->bookingSessionService->clearBookingDto($request, BookingDto::MODE_EDIT); // Delete draft since user explicitly chose to discard changes /** @var User $user */ $user = $this->getUser(); $this->draftService->deleteDraft($user, $id); $this->addFlash('success', 'Änderungen verworfen, Daten neu geladen'); return $this->redirectToRoute('app_booking_edit', ['id' => $id]); } return $this->render('booking/edit/modal_reload.html.twig', [ 'bookingId' => $id, ]); } /** * Handles "Zurück" button - clears session and preserves draft. * * Draft is preserved so the user can continue editing later. * Shows a flash message informing about the saved draft. */ #[Route( path: '/bookings/{id}/edit/cancel', name: 'app_booking_edit_cancel', requirements: ['id' => '\d+'] )] #[IsGranted('ROLE_USER')] public function cancelEdit(int $id, Request $request): Response { // Clear session state $this->bookingSessionService->clearBookingDto($request, BookingDto::MODE_EDIT); // Check if a draft exists to show appropriate message /** @var User $user */ $user = $this->getUser(); $draft = $this->draftService->findDraft($user, $id); if (null !== $draft) { $this->addFlash('info', 'Deine Änderungen wurden als Entwurf gespeichert.'); } return $this->redirectToRoute('app_bookings'); } }