477 lines
28 KiB
Twig
477 lines
28 KiB
Twig
{% extends 'layout.html.twig' %}
|
|
|
|
{% block title %}Buchung bestätigen{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1>Neue Buchung</h1>
|
|
|
|
<div id="form-wrapper">
|
|
{% include '_partials/_flashes.html.twig' %}
|
|
|
|
<h2 class="mb-6">Buchung bestätigen</h2>
|
|
|
|
{# Travel Summary #}
|
|
<div class="mb-8 p-6 bg-gray-50 rounded-lg border border-gray-200">
|
|
<h3 class="text-xl font-semibold mb-4">Reise</h3>
|
|
<dl class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<dt class="font-semibold text-gray-700">Reiseziel</dt>
|
|
<dd>{{ bookingCreateDto.travel.label }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt class="font-semibold text-gray-700">Zeitraum</dt>
|
|
<dd>{{ bookingCreateDto.travel.dateFrom|date('d.m.Y') }} - {{ bookingCreateDto.travel.dateTo|date('d.m.Y') }}</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
|
|
{# Detailed Pricing Breakdown #}
|
|
<div class="mb-8 p-6 bg-blue-50 rounded-lg border border-blue-200">
|
|
<h3 class="text-xl font-semibold mb-6 text-blue-900">Preisübersicht</h3>
|
|
|
|
{# Rooms Section #}
|
|
{% if pricingData.rooms is not empty %}
|
|
<div class="mb-6 pb-6 border-b border-blue-200">
|
|
<h4 class="font-semibold text-lg mb-3 text-blue-800">Unterkunft</h4>
|
|
<div class="space-y-2">
|
|
{% for roomPricing in pricingData.rooms %}
|
|
<div class="flex justify-between items-start">
|
|
<div class="text-sm text-gray-700">
|
|
<span class="font-medium">{{ roomPricing.quantity }}x {{ roomPricing.label }}</span>
|
|
{% if assignmentCounts is defined and assignmentCounts[roomPricing.roomId] is defined %}
|
|
<span class="block text-xs text-gray-600">{{ assignmentCounts[roomPricing.roomId] }} Person(en) belegt</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="text-gray-900 font-semibold">
|
|
€{{ roomPricing.totalPrice|number_format(2, ',', '.') }}
|
|
</div>
|
|
<div class="text-xs text-gray-600">
|
|
€{{ roomPricing.unitPrice|number_format(2, ',', '.') }} pro Person
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Services Section #}
|
|
{% if pricingData.services is not empty %}
|
|
<div class="mb-6 pb-6 border-b border-blue-200">
|
|
<h4 class="font-semibold text-lg mb-3 text-blue-800">Leistungen</h4>
|
|
{% for serviceGroup in pricingData.services %}
|
|
<div class="mb-4 last:mb-0">
|
|
<h5 class="font-medium text-sm text-gray-700 mb-2 uppercase tracking-wide">{{ serviceGroup.groupName }}</h5>
|
|
<div class="space-y-1.5 ml-4">
|
|
{% for servicePricing in serviceGroup.services %}
|
|
<div class="flex justify-between items-center text-sm">
|
|
<span class="text-gray-700">
|
|
{{ servicePricing.participantCount }}x {{ servicePricing.label }}
|
|
{% if servicePricing.unitPrice is not null %}
|
|
<span class="text-xs text-gray-500">(€{{ servicePricing.unitPrice|number_format(2, ',', '.') }} pro Person)</span>
|
|
{% endif %}
|
|
</span>
|
|
<span class="font-medium text-gray-900">
|
|
€{{ servicePricing.totalPrice|number_format(2, ',', '.') }}
|
|
</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Grand Total #}
|
|
{% if pricingData.grandTotal is defined and pricingData.grandTotal > 0 %}
|
|
<div class="pt-4">
|
|
{% set acceptedVouchers = bookingCreateDto.getAcceptedVouchers() %}
|
|
{% if acceptedVouchers and acceptedVouchers.hasVouchers() %}
|
|
{# Subtotal before vouchers #}
|
|
<div class="flex justify-between items-center mb-3">
|
|
<span class="text-lg text-blue-800">Gesamtpreis:</span>
|
|
<span class="text-lg text-blue-800">
|
|
€{{ pricingData.grandTotal|number_format(2, ',', '.') }}
|
|
</span>
|
|
</div>
|
|
|
|
{# Voucher discounts breakdown #}
|
|
<div class="mb-4 space-y-2 pb-4 border-b border-blue-200">
|
|
{% for voucher in acceptedVouchers.vouchers %}
|
|
<div class="flex justify-between items-center">
|
|
<span class="text-blue-700">
|
|
{% if voucher.promotional %}
|
|
Aktionsgutschein ({{ voucher.code }})
|
|
{% elseif voucher.goodwill %}
|
|
Kulanzgutschein ({{ voucher.code }})
|
|
{% elseif voucher.purchase %}
|
|
Kaufgutschein ({{ voucher.code }})
|
|
{% endif %}
|
|
</span>
|
|
<span class="font-semibold text-green-600">
|
|
-€{{ voucher.amount|number_format(2, ',', '.') }}
|
|
</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
{# Amount to pay after vouchers #}
|
|
<div class="flex justify-between items-center">
|
|
<span class="font-bold text-xl text-blue-900">Zu zahlen:</span>
|
|
<span class="font-bold text-2xl text-blue-900">
|
|
€{{ (pricingData.grandTotal - acceptedVouchers.totalDiscount)|number_format(2, ',', '.') }}
|
|
</span>
|
|
</div>
|
|
{% else %}
|
|
<div class="flex justify-between items-center">
|
|
<span class="font-bold text-xl text-blue-900">Gesamtpreis:</span>
|
|
<span class="font-bold text-2xl text-blue-900">
|
|
€{{ pricingData.grandTotal|number_format(2, ',', '.') }}
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{# Participants Summary #}
|
|
<div class="mb-8 p-6 bg-gray-50 rounded-lg border border-gray-200">
|
|
<h3 class="text-xl font-semibold mb-4">Teilnehmer ({{ participantCount }})</h3>
|
|
{% for participant in bookingCreateDto.participants %}
|
|
<div class="mb-6 pb-6 {% if not loop.last %}border-b border-gray-300{% endif %}">
|
|
<div class="flex justify-between items-start mb-3">
|
|
<h4 class="font-semibold text-lg">
|
|
{{ participant.firstName }} {{ participant.lastName }}
|
|
{% if loop.first %}<span class="text-sm text-gray-600">(Anmelder)</span>{% endif %}
|
|
</h4>
|
|
{% if participantPrices is defined and participantPrices[loop.index0] is defined %}
|
|
<div class="text-right">
|
|
<div class="text-xs text-gray-600 uppercase tracking-wide">Preis</div>
|
|
<div class="font-bold text-lg text-blue-700">€{{ participantPrices[loop.index0]|number_format(2, ',', '.') }}</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<dl class="grid grid-cols-2 gap-4 text-sm">
|
|
{# Personal Data #}
|
|
{% if participant.dateOfBirth %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Geburtsdatum</dt>
|
|
<dd>{{ participant.dateOfBirth|date('d.m.Y') }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if participant.gender %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Geschlecht</dt>
|
|
<dd>{{ participant.gender == 'M' ? 'Männlich' : 'Weiblich' }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if participant.email %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">E-Mail</dt>
|
|
<dd>{{ participant.email }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if participant.mobile %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Telefon</dt>
|
|
<dd>{{ participant.mobile }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if participant.nationality %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Nationalität</dt>
|
|
<dd>{{ participant.nationality }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Address #}
|
|
{% if participant.address and (participant.address.street or participant.address.city) %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold">Adresse</dt>
|
|
<dd>
|
|
{% if participant.address.street %}{{ participant.address.street }}<br>{% endif %}
|
|
{% if participant.address.postCode or participant.address.city %}
|
|
{{ participant.address.postCode }} {{ participant.address.city }}<br>
|
|
{% endif %}
|
|
{% if participant.address.country %}{{ participant.address.country }}{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Room Assignment #}
|
|
{% set assignedRoom = bookingCreateDto.travel.getRoomById(participant.assignedRoomId) %}
|
|
{% if assignedRoom %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Zimmer</dt>
|
|
<dd>
|
|
{{ assignedRoom.label }}
|
|
{% if assignedRoom.price is not null and assignedRoom.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ assignedRoom.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Room Remarks #}
|
|
{% if participant.remarksRoom %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Zimmerwunsch</dt>
|
|
<dd>{{ participant.remarksRoom }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Transportation Services #}
|
|
{% if participant.transportationOutbound %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Anreise</dt>
|
|
<dd>
|
|
{{ participant.transportationOutbound.label }}
|
|
{% if participant.transportationOutbound.price is not null and participant.transportationOutbound.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.transportationOutbound.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if participant.transportationInbound %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Abreise</dt>
|
|
<dd>
|
|
{{ participant.transportationInbound.label }}
|
|
{% if participant.transportationInbound.price is not null and participant.transportationInbound.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.transportationInbound.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Pickup Location #}
|
|
{% if participant.pickup %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Zu- und Ausstieg</dt>
|
|
<dd>
|
|
{{ participant.pickup.label }}
|
|
{% if participant.pickup.price is not null and participant.pickup.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.pickup.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Parking & License Plate #}
|
|
{% if participant.parking %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Parkplatz</dt>
|
|
<dd>
|
|
Ja
|
|
{% if participant.parkingService is not null and participant.parkingService.price is not null and participant.parkingService.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.parkingService.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if participant.licensePlate %}
|
|
<div>
|
|
<dt class="text-gray-600 font-semibold">Kennzeichen</dt>
|
|
<dd>{{ participant.licensePlate }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Board Services #}
|
|
{% if participant.board is not empty %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold mb-1">Verpflegung</dt>
|
|
<dd>
|
|
<ul class="list-disc list-inside">
|
|
{% for boardItem in participant.board %}
|
|
<li>
|
|
{{ boardItem.label }}
|
|
{% if boardItem.price is not null and boardItem.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ boardItem.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Ski Pass #}
|
|
{% if participant.skiPass %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold">Skipass</dt>
|
|
<dd>
|
|
{{ participant.skiPass.label }}
|
|
{% if participant.skiPass.price is not null and participant.skiPass.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.skiPass.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Rentals #}
|
|
{% if participant.rentals is not empty %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold mb-1">Ausrüstung</dt>
|
|
<dd>
|
|
<ul class="list-disc list-inside">
|
|
{% for rental in participant.rentals %}
|
|
<li>
|
|
{{ rental.label }}
|
|
{% if rental.price is not null and rental.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ rental.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Rental Insurance #}
|
|
{% if participant.rentalInsuranceSelected and participant.rentalInsurance %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold">Leihmaterial-Versicherung</dt>
|
|
<dd>
|
|
{{ participant.rentalInsurance.label }}
|
|
{% if participant.rentalInsurance.price is not null and participant.rentalInsurance.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.rentalInsurance.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Body Dimensions (if rentals selected) #}
|
|
{% if participant.rentals is not empty %}
|
|
{% if participant.height or participant.weight or participant.shoeSize %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold mb-1">Körpermaße</dt>
|
|
<dd>
|
|
{% 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 %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
{# Courses #}
|
|
{% if participant.courses is not empty %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold mb-1">Kurse</dt>
|
|
<dd>
|
|
<ul class="list-disc list-inside">
|
|
{% for course in participant.courses %}
|
|
<li>
|
|
{{ course.label }}
|
|
{% if course.price is not null and course.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ course.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Additional Services #}
|
|
{% if participant.additionalServices is not empty %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold mb-1">Zusatzleistungen</dt>
|
|
<dd>
|
|
<ul class="list-disc list-inside">
|
|
{% for service in participant.additionalServices %}
|
|
<li>
|
|
{{ service.label }}
|
|
{% if service.price is not null and service.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ service.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Insurance #}
|
|
{% if participant.insurance %}
|
|
<div class="col-span-2">
|
|
<dt class="text-gray-600 font-semibold">Reiseversicherung</dt>
|
|
<dd>
|
|
{{ participant.insurance.label }}
|
|
{% if participant.insurance.price is not null and participant.insurance.price != 0 %}
|
|
<span class="text-blue-700 font-semibold ml-1">(€{{ participant.insurance.price|number_format(2, ',', '.') }})</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
{# Payment Summary #}
|
|
<div class="mb-8 p-6 bg-gray-50 rounded-lg border border-gray-200">
|
|
<h3 class="text-xl font-semibold mb-4">Zahlungsart</h3>
|
|
<dl class="space-y-2">
|
|
<div>
|
|
<dt class="font-semibold text-gray-700">Gewählte Zahlungsart</dt>
|
|
<dd>
|
|
{% if bookingCreateDto.paymentMethod == constant('App\\BusProNet\\Constants::PAYMENT_METHOD_DEBIT') %}
|
|
Lastschrift (Einzugsermächtigungsverfahren)
|
|
{% else %}
|
|
Überweisung
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% if bookingCreateDto.paymentMethod == constant('App\\BusProNet\\Constants::PAYMENT_METHOD_DEBIT') and bookingCreateDto.bankAccount %}
|
|
<div>
|
|
<dt class="font-semibold text-gray-700">IBAN</dt>
|
|
<dd class="font-mono">{{ bookingCreateDto.bankAccount.iban }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt class="font-semibold text-gray-700">Kontoinhaber</dt>
|
|
<dd>{{ bookingCreateDto.bankAccount.accountHolder }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
|
|
{# Confirmation Form #}
|
|
{{ form_start(form, {
|
|
'attr': {
|
|
'novalidate': 'novalidate',
|
|
'hx-post': path('app_booking_create_step_4'),
|
|
'hx-target': '#form-wrapper',
|
|
'hx-select': '#form-wrapper',
|
|
'hx-swap': 'outerHTML'
|
|
}
|
|
}) }}
|
|
|
|
<div class="mb-8 p-6 bg-blue-50 border border-blue-200 rounded-lg">
|
|
{{ form_row(form.confirmationAccepted, {
|
|
'label_attr': {'class': 'text-base font-semibold'}
|
|
}) }}
|
|
{{ form_row(form.termsAccepted, {
|
|
'label_attr': {'class': 'text-base font-semibold'}
|
|
}) }}
|
|
</div>
|
|
|
|
<div class="flex justify-between pt-6">
|
|
<a href="{{ path('app_booking_create_step_3') }}" class="button bg-button bg-button--secondary">Zurück</a>
|
|
<button type="submit" class="button bg-button bg-button--primary" {{ stimulus_action('loading', 'toggle') }}>
|
|
{% if bookingCreateDto.bookingStatus == 'A' %}
|
|
Anfragen
|
|
{% else %}
|
|
Verbindlich buchen
|
|
{% endif %}
|
|
</button>
|
|
</div>
|
|
|
|
{{ form_end(form) }}
|
|
</div>
|
|
|
|
{% include 'booking/_cancel_link.html.twig' %}
|
|
{% endblock %}
|