wip: continue implementation

This commit is contained in:
Björn Fromme
2024-11-27 11:31:48 +01:00
parent b5d52b0053
commit 84ab6446ea
81 changed files with 9127 additions and 898 deletions
+12
View File
@@ -0,0 +1,12 @@
{% apply spaceless %}
{% for message in messages %}
{% if message is iterable %}
{% set message = message.id | trans(message.parameters | default({}), message.domain | default(null), message.locale | default(null)) | raw %}
{% else %}
{% set message = message | trans | raw %}
{% endif %}
<div>
{{ message }}
</div>
{% endfor %}
{% endapply %}
+9
View File
@@ -0,0 +1,9 @@
{% if app.session.flashBag.peek('error')|length > 0 %}
{% include '_partials/_alert.html.twig' with { level: 'warning', messages: app.flashes('error') } %}
{% endif %}
{% if app.session.flashBag.peek('success')|length > 0 %}
{% include '_partials/_alert.html.twig' with { level: 'success', messages: app.flashes('success') } %}
{% endif %}
{% if app.session.flashBag.peek('info')|length > 0 %}
{% include '_partials/_alert.html.twig' with { level: 'info', messages: app.flashes('info') } %}
{% endif %}
+37
View File
@@ -0,0 +1,37 @@
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
<svg class="{{ class }}" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">
<g fill="none" fill-rule="evenodd" stroke-width="2">
<circle cx="22" cy="22" r="1">
<animate attributeName="r"
begin="0s" dur="1.8s"
values="1; 20"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.165, 0.84, 0.44, 1"
repeatCount="indefinite" />
<animate attributeName="stroke-opacity"
begin="0s" dur="1.8s"
values="1; 0"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.3, 0.61, 0.355, 1"
repeatCount="indefinite" />
</circle>
<circle cx="22" cy="22" r="1">
<animate attributeName="r"
begin="-0.9s" dur="1.8s"
values="1; 20"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.165, 0.84, 0.44, 1"
repeatCount="indefinite" />
<animate attributeName="stroke-opacity"
begin="-0.9s" dur="1.8s"
values="1; 0"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.3, 0.61, 0.355, 1"
repeatCount="indefinite" />
</circle>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+6 -8
View File
@@ -2,18 +2,16 @@
<html lang="de">
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
<title>{% block title %}MyE&P.next{% endblock %}</title>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</head>
<body>
<div class="container">
{% block body %}{% endblock %}
</div>
<body class="bg-white text-gray-700 font-sans antialiased text-sm">
{% block body %}{% endblock %}
{% include '_partials/_flashes.html.twig' %}
</body>
</html>
+128 -163
View File
@@ -10,42 +10,39 @@
{{ form_errors(form) }}
</article>
{% endif %}
<article>
<header>
<strong>Reisedaten</strong>
</header>
<table>
<tbody>
<tr>
<th>
<strong>Reise</strong>
</th>
<td>
<div class="flex flex-col space-y-8 pb-4">
<div class="p-8 border border-gray-300 rounded-md"
{{ stimulus_controller('availabilities')|stimulus_controller('toggle', { 'open': true }, { 'closed': 'hidden' }) }}>
<div role="button" class="flex items-center justify-between" {{ stimulus_action('toggle', 'toggle', 'click') }}>
<span class="block text-3xl font-semibold">Reisedaten</span>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" {{ stimulus_target('toggle', 'icon') }}>
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-4 pt-4" {{ stimulus_target('toggle', 'toggle') }}>
<div>
<h3 class="text-lg font-semibold">
Destination
</h3>
{{ bookingData.travel }}
</td>
</tr>
<tr>
<th>
<strong>Reiseedatum</strong>
</th>
<td>
</div>
<div>
<h3 class="text-lg font-semibold">
Reisedatum
</h3>
{{ bookingData.travelDate|date('d.m.Y') }}
</td>
</tr>
<tr>
<th>
<strong>Buchungsdatum</strong>
</th>
<td>
</div>
<div>
<h3 class="text-lg font-semibold">
Buchungsdatum
</h3>
{{ bookingData.bookingDate|date('d.m.Y') }}
</td>
</tr>
<tr>
<th>
<strong>Inklusivleistungen</strong>
</th>
<td>
<ul>
</div>
<div>
<h3 class="text-lg font-semibold">
Inklusivleistungen
</h3>
<ul class="list-disc pl-4">
{% for selectionGroup in travelData.includedServices %}
{% for service in selectionGroup.selections %}
<li>
@@ -54,136 +51,104 @@
{% endfor %}
{% endfor %}
</ul>
</td>
</tr>
</tbody>
</table>
</article>
{% for child in form.participants %}
{% set participant = child.vars.data %}
<details{% if not child.vars.valid %} open{% endif %}>
<summary role="button" class="outline">
Teilnehmer {{ participant.index }}
</summary>
<article>
<header>
<strong>Persönliche Daten</strong>
</header>
<fieldset class="grid">
{% if travelData.participantDataMutable %}
{{ form_row(child.firstName) }}
{{ form_row(child.lastName) }}
{{ form_row(child.gender) }}
{% else %}
Teilnehmerdaten nicht mehr änderbar
{% endif %}
</fieldset>
<fieldset class="grid">
{% if travelData.participantDataMutable %}
{{ form_row(child.dateOfBirth) }}
{{ form_row(child.nationality) }}
{% else %}
Teilnehmerdaten nicht mehr änderbar
{% endif %}
</fieldset>
<fieldset class="grid">
{% if travelData.participantDataMutable %}
{{ form_row(child.email) }}
{{ form_row(child.mobile) }}
{% else %}
Teilnehmerdaten nicht mehr änderbar
{% endif %}
</fieldset>
<fieldset class="grid">
{% if travelData.participantDataMutable %}
{{ form_row(child.height) }}
{{ form_row(child.shoeSize) }}
{{ form_row(child.weight) }}
{% else %}
Teilnehmerdaten nicht mehr änderbar
{% endif %}
</fieldset>
</article>
<article>
<header>
<strong>Unterkunft</strong>
</header>
{% set room = bookingData.roomForParticipant(participant.index) %}
{{ room.label }} ({{ room.individualPrice[participant.index]|format_currency('EUR') }})
</article>
<article>
<header>
<strong>Leistungen</strong>
</header>
<fieldset class="grid">
{% if travelData.additionalServicesMutable %}
{% if child.courses is defined %}
{{ form_row(child.courses) }}
{% endif %}
{% if child.skiPass is defined %}
{{ form_row(child.skiPass) }}
{% endif %}
{% else %}
Leistungen nicht mehr änderbar
{% endif %}
</fieldset>
<fieldset class="grid">
{% if travelData.additionalServicesMutable %}
{% if child.additionalServices is defined %}
{{ form_row(child.additionalServices) }}
{% endif %}
{% if child.board is defined %}
{{ form_row(child.board) }}
{% endif %}
{% else %}
Leistungen nicht mehr änderbar
{% endif %}
</fieldset>
<fieldset class="grid">
{% if travelData.additionalServicesMutable %}
{% if child.rentals is defined %}
{{ form_row(child.rentals) }}
{% endif %}
{% else %}
Leistungen nicht mehr änderbar
{% endif %}
</fieldset>
<fieldset class="grid">
{% if travelData.additionalServicesMutable %}
{{ form_row(child.transportationServiceTo) }}
{{ form_row(child.transportationServiceFro) }}
{% else %}
Beförderungsleistung nicht mehr änderbar
{% endif %}
{% if child.pickup is defined %}
{% if travelData.pickupsMutable %}
{{ form_row(child.pickup) }}
{% else %}
Zustieg nicht mehr änderbar
{% endif %}
{% endif %}
</fieldset>
</article>
<article>
<header>
<strong>Gesamtpreis</strong>
</header>
{{ bookingData.priceForParticipant(participant.index)|format_currency('EUR') }}
</article>
</details>
{% endfor %}
{{ form_rest(form) }}
<button type="submit">
Aktualisieren
</button>
{{ form_end(form) }}
<p>
<button type="button"
hx-get="{{ path('app_bookings') }}"
hx-target="#app"
hx-swap="innerHTML show:top"
hx-indicator="#loading-indicator">
</div>
</div>
</div>
{% for child in form.participants %}
{% set participant = child.vars.data %}
<div class="{{ html_classes('p-8 border rounded-md', { 'border-gray-300': child.vars.valid, 'border-red-500': not child.vars.valid }) }}" {{ stimulus_controller('availabilities')|stimulus_controller('toggle', {'open': child.vars.valid == false}, { 'closed': 'hidden' }) }}>
<div role="button" class="flex items-center justify-between" {{ stimulus_action('toggle', 'toggle', 'click') }}>
<div class="text-xl font-semibold">Teilnehmer:in {{ participant.index }}: {{ participant.firstName }} {{ participant.lastName }}</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" {{ stimulus_target('toggle', 'icon') }}>
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
</div>
<div class="hidden" {{ stimulus_target('toggle', 'toggle') }}>
<div class="flex flex-col space-y-4 pt-4">
<div>
<h3 class="text-xl font-semibold pb-2">
Persönliche Daten
</h3>
<fieldset class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-4 pb-4">
{{ form_row(child.firstName) }}
{{ form_row(child.lastName) }}
{{ form_row(child.gender) }}
{{ form_row(child.dateOfBirth) }}
{{ form_row(child.nationality) }}
</fieldset>
<fieldset class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-4 pb-4">
{{ form_row(child.email) }}
{{ form_row(child.mobile) }}
</fieldset>
<fieldset class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-4">
{{ form_row(child.height) }}
{{ form_row(child.shoeSize) }}
{{ form_row(child.weight) }}
</fieldset>
</div>
<div>
<h3 class="text-xl font-semibold pb-2">
Unterkunft
</h3>
{% set room = bookingData.roomForParticipant(participant.index) %}
{{ room.label }} ({{ room.individualPrice[participant.index]|format_currency('EUR') }})
</div>
<div>
<h3 class="text-xl font-semibold pb-2">
Leistungen
</h3>
<fieldset class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-4">
{% if child.courses is defined %}
{{ form_row(child.courses) }}
{% endif %}
{% if child.skiPass is defined %}
{{ form_row(child.skiPass) }}
{% endif %}
{% if child.additionalServices is defined %}
{{ form_row(child.additionalServices) }}
{% endif %}
{% if child.board is defined %}
{{ form_row(child.board) }}
{% endif %}
{% if child.rentals is defined %}
{{ form_row(child.rentals) }}
{% endif %}
</fieldset>
</div>
<div>
<h3 class="text-xl font-semibold pb-2">
Hin-/Rückreise
</h3>
<fieldset class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-4" {{ stimulus_controller('select-toggle', { 'show': ['BUS'] }, { 'hidden': 'hidden' }) }}>
{{ form_row(child.transportationServiceTo) }}
{{ form_row(child.transportationServiceFro) }}
{% if child.pickup is defined %}
<div {{ stimulus_target('select-toggle', 'container') }}>
{{ form_row(child.pickup) }}
</div>
{% endif %}
</fieldset>
</div>
<div>
<h3 class="text-xl font-semibold pb-2">
Gesamtpreis
</h3>
<span class="text-2xl font-medium">{{ bookingData.priceForParticipant(participant.index)|format_currency('EUR') }}</span>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="flex justify-between">
<a href="{{ path('app_bookings') }}"
class="btn">
zurück
</a>
<button type="submit" class="btn btn--secondary">
Aktualisieren
</button>
</p>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}
+65 -61
View File
@@ -1,71 +1,75 @@
{% extends 'layout.html.twig' %}
{% block content %}
<div class="overflow-auto">
<table>
<thead>
<tr>
<th scope="col">
Buchungsdatum/<br>Reisedatum
</th>
<th scope="col">
Reise
</th>
<th scope="col">
Vorgangsnr.
</th>
<th scope="col">
Preis/<br>offen
</th>
<th scope="col">
Status
</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for booking in bookings %}
<tr>
<td>
{{ booking.bookingDate | date('d.m.Y') }}/<br>{{ booking.travelDate | date('d.m.Y') }}
</td>
<td>
{{ booking.travel }}
</td>
<td>
{{ booking.bookingNumber }}
</td>
<td>
{{ booking.price|format_currency('EUR') }}/<br>{{ booking.balance ? booking.balance|format_currency('EUR') : '-' }}
</td>
<td>
{{ booking.status }}
</td>
<td>
{% if booking.editable %}
<button type="button"
hx-get="{{ path('app_booking_edit', { 'id': booking.id }) }}"
hx-target="#app"
hx-indicator="#loading-indicator">
bearbeiten
</button>
<h2 class="text-2xl font-semibold pb-4">
Meine Buchungen
</h2>
<div class="space-y-8">
{% for booking in bookings %}
<div class="p-4 border border-gray-300 rounded-md overflow-hidden" {{ stimulus_controller('toggle', { 'open': false }, { 'closed': 'hidden' }) }}>
<div role="button" class="flex items-center justify-between py-2" {{ stimulus_action('toggle', 'toggle', 'click') }}>
<div class="text-lg md:text-xl font-semibold">
{% if booking.travelData %}
{{ booking.travel }}, {{ booking.travelData.dateFrom | date('d.m.Y') }} - {{ booking.travelData.dateTo | date('d.m.Y') }}
{% else %}
{{ booking.travel }}, {{ booking.travelDate | date('d.m.Y') }}
{% endif %}
<a href="{{ path('app_booking_confirmation', { 'id': booking.id }) }}" target="_blank">
</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" {{ stimulus_target('toggle', 'icon') }}>
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
</div>
<div class="flex flex-col space-y-4 sm:flex-row sm:items-start sm:space-x-2" {{ stimulus_target('toggle', 'toggle') }}>
<div class="flex-1 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
<div>
<div class="font-semibold pb-2">
Buchungsdatum
</div>
{{ booking.bookingDate | date('d.m.Y') }}
</div>
<div>
<div class="font-semibold pb-2">
Buchungsnummer
</div>
{{ booking.bookingNumber }}
</div>
<div>
<div class="font-semibold pb-2">
Reisepreis
</div>
{{ booking.price|format_currency('EUR') }}/<br>{{ booking.balance ? booking.balance|format_currency('EUR') : '-' }}
</div>
<div>
<div class="font-semibold pb-2">
Status
</div>
{{ booking.status }}
</div>
</div>
<div class="flex sm:flex-col space-x-2 sm:space-x-0 sm:space-y-1">
{% if booking.editable %}
<a href="{{ path('app_booking_edit', { 'id': booking.id }) }}"
class="btn btn--small btn--secondary">
bearbeiten
</a>
{% endif %}
<a href="{{ path('app_booking_confirmation', { 'id': booking.id }) }}"
class="btn btn--small"
target="_blank">
Bestätigung
</a>
<a href="{{ path('app_booking_documents', { 'id': booking.id }) }}" target="_blank">
<a href="{{ path('app_booking_documents', { 'id': booking.id }) }}"
class="btn btn--small"
target="_blank">
Reisedokumente
</a>
</td>
</tr>
{% else %}
<tr>
<td>
Keine Daten
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% else %}
<div>
Keine Daten
</div>
{% endfor %}
</div>
{% endblock %}
+134 -41
View File
@@ -1,62 +1,155 @@
{% use 'form_div_layout.html.twig' %}
{%- block form_widget_simple -%}
{%- set type = type|default('text') -%}
{%- if type == 'range' or type == 'color' -%}
{# Attribute "required" is not supported #}
{%- set required = false -%}
{%- endif -%}
{%- if errors|length > 0 -%}
{% set attr = attr|merge({ 'aria-invalid': 'true', 'aria-describedby': 'error-' ~ id }) %}
{%- endif -%}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{%- endblock form_widget_simple -%}
{%- block form_row -%}
<fieldset{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
<legend>
<strong>
{{- label -}}
</strong>
</legend>
{{- form_widget(form) -}}
{%- set widget_attr = {} -%}
{%- if help is not empty -%}
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
{%- endif -%}
<div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
{{- form_label(form) -}}
{{- form_widget(form, widget_attr) -}}
{{- form_errors(form) -}}
{{- form_help(form) -}}
</fieldset>
</div>
{%- endblock form_row -%}
{%- block form_label -%}
{% set class = 'block font-semibold pb-2' %}
{% if errors|length %}
{% set class = class ~ ' text-red-500' %}
{% endif %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ class)|trim}) %}
{{ parent() }}
{%- endblock form_label -%}
{%- block form_errors -%}
{%- if errors|length > 0 -%}
<small id="error-{{ id }}">
<ul class="pb-2">
{%- for error in errors -%}
<div>{{ error.message }}</div>
<li class="text-red-500">{{ error.message }}</li>
{%- endfor -%}
</small>
</ul>
{%- endif -%}
{%- endblock form_errors -%}
{%- block choice_widget_expanded -%}
{%- for child in form %}
{{- form_widget(child) -}}
{% endfor -%}
{%- endblock choice_widget_expanded -%}
{%- block form_widget_simple -%}
{%- set type = type|default('text') -%}
{%- if type != 'hidden' -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset text-sm')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-gray-400 focus:ring-primary' }) -%}
{%- endif -%}
{%- if disabled is defined and disabled == true -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
{%- endif -%}
{%- endif -%}
{{ parent() }}
{%- if disabled is defined and disabled == true -%}
<input type="hidden" name="{{ form.vars.full_name }}" value="{{ form.vars.value }}">
{%- endif -%}
{%- endblock form_widget_simple -%}
{%- block textarea_widget -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset text-sm')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-gray-400 focus:ring-primary' }) -%}
{%- endif -%}
{%- if disabled is defined and disabled == true -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
{%- endif -%}
{{ parent() }}
{%- if disabled is defined and disabled == true -%}
<input type="hidden" name="{{ form.vars.full_name }}" value="{{ form.vars.value }}">
{%- endif -%}
{%- endblock textarea_widget -%}
{%- block checkbox_widget -%}
<label for="{{ id }}">
{{ parent() }}
{{ label|trans|raw }}
{%- if attr.disabled is defined and attr.disabled == true and attr.checked == true -%}
<input type="hidden" name="{{ form.vars.full_name }}" value="{{ form.vars.value }}">
{%- endif -%}
</label>
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' h-4 w-4 rounded text-primary')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-red-500 text-red-500 ring-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-gray-300 focus:ring-primary' }) -%}
{%- endif -%}
{%- if attr.disabled is defined and attr.disabled == true -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
{%- endif -%}
<input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{%- endblock checkbox_widget -%}
{%- block radio_widget -%}
<label for="{{ id }}">
{{ parent() }}
{{ label|trans|raw }}
</label>
{%- if attr.disabled is defined and attr.disabled == true and attr.checked == true -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' h-4 w-4 rounded-full text-primary')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-red-500 text-red-500 ring-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-gray-300 focus:ring-primary' }) -%}
{%- endif -%}
{%- if attr.disabled is defined and attr.disabled == true -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
{%- endif -%}
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{%- endblock radio_widget -%}
{% block checkbox_row %}
<div class="relative flex items-start">
<div class="flex h-6 items-center">
{{ form_widget(form) }}
</div>
<div class="{{ html_classes('ml-3 leading-6', { 'text-red-500': errors|length }) }}">
<label for="{{ form.vars.id }}">
{{ form.vars.label }}
</label>
{{- form_errors(form) -}}
</div>
</div>
{% endblock %}
{%- block choice_widget_collapsed -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset text-sm')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-gray-400 focus:ring-primary' }) -%}
{%- endif -%}
{%- if disabled is defined and disabled == true -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
{%- endif -%}
{{ parent() }}
{%- if disabled is defined and disabled == true -%}
<input type="hidden" name="{{ form.vars.full_name }}" value="{{ form.vars.value }}">
{%- endif -%}
{%- endblock radio_widget -%}
{%- endblock choice_widget_collapsed -%}
{%- block choice_widget_expanded -%}
{%- for child in form %}
<div class="relative flex items-start pb-2">
<div class="min-w-0 flex-1 text-sm leading-4">
<label for="{{ child.vars.id }}" class="select-none font-medium text-gray-900">
{{ child.vars.label }}
</label>
</div>
<div class="ml-3 flex h-4 items-center">
{{- form_widget(child) -}}
</div>
</div>
{% endfor -%}
{%- endblock choice_widget_expanded -%}
{%- block multiselect_widget -%}
<div class="relative" {{ stimulus_controller('multiselect', { 'placeholder': form.vars.empty_label }) }}>
<div {{ stimulus_action('multiselect', 'toggle', 'click')}}
role="button"
class="relative rounded-md border border-gray-300 flex items-start space-x-2 px-3">
<div {{ stimulus_target('multiselect', 'label') }} class="flex-1 min-h-8 py-1.5 text-gray-900 text-sm"></div>
{{ icon('dots', 'w-4 h-4 mt-2') }}
</div>
<div {{ stimulus_target('multiselect', 'dropdown')}} class="absolute z-10 top-full -mt-1.5 left-0 inset-x-0 max-h-48 overflow-y-scroll px-3 py-2 bg-white shadow-lg rounded-md rounded-t-none border border-gray-300 border-t-0 hidden">
{% for item in form.children %}
{{ form_row(item, { 'attr': { 'data-action': 'multiselect#update', 'data-multiselect-target': 'choice', 'data-label': item.vars.label } }) }}
{% endfor %}
</div>
</div>
{%- endblock multiselect_widget -%}
+7
View File
@@ -0,0 +1,7 @@
{% extends 'base.html.twig' %}
{% block body %}
<div hx-get="{{ path('app_login') }}"
hx-trigger="load"
hx-swap="outerHTML"></div>
{% endblock %}
+18 -55
View File
@@ -1,58 +1,21 @@
{% extends 'base.html.twig' %}
{% block body %}
<div id="app">
<div class="container py-8"
id="app"
hx-boost="true"
hx-indicator="#loading-indicator">
<div class="relative z-20 flex items-center justify-between pb-4">
<img class="h-8 w-auto" src="{{ asset('build/images/logo.svg') }}" alt="My E&amp;P Team">
{% if is_granted('ROLE_USER') %}
<nav>
<ul>
<li><strong>MyE&amp;P BETA</strong></li>
</ul>
<ul>
<li>
<a href="#"
class="contrast"
hx-get="{{ path('app_personal_data') }}"
hx-target="#app"
hx-swap="innerHTML"
hx-indicator="#loading-indicator">
Persönliche Daten
</a>
</li>
<li>
<a href="#"
class="contrast"
hx-get="{{ path('app_bookings') }}"
hx-target="#app"
hx-swap="innerHTML"
hx-indicator="#loading-indicator">
Buchungen
</a>
</li>
<li>
<a href="#"
class="contrast"
hx-get="{{ path('app_logout') }}"
hx-target="#app"
hx-swap="innerHTML"
hx-indicator="#loading-indicator">
Logout
</a>
</li>
</ul>
</nav>
{% endif %}
<div id="content">
{% for label, messages in app.flashes %}
{% for message in messages %}
<article>
{{ message }}
</article>
{% endfor %}
{% endfor %}
{% block content %}{% endblock %}
<div id="loading-indicator">
<progress />
<div class="hidden lg:block">
{{ knp_menu_render(knp_menu_get('main')) }}
</div>
</div>
{% endif %}
</div>
{% endblock %}
<div id="content">
{% include '_partials/_flashes.html.twig' %}
{% block content %}{% endblock %}
</div>
<div class="htmx-indicator fixed top-0 left-0 inset-0 z-10 bg-white/90 flex items-center justify-center"
id="loading-indicator">
{% include '_partials/_spinner.html.twig' with { 'class': 'w-8 h-8'} %}
</div>
</div>
+51 -23
View File
@@ -1,32 +1,60 @@
{% extends 'layout.html.twig' %}
{% block content %}
<h2>
Persönliche Daten
</h2>
{{ form_start(form) }}
<div class="grid">
<div class="grid md:grid-cols-2 gap-x-16 gap-y-4">
<div>
{{ form_row(form.gender) }}
{{ form_row(form.firstName) }}
{{ form_row(form.name) }}
{{ form_row(form.dateOfBirth) }}
<h2 class="text-2xl font-semibold pb-4">
Persönliche Daten
</h2>
{{ form_start(form) }}
<div class="grid grid-cols-2 gap-x-8 gap-y-4 pb-4">
{{ form_row(form.firstName) }}
{{ form_row(form.name) }}
{{ form_row(form.gender) }}
{{ form_row(form.dateOfBirth) }}
</div>
<h3 class="text-xl font-semibold pb-2">
Anschrift
</h3>
<div class="grid grid-cols-2 gap-x-8 gap-y-4 pb-4">
<div class="col-span-2">
{{ form_row(form.street) }}
</div>
{{ form_row(form.postCode) }}
{{ form_row(form.city) }}
{{ form_row(form.country) }}
</div>
<h3 class="text-xl font-semibold pb-2">
Kontakt
</h3>
<div class="grid grid-cols-2 gap-x-8 gap-y-4 pb-4">
<div class="col-span-2">
{{ form_row(form.email) }}
</div>
{{ form_row(form.phone) }}
{{ form_row(form.mobile) }}
</div>
<button type="submit" class="btn">
Speichern
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
<div>
{{ form_row(form.street) }}
{{ form_row(form.postCode) }}
{{ form_row(form.city) }}
{{ form_row(form.country) }}
</div>
<div>
{{ form_row(form.email) }}
{{ form_row(form.phone) }}
{{ form_row(form.mobile) }}
<h2 class="text-2xl font-semibold pb-4">
Newsletter
</h2>
<p class="pb-4">
Du bist aktuell {% if not personalData.communication.newsletter %}<strong>nicht</strong> {% endif%} zum Newsletter
angemeldet.
</p>
<button type="button" class="btn" hx-post="{{ path('app_personal_data_newsletter') }}" hx-target="#app">
{% if personalData.communication.newsletter %}
vom Newsletter abmelden
{% else %}
zum Newsletter anmelden
{% endif %}
</button>
</div>
</div>
{{ form_rest(form) }}
<button type="submit">
Speichern
</button>
{{ form_end(form) }}
{% endblock %}
+49 -48
View File
@@ -1,52 +1,53 @@
{% extends 'layout.html.twig' %}
{% block content %}
{% if error %}
<div class="flex items-center space-x-1 bg-red-500 text-white p-2 rounded-md mb-6">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" />
</svg>
<span class="flex-1 text-sm">{{ error.messageKey|trans(error.messageData, 'security') }}</span>
</div>
{% endif %}
<form hx-post="{{ path('app_login') }}"
hx-target="#app"
hx-swap="innerHTML"
hx-indicator="#loading-indicator">
<div class="mb-6">
<label for="username" class="block leading-6 text-gray-900">
E-Mail:
</label>
<input type="email"
id="username"
name="_username"
value="{{ last_username }}"
class="mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
required
autofocus
autocomplete="username">
</div>
<div class="mb-6">
<label for="password" class="block leading-6 text-gray-900">
Passwort:
</label>
<input type="password"
id="password"
name="_password"
class="mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
required
autocomplete="current-password">
</div>
<div class="flex items-start mb-6">
<label for="rememberme" class="flex h-6 items-center">
<input type="checkbox" id="rememberme" name="_remember_me" class="h-4 w-4 rounded text-primary">
<span class="block ml-3 leading-6">angemeldet bleiben</span>
</label>
</div>
<button type="submit" class="btn w-full">
Login
</button>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
</form>
<div class="p-8 max-w-screen-sm border border-gray-300 rounded-md mx-auto">
{% if error %}
<div class="flex items-center space-x-1 bg-red-500 text-white p-2 rounded-md mb-6">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" />
</svg>
<span class="flex-1 text-sm">{{ error.messageKey|trans(error.messageData, 'security') }}</span>
</div>
{% endif %}
<h2 class="text-2xl font-semibold pb-4">
Login MyE&amp;P
</h2>
<form action="{{ path('app_login') }}" method="post">
<div class="mb-6">
<label for="username" class="block leading-6 text-gray-900">
E-Mail:
</label>
<input type="email"
id="username"
name="_username"
value="{{ last_username }}"
class="mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
required
autofocus
autocomplete="username">
</div>
<div class="mb-6">
<label for="password" class="block leading-6 text-gray-900">
Passwort:
</label>
<input type="password"
id="password"
name="_password"
class="mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
required
autocomplete="current-password">
</div>
<div class="flex items-start mb-6">
<label for="rememberme" class="flex h-6 items-center">
<input type="checkbox" id="rememberme" name="_remember_me" class="h-4 w-4 rounded text-primary">
<span class="block ml-3 leading-6">angemeldet bleiben</span>
</label>
</div>
<button type="submit" class="btn w-full">
Login
</button>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
</form>
</div>
{% endblock %}