- {{ macros.field_or_static(form, 'firstName', 'Vorname', form.vars.data.participant.firstName, bookingDto, participantIndex) }}
- {{ macros.field_or_static(form, 'lastName', 'Nachname', form.vars.data.participant.lastName, bookingDto, participantIndex) }}
+
- {{ macros.field_or_static(
- form,
- 'dateOfBirth',
- 'Geburtsdatum',
- form.vars.data.participant.dateOfBirth ? form.vars.data.participant.dateOfBirth|date('d.m.Y') : null,
- bookingDto,
- participantIndex,
- {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content',
- 'hx-swap': 'innerHTML'
- }
- }
- ) }}
+ {% from '_partials/_validation_errors.html.twig' import validation_alert %}
+ {{ validation_alert(form) }}
- {% set genderLabel = form.vars.data.participant.gender == 'M' ? 'männlich' : (form.vars.data.participant.gender == 'W' ? 'weiblich' : (form.vars.data.participant.gender == 'D' ? 'divers' : null)) %}
- {{ macros.field_or_static(form, 'gender', 'Geschlecht', genderLabel, bookingDto, participantIndex) }}
+ {# Eligibility checks #}
+ {% set participantData = form.vars.data.participant %}
+ {% set hasDateOfBirth = participantData and participantData.dateOfBirth %}
+ {% set isEligible = hasDateOfBirth and is_participant_eligible(bookingDto, participantIndex) %}
- {{ macros.field_or_static(form, 'nationality', 'Nationalität', form.vars.data.participant.nationality|map_nationality, bookingDto, participantIndex) }}
-
+ {% if not hasDateOfBirth %}
+ {% include '_partials/_alert.html.twig' with {
+ level: 'info',
+ messages: ['Leistungen sind erst nach Angabe des Geburtsdatums buchbar']
+ } %}
+ {% elseif not isEligible %}
+ {% include '_partials/_alert.html.twig' with {
+ level: 'error',
+ messages: ['Buchung wegen des Alters von Teilnehmer:in ' ~ (participantIndex + 1) ~ ' nicht möglich']
+ } %}
+ {% endif %}
+
+ {# Personal data section #}
+
+ {{ macros.field_or_static(form, 'firstName', 'Vorname', form.vars.data.participant.firstName, bookingDto, participantIndex) }}
+ {{ macros.field_or_static(form, 'lastName', 'Nachname', form.vars.data.participant.lastName, bookingDto, participantIndex) }}
+ {{ macros.field_or_static(
+ form,
+ 'dateOfBirth',
+ 'Geburtsdatum',
+ form.vars.data.participant.dateOfBirth ? form.vars.data.participant.dateOfBirth|date('d.m.Y') : null,
+ bookingDto,
+ participantIndex,
+ {
+ 'attr': {
+ 'hx-trigger': 'change',
+ 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
+ 'hx-target': '#main-content',
+ 'hx-swap': 'innerHTML'
+ }
+ }
+ ) }}
+
+ {% set genderLabel = form.vars.data.participant.gender == 'M' ? 'männlich' : (form.vars.data.participant.gender == 'W' ? 'weiblich' : (form.vars.data.participant.gender == 'D' ? 'divers' : null)) %}
+ {{ macros.field_or_static(form, 'gender', 'Geschlecht', genderLabel, bookingDto, participantIndex) }}
+
+ {{ macros.field_or_static(form, 'nationality', 'Nationalität', form.vars.data.participant.nationality|map_nationality, bookingDto, participantIndex) }}
{# Contact information #}
-
- {{ macros.field_or_static(form, 'email', 'E-Mail', form.vars.data.participant.email, bookingDto, participantIndex) }}
- {{ macros.field_or_static(form, 'mobile', 'Telefon (mobil)', form.vars.data.participant.mobile, bookingDto, participantIndex) }}
-
-
- {# Address #}
- {% if form.address is defined %}
- {# Address field is in form - render as editable form fields #}
-
- {{ form_row(form.address.street) }}
- {{ form_row(form.address.postCode) }}
- {{ form_row(form.address.city) }}
- {{ form_row(form.address.country) }}
-
- {% elseif is_static_text('address', bookingDto, participantIndex) %}
- {# Address excluded from form but should render as static text #}
- {# For applicant (index 0), use booking.applicant.address which has full data from BPN #}
- {# For other participants, use participants[index].address (may only have country in BPN response) #}
- {% set addressSource = (0 == participantIndex and bookingDto.booking) ? bookingDto.booking.applicant : bookingDto.participants[participantIndex] %}
-
-
- {% if addressSource.address %}
-
- {% if addressSource.address.street %}{{ addressSource.address.street }}
{% endif %}
- {% if addressSource.address.postCode or addressSource.address.city %}
- {{ addressSource.address.postCode }} {{ addressSource.address.city }}
- {% endif %}
- {% if addressSource.address.country %}{{ addressSource.address.country|map_country }}{% endif %}
-
- {% else %}
-
-
- {% endif %}
-
- {% endif %}
-
- {# Room assignment - hidden until date of birth is provided, or shown as static text in edit mode #}
- {% if form.assignedRoomId is defined or is_static_text('assignedRoomId', bookingDto, participantIndex) %}
-
- {% set assignedRoom = bookingDto.travel.getRoomById(form.vars.data.participant.assignedRoomId) %}
- {% set roomLabel = assignedRoom ? assignedRoom.label : 'Kein Zimmer zugewiesen' %}
- {{ macros.field_or_static(form, 'assignedRoomId', 'Zimmer', roomLabel, bookingDto, participantIndex, {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content',
- 'hx-swap': 'innerHTML'
- }
- }) }}
- {% if form.remarksRoom is defined %}
- {{ form_row(form.remarksRoom) }}
- {% endif %}
-
- {% endif %}
-
- {# Eligibility checks #}
- {% set participantData = form.vars.data.participant %}
- {% set hasDateOfBirth = participantData and participantData.dateOfBirth %}
- {% set isEligible = hasDateOfBirth and is_participant_eligible(bookingDto, participantIndex) %}
-
- {% if not hasDateOfBirth %}
-
-
-
-
- Leistungen sind erst nach Angabe des Geburtsdatums buchbar
-
-
-
- {% elseif not isEligible %}
-
-
-
-
- Buchung wegen des Alters von Teilnehmer:in {{ participantIndex + 1 }} nicht möglich
-
-
-
- {% endif %}
-
- {# Service selection #}
- {% if isEligible %}
-
- {{ macros.service_field(form, 'skiPass', 'Skipass', {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
-
- {{ macros.service_field(form, 'courses', 'Kurse', {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
-
- {{ macros.service_field(form, 'additionalServices', 'Zusatzleistungen', {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
-
- {{ macros.service_field(form, 'board', 'Verpflegung', {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
-
-
- {{ macros.service_field(form, 'rentals', 'Leihmaterial', {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }, 'Bitte zuerst den Skipass auswählen') }}
-
- {{ macros.checkbox_field(form, 'rentalInsurance', null, {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }, null) }}
-
-
- {% if form.bodyDimensions is defined %}
-
- {{ form_row(form.bodyDimensions.height) }}
- {{ form_row(form.bodyDimensions.shoeSize) }}
- {{ form_row(form.bodyDimensions.weight) }}
-
- {% else %}
-
{# empty slot to maintain grid layout #}
- {% endif %}
-
-
- {# Insurance display for edit mode (read-only) #}
- {% if bookingDto.mode == constant('App\\Form\\Model\\BookingDto::MODE_EDIT') and form.vars.data.participant.insurance %}
-
-
- {# Insurance field OR assigned insurance display for dependent participants (create mode) #}
- {% else %}
- {% set showBulkInsurance = participantIndex > 0 and bookingDto.participants[0].bulkInsuranceBooking %}
-
- {% if showBulkInsurance %}
-
- {% else %}
-
- {% endif %}
- {% endif %}
-
-
-
-
- {# Transportation Services Section #}
-
-
Anreise
-
- {% if form.transportationOutbound is defined %}
- {{ form_row(form.transportationOutbound, {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
- {% endif %}
- {% if form.transportationInbound is defined %}
- {{ form_row(form.transportationInbound, {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
- {% endif %}
- {% if form.pickup is defined %}
-
- {{ form_row(form.pickup, {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
-
- {% endif %}
- {% if form.parking is defined %}
-
- {{ form_row(form.parking, {
- 'attr': {
- 'hx-trigger': 'change',
- 'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
- 'hx-target': '#main-content', 'hx-swap': 'innerHTML'
- }
- }) }}
-
- {% endif %}
- {% if form.licensePlate is defined %}
-
- {{ form_row(form.licensePlate) }}
-
- {% endif %}
-
-
- {% endif %}
-
- {# Voucher fields - available for all participants regardless of eligibility #}
- {% if form.purchaseVoucherCode is defined or form.promoVoucherCode is defined %}
-
-
Gutscheine
-
- {% if form.purchaseVoucherCode is defined %}
- {{ form_row(form.purchaseVoucherCode) }}
- {% endif %}
- {% if form.promoVoucherCode is defined %}
- {{ form_row(form.promoVoucherCode) }}
- {% endif %}
-
-
- {% endif %}
+ {{ macros.field_or_static(form, 'email', 'E-Mail', form.vars.data.participant.email, bookingDto, participantIndex) }}
+ {{ macros.field_or_static(form, 'mobile', 'Telefon (mobil)', form.vars.data.participant.mobile, bookingDto, participantIndex) }}