Files
myep/templates/groups/booking/step_2.html.twig
T

236 lines
15 KiB
Twig

{% extends 'layout_booking.html.twig' %}
{% block title %}Schritt 2: Personen & Leistungen{% endblock %}
{% block background %}bg-outer bg-outer--summer{% endblock %}
{% block content %}
{% form_theme form 'booking/_form_theme.html.twig' %}
{{ form_start(form, {
'attr': {
'class': 'flex-1 flex flex-col min-h-0',
}
}) }}
{# Pagination - mobile only (above summary) #}
<div class="lg:hidden">
{% include 'groups/booking/_pagination.html.twig' with { 'current_step': 2 } %}
</div>
<div class="flex-1 flex flex-col lg:grid lg:grid-cols-5 min-h-0 relative">
{# Sidebar summary #}
{% block accommodation_summary %}
<div id="accommodation-summary"
class="order-1 lg:order-2 lg:flex-1 lg:min-h-0 lg:col-span-2"
{{ stimulus_controller('toggle', { 'open': false }, { 'closed': 'hidden', 'open': 'absolute inset-0 z-20', 'iconOpen': 'rotate-180' }) }}
{% if htmx_oob_swap is defined and htmx_oob_swap %}hx-swap-oob="true"{% endif %}>
{% include 'groups/booking/_summary.html.twig' with { 'dto': dto, 'ctx': ctx } %}
</div>
{% endblock %}
{# Main form #}
{% block accommodation_form %}
<div id="accommodation-form"
class="flex-1 order-2 lg:order-1 lg:col-span-3 bg-white flex flex-col min-h-0"
{% if htmx_oob_swap is defined and htmx_oob_swap %}hx-swap-oob="true"{% endif %}>
{% include '_partials/_flashes.html.twig' %}
{# Pagination - desktop only (fixed above scrollable content) #}
<div class="hidden lg:block shrink-0">
{% include 'groups/booking/_pagination.html.twig' with { 'current_step': 2 } %}
</div>
<div id="participant-form"
class="flex-1 overflow-y-auto px-4 lg:px-8 py-8"
hx-post="{{ path('app_groups_booking_step_2_refresh') }}"
hx-trigger="change delay:300ms"
hx-swap="none">
{# Validation errors #}
{% from '_partials/_validation_errors.html.twig' import validation_alert %}
{{ validation_alert(form) }}
{% if dto.isInquiry %}
{% include '_partials/_alert.html.twig' with {
level: 'warning',
title: 'Diese Buchung wird als unverbindliche Anfrage behandelt',
messages: dto.inquiryReasons
} %}
{% endif %}
{# Pax counts #}
<h2 class="pb-4">
Personenanzahl und gewünschte Leistungen
</h2>
<div class="grid lg:grid-cols-3 lg:gap-x-8">
{{ form_row(form.paxCount) }}
{{ form_row(form.minorsCount) }}
{{ form_row(form.childrenCount) }}
</div>
{# Board services — rendered manually so price is formatted in Twig #}
{% do form.selectedBoardServiceId.setRendered %}
{% if ctx.boardServices is not empty %}
<div class="pb-4">
<fieldset class="border border-primary-bg">
<legend class="w-full bg-primary-bg p-2 font-semibold uppercase">
Verpflegungsleistungen
</legend>
<table class="w-full table-fixed border-collapse">
<tr>
<td class="border border-primary-bg p-2 align-top">
<label for="board_service_none" class="cursor-pointer">Selbstversorgung</label>
</td>
<td class="border border-primary-bg p-2 align-top w-32 text-right"></td>
<td class="border border-primary-bg p-2 align-top w-12 text-center">
<input type="radio"
id="board_service_none"
name="{{ form.selectedBoardServiceId.vars.full_name }}"
value=""
{% if dto.selectedBoardServiceId is null %}checked{% endif %}
class="form-radio">
</td>
</tr>
{% for service in ctx.boardServices %}
<tr>
<td class="border border-primary-bg p-2 align-top">
<label for="board_service_{{ service.id }}" class="cursor-pointer">{{ service.label }}</label>
{% if service.description %}
<div {{ stimulus_controller('tooltip') }}>
<button type="button" data-tooltip-target="trigger" class="text-sm text-primary-light">Details</button>
<template data-tooltip-target="template">
<div class="text-sm">{{ service.description|nl2br }}</div>
</template>
</div>
{% endif %}
</td>
<td class="border border-primary-bg p-2 align-top w-32 text-right">
<div>{% if service.price == 0 %}inkl.{% else %}{{ (service.price / 100)|format_currency(ctx.accommodation.currency) }}{% endif %}</div>
<div class="text-xs text-gray-500">pro Person und Nacht</div>
</td>
<td class="border border-primary-bg p-2 align-top w-12 text-center">
<input type="radio"
id="board_service_{{ service.id }}"
name="{{ form.selectedBoardServiceId.vars.full_name }}"
value="{{ service.id }}"
{% if dto.selectedBoardServiceId == service.id %}checked{% endif %}
class="form-radio">
</td>
</tr>
{% endfor %}
</table>
</fieldset>
</div>
{% endif %}
{# Additional services — rendered manually to support checkbox/radio mix #}
{% do form.selectedAdditionalServiceIds.setRendered %}
{% set selectedAdditionalServiceBaseName = form.selectedAdditionalServiceIds.vars.full_name|replace({'[]': ''}) %}
{% if ctx.ungroupedAdditionalServices is not empty or ctx.groupedAdditionalServices is not empty %}
{# Ungrouped → checkboxes #}
{% if ctx.ungroupedAdditionalServices is not empty %}
<div class="pb-4">
<fieldset class="border border-primary-bg">
<legend class="w-full bg-primary-bg p-2 font-semibold uppercase">
Optionale Zusatzleistungen
</legend>
<table class="w-full table-fixed border-collapse">
{% for service in ctx.ungroupedAdditionalServices %}
<tr>
<td class="border border-primary-bg p-2 align-top">
<label for="add_service_{{ service.id }}" class="cursor-pointer">{{ service.label }}</label>
{% if service.description %}
<div {{ stimulus_controller('tooltip') }}>
<button type="button" data-tooltip-target="trigger" class="text-sm text-primary-light">Details</button>
<template data-tooltip-target="template">
<div class="text-sm">{{ service.description|nl2br }}</div>
</template>
</div>
{% endif %}
</td>
<td class="border border-primary-bg p-2 align-top w-32 text-right">
<div>{% if service.price == 0 %}inkl.{% else %}{{ (service.price / 100)|format_currency(ctx.accommodation.currency) }}{% endif %}</div>
<div class="text-xs text-gray-500">{{ service.type.label | trans }}</div>
</td>
<td class="border border-primary-bg p-2 align-top w-12 text-center">
<input type="checkbox"
id="add_service_{{ service.id }}"
name="{{ form.selectedAdditionalServiceIds.vars.full_name }}"
value="{{ service.id }}"
{% if service.id in dto.selectedAdditionalServiceIds %}checked{% endif %}
class="form-checkbox">
</td>
</tr>
{% endfor %}
</table>
</fieldset>
</div>
{% endif %}
{# Grouped → radio buttons per group, one fieldset per group #}
{% for groupName, services in ctx.groupedAdditionalServices %}
<div class="pb-4">
<fieldset class="border border-primary-bg">
<legend class="w-full bg-primary-bg p-2 font-semibold uppercase">{{ groupName }}</legend>
<table class="w-full table-fixed border-collapse">
{% for service in services %}
<tr>
<td class="border border-primary-bg p-2 align-top">
<label for="add_service_{{ service.id }}" class="cursor-pointer">{{ service.label }}</label>
{% if service.description %}
<div {{ stimulus_controller('tooltip') }}>
<button type="button" data-tooltip-target="trigger" class="text-sm text-primary-light">Details</button>
<template data-tooltip-target="template">
<div class="text-sm">{{ service.description|nl2br }}</div>
</template>
</div>
{% endif %}
</td>
<td class="border border-primary-bg p-2 align-top w-32 text-right">
<div>{% if service.price == 0 %}inkl.{% else %}{{ (service.price / 100)|format_currency(ctx.accommodation.currency) }}{% endif %}</div>
<div class="text-xs text-gray-500">{{ service.type.label | trans }}</div>
</td>
<td class="border border-primary-bg p-2 align-top w-12 text-center">
<input type="radio"
id="add_service_{{ service.id }}"
name="{{ selectedAdditionalServiceBaseName }}[{{ groupName|e('html_attr') }}]"
value="{{ service.id }}"
{% if service.id in dto.selectedAdditionalServiceIds %}checked{% endif %}
class="form-radio">
</td>
</tr>
{% endfor %}
</table>
</fieldset>
</div>
{% endfor %}
{% endif %}
</div>
</div>
{% endblock %}
</div>
<div class="shrink-0 bg-primary-dark px-4 lg:px-8 py-2 lg:py-4 z-20">
<div class="flex items-center justify-between">
<a href="{{ path('app_groups_booking_step_1') }}" class="button button--secondary">
Zurück
</a>
<button type="submit" class="button button--primary">
Weiter zu Schritt 3
</button>
</div>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}