From 0f4b16c1940b4f8a04db8db938291af8dafa242c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Mon, 6 Oct 2025 16:43:55 +0200 Subject: [PATCH] feat: comprehensive booking overview for confirmation --- src/BusProNet/Model/Pickup.php | 45 ++++ src/BusProNet/Model/Travel.php | 18 ++ .../ParticipantFieldOptionsProvider.php | 35 +-- templates/booking/create_step_4.html.twig | 223 ++++++++++++++---- 4 files changed, 239 insertions(+), 82 deletions(-) diff --git a/src/BusProNet/Model/Pickup.php b/src/BusProNet/Model/Pickup.php index ad981d3..d4ae1c1 100644 --- a/src/BusProNet/Model/Pickup.php +++ b/src/BusProNet/Model/Pickup.php @@ -41,4 +41,49 @@ class Pickup #[Groups(['api:booking'])] public array $mapping = []; + + /** + * Gets the formatted label for the pickup location without pricing. + * + * Creates user-friendly labels following the pattern: + * - Primary format: "City (Street)" if street is available + * - Fallback format: "City" if no street information + * + * @return string The formatted pickup location label + */ + public function getLabel(): string + { + $label = $this->city ?? ''; + + if (null !== $this->street && '' !== trim($this->street)) { + $label .= ' ('.$this->street.')'; + } + + return $label; + } + + /** + * Gets the formatted label with pricing information. + * + * Formats the pickup label with price display: + * - Zero/null price: Just the label without price suffix + * - Positive price: "Label (€X,XX)" as surcharge + * - Negative price: "Label (-X,XX€ Rabatt)" as discount + * + * @return string The formatted pickup label with pricing + */ + public function getLabelWithPrice(): string + { + $label = $this->getLabel(); + + if (null === $this->price || 0.0 === $this->price) { + return $label; + } + + if ($this->price < 0) { + return sprintf('%s (-%s€ Rabatt)', $label, number_format(abs($this->price), 2, ',', '.')); + } + + return sprintf('%s (€%s)', $label, number_format($this->price, 2, ',', '.')); + } } diff --git a/src/BusProNet/Model/Travel.php b/src/BusProNet/Model/Travel.php index 92d7c67..4fb16e8 100644 --- a/src/BusProNet/Model/Travel.php +++ b/src/BusProNet/Model/Travel.php @@ -228,4 +228,22 @@ class Travel return $result; } + + /** + * Retrieves a room by its ID. + * + * @param int|null $roomId The room ID to search for + * + * @return Room|null The room with the matching ID, or null if not found + */ + public function getRoomById(?int $roomId): ?Room + { + if (null === $roomId) { + return null; + } + + $rooms = $this->getRoomsByIds([$roomId]); + + return false === empty($rooms) ? reset($rooms) : null; + } } diff --git a/src/Form/Service/ParticipantFieldOptionsProvider.php b/src/Form/Service/ParticipantFieldOptionsProvider.php index 3fc4a76..7d55cb0 100644 --- a/src/Form/Service/ParticipantFieldOptionsProvider.php +++ b/src/Form/Service/ParticipantFieldOptionsProvider.php @@ -544,46 +544,13 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider return $label; } - /** - * Format pickup labels with city and street information. - * - * Creates user-friendly labels for pickup locations following the existing pattern: - * - Primary format: "City (Street)" if street is available - * - Fallback format: "City" if no street information - * - * @param Pickup $pickup The pickup location to format - * - * @return string The formatted pickup location label - */ - private function formatPickupLabel(Pickup $pickup): string - { - $label = $pickup->city ?? ''; - - if (null !== $pickup->street && '' !== trim($pickup->street)) { - $label .= ' ('.$pickup->street.')'; - } - - return $label; - } - private function formatPickupLabelWithPrice(?Pickup $pickup): string { if (null === $pickup) { return ''; } - $label = $this->formatPickupLabel($pickup); - - if (null === $pickup->price || 0.0 === $pickup->price) { - return $label; - } - - if ($pickup->price < 0) { - // Negative prices are discounts - return sprintf('%s (-%s€ Rabatt)', $label, number_format(abs($pickup->price), 2, ',', '.')); - } - - return sprintf('%s (€%s)', $label, number_format($pickup->price, 2, ',', '.')); + return $pickup->getLabelWithPrice(); } /** diff --git a/templates/booking/create_step_4.html.twig b/templates/booking/create_step_4.html.twig index 30c0464..bb8c956 100644 --- a/templates/booking/create_step_4.html.twig +++ b/templates/booking/create_step_4.html.twig @@ -7,8 +7,7 @@

Neue Buchung

-
-
+

Buchung bestätigen

{# Travel Summary #} @@ -51,67 +50,205 @@ {% if loop.first %}(Anmelder){% endif %} -
+
+ {# Personal Data #} {% if participant.dateOfBirth %}
-
Geburtsdatum
+
Geburtsdatum
{{ participant.dateOfBirth|date('d.m.Y') }}
{% endif %} + {% if participant.gender %} +
+
Geschlecht
+
{{ participant.gender == 'M' ? 'Männlich' : 'Weiblich' }}
+
+ {% endif %} {% if participant.email %}
-
E-Mail
+
E-Mail
{{ participant.email }}
{% endif %} {% if participant.mobile %}
-
Telefon
+
Telefon
{{ participant.mobile }}
{% endif %} - - {# Selected Services #} - {% set services = [] %} - {% if participant.board is not empty %} - {% for boardItem in participant.board %} - {% set services = services|merge(['Verpflegung: ' ~ boardItem.label]) %} - {% endfor %} - {% endif %} - {% if participant.skiPass %} - {% set services = services|merge(['Skipass: ' ~ participant.skiPass.label]) %} - {% endif %} - {% if participant.rentals is not empty %} - {% for rental in participant.rentals %} - {% set services = services|merge(['Ausrüstung: ' ~ rental.label]) %} - {% endfor %} - {% endif %} - {% if participant.courses is not empty %} - {% for course in participant.courses %} - {% set services = services|merge(['Kurs: ' ~ course.label]) %} - {% endfor %} - {% endif %} - {% if participant.additionalServices is not empty %} - {% for service in participant.additionalServices %} - {% set services = services|merge(['Service: ' ~ service.label]) %} - {% endfor %} - {% endif %} - {% if participant.insurance %} - {% set services = services|merge(['Versicherung: ' ~ participant.insurance.label]) %} + {% if participant.nationality %} +
+
Nationalität
+
{{ participant.nationality }}
+
{% endif %} - {% if services is not empty %} + {# Address #} + {% if participant.address and (participant.address.street or participant.address.city) %}
-
Gebuchte Leistungen
+
Adresse
+
+ {% if participant.address.street %}{{ participant.address.street }}
{% endif %} + {% if participant.address.postCode or participant.address.city %} + {{ participant.address.postCode }} {{ participant.address.city }}
+ {% endif %} + {% if participant.address.country %}{{ participant.address.country }}{% endif %} +
+
+ {% endif %} + + {# Room Assignment #} + {% set assignedRoom = bookingCreateDto.travel.getRoomById(participant.assignedRoomId) %} + {% if assignedRoom %} +
+
Zimmer
+
{{ assignedRoom.label }}
+
+ {% endif %} + + {# Room Remarks #} + {% if participant.remarksRoom %} +
+
Zimmerwunsch
+
{{ participant.remarksRoom }}
+
+ {% endif %} + + {# Transportation Services #} + {% if participant.transportationOutbound %} +
+
Anreise
+
{{ participant.transportationOutbound.label }}
+
+ {% endif %} + {% if participant.transportationInbound %} +
+
Abreise
+
{{ participant.transportationInbound.label }}
+
+ {% endif %} + + {# Pickup Locations #} + {% if participant.pickupOutbound %} +
+
Zustieg Hinfahrt
+
{{ participant.pickupOutbound.label }}
+
+ {% endif %} + {% if participant.pickupInbound %} +
+
Zustieg Rückfahrt
+
{{ participant.pickupInbound.label }}
+
+ {% endif %} + + {# Parking & License Plate #} + {% if participant.parking %} +
+
Parkplatz
+
Ja
+
+ {% endif %} + {% if participant.licensePlate %} +
+
Kennzeichen
+
{{ participant.licensePlate }}
+
+ {% endif %} + + {# Board Services #} + {% if participant.board is not empty %} +
+
Verpflegung
    - {% for service in services %} -
  • {{ service }}
  • + {% for boardItem in participant.board %} +
  • {{ boardItem.label }}
  • {% endfor %}
{% endif %} + + {# Ski Pass #} + {% if participant.skiPass %} +
+
Skipass
+
{{ participant.skiPass.label }}
+
+ {% endif %} + + {# Rentals #} + {% if participant.rentals is not empty %} +
+
Ausrüstung
+
+
    + {% for rental in participant.rentals %} +
  • {{ rental.label }}
  • + {% endfor %} +
+
+
+ {% endif %} + + {# Rental Insurance #} + {% if participant.rentalInsuranceSelected and participant.rentalInsurance %} +
+
Leihmaterial-Versicherung
+
{{ participant.rentalInsurance.label }}
+
+ {% endif %} + + {# Body Dimensions (if rentals selected) #} + {% if participant.rentals is not empty %} + {% if participant.height or participant.weight or participant.shoeSize %} +
+
Körpermaße
+
+ {% if participant.height %}Größe: {{ participant.height }} cm{% endif %} + {% if participant.weight %}{% if participant.height %}, {% endif %}Gewicht: {{ participant.weight }} kg{% endif %} + {% if participant.shoeSize %}{% if participant.height or participant.weight %}, {% endif %}Schuhgröße: {{ participant.shoeSize }}{% endif %} +
+
+ {% endif %} + {% endif %} + + {# Courses #} + {% if participant.courses is not empty %} +
+
Kurse
+
+
    + {% for course in participant.courses %} +
  • {{ course.label }}
  • + {% endfor %} +
+
+
+ {% endif %} + + {# Additional Services #} + {% if participant.additionalServices is not empty %} +
+
Zusatzleistungen
+
+
    + {% for service in participant.additionalServices %} +
  • {{ service.label }}
  • + {% endfor %} +
+
+
+ {% endif %} + + {# Insurance #} + {% if participant.insurance %} +
+
Reiseversicherung
+
{{ participant.insurance.label }}
+
+ {% endif %}
{% endfor %} @@ -159,15 +296,5 @@
{{ form_end(form) }} -
- -
- {% include 'booking/_summary.html.twig' with { - 'bookingCreateDto': bookingCreateDto, - 'participantCount': participantsCount, - 'groupedSelectedRooms': groupedSelectedRooms, - 'assignmentCounts': assignmentCounts - } %} -
{% endblock %} \ No newline at end of file