feat: authenticated booking

This commit is contained in:
Björn Fromme
2025-10-24 17:07:08 +02:00
parent 647a25a78f
commit b63804df88
13 changed files with 866 additions and 50 deletions
+93 -14
View File
@@ -46,24 +46,88 @@
<div id="participant-form" class="space-y-4">
{# Personal data section #}
<div class="grid grid-cols-2 gap-4">
{{ form_row(form.firstName) }}
{{ form_row(form.lastName) }}
{{ form_row(form.dateOfBirth, {
'attr': {
'hx-trigger': 'change',
'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
'hx-target': '#main-content',
'hx-swap': 'innerHTML'
}
}) }}
{{ form_row(form.gender) }}
{{ form_row(form.nationality) }}
{% if form.firstName is defined %}
{{ form_row(form.firstName) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">Vorname</label>
<div class="text-sm text-gray-600">{{ form.vars.data.participant.firstName }}</div>
</div>
{% endif %}
{% if form.lastName is defined %}
{{ form_row(form.lastName) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">Nachname</label>
<div class="text-sm text-gray-600">{{ form.vars.data.participant.lastName }}</div>
</div>
{% endif %}
{% if form.dateOfBirth is defined %}
{{ form_row(form.dateOfBirth, {
'attr': {
'hx-trigger': 'change',
'hx-post': path(refreshRouteName, refreshRouteParams|default({index: participantIndex})),
'hx-target': '#main-content',
'hx-swap': 'innerHTML'
}
}) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">Geburtsdatum</label>
<div class="text-sm text-gray-600">{{ form.vars.data.participant.dateOfBirth ? form.vars.data.participant.dateOfBirth|date('d.m.Y') : '-' }}</div>
</div>
{% endif %}
{% if form.gender is defined %}
{{ form_row(form.gender) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">Geschlecht</label>
<div class="text-sm text-gray-600">
{% if form.vars.data.participant.gender == 'M' %}
männlich
{% elseif form.vars.data.participant.gender == 'W' %}
weiblich
{% elseif form.vars.data.participant.gender == 'D' %}
divers
{% else %}
-
{% endif %}
</div>
</div>
{% endif %}
{% if form.nationality is defined %}
{{ form_row(form.nationality) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">Nationalität</label>
<div class="text-sm text-gray-600">{{ form.vars.data.participant.nationality ?: '-' }}</div>
</div>
{% endif %}
</div>
{# Contact information #}
<div class="grid grid-cols-2 gap-4">
{{ form_row(form.email) }}
{{ form_row(form.mobile) }}
{% if form.email is defined %}
{{ form_row(form.email) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">E-Mail</label>
<div class="text-sm text-gray-600">{{ form.vars.data.participant.email }}</div>
</div>
{% endif %}
{% if form.mobile is defined %}
{{ form_row(form.mobile) }}
{% else %}
<div>
<label class="font-semibold mb-1 block">Telefon (mobil)</label>
<div class="text-sm text-gray-600">{{ form.vars.data.participant.mobile ?: '-' }}</div>
</div>
{% endif %}
</div>
{# Address #}
@@ -74,6 +138,21 @@
{{ form_row(form.address.city) }}
{{ form_row(form.address.country) }}
</div>
{% else %}
<div>
<label class="font-semibold mb-1 block">Adresse</label>
{% if form.vars.data.participant.address %}
<div class="text-sm text-gray-600">
{% if form.vars.data.participant.address.street %}{{ form.vars.data.participant.address.street }}<br>{% endif %}
{% if form.vars.data.participant.address.postCode or form.vars.data.participant.address.city %}
{{ form.vars.data.participant.address.postCode }} {{ form.vars.data.participant.address.city }}<br>
{% endif %}
{% if form.vars.data.participant.address.country %}{{ form.vars.data.participant.address.country }}{% endif %}
</div>
{% else %}
<div class="text-sm text-gray-600">-</div>
{% endif %}
</div>
{% endif %}
{# Room assignment #}
@@ -0,0 +1,103 @@
{% extends 'layout.html.twig' %}
{% block content %}
{% include '_partials/_flashes.html.twig' %}
<h1 class="mb-4">
Neue Buchung
</h1>
<div class="bg-blue-50 border border-blue-200 rounded-lg p-6 mb-6">
<h2 class="text-blue-900 font-semibold text-lg mb-3">
Optional: Anmelden für schnelleres Buchen
</h2>
<p class="text-blue-800 mb-2">
Melde dich an, um deine persönlichen Daten automatisch in die Buchung zu übernehmen.
Dies ist <strong>vollständig optional</strong> du kannst auch ohne Anmeldung als Gast fortfahren.
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
{# Login Form #}
<div>
<h3 class="mb-4 font-semibold text-lg">
Mit bestehendem Account anmelden
</h3>
{% if error %}
{% include '_partials/_alert.html.twig' with { 'level': 'error', messages: [ error.messageKey|trans(error.messageData, 'security') ] } %}
{% endif %}
<form action="{{ path('app_login') }}" method="post" {{ stimulus_action('loading', 'toggle') }}>
<div class="mb-4">
<label for="username" class="mb-1 font-semibold">
E-Mail:
</label>
<input type="email"
id="username"
name="_username"
value="{{ last_username }}"
class="form-field"
required
autocomplete="username">
</div>
<div class="mb-4">
<label for="password" class="mb-1 font-semibold">
Passwort:
</label>
<input type="password"
id="password"
name="_password"
class="form-field"
required
autocomplete="current-password">
</div>
<div class="mb-4">
<label class="flex items-center">
<input type="checkbox" name="_remember_me" class="mr-2">
<span class="text-sm">Angemeldet bleiben</span>
</label>
</div>
<div class="flex flex-col space-y-2">
<button type="submit" class="button bg-button">
Anmelden und fortfahren
</button>
<a href="{{ path('app_reset_password') }}"
class="text-sm text-center text-blue-600 hover:underline">
Passwort vergessen?
</a>
</div>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
</form>
</div>
{# Continue as Guest #}
<div>
<h3 class="mb-4 font-semibold text-lg">
Als Gast fortfahren
</h3>
<p class="mb-4 text-gray-700">
Du kannst auch ohne Anmeldung buchen. Deine persönlichen Daten gibst du dann im nächsten Schritt ein.
</p>
<a href="{{ path('app_booking_create_step_1') }}" class="button bg-button bg-button--secondary w-full block text-center">
Als Gast fortfahren
</a>
<div class="mt-6 p-4 bg-gray-50 border border-gray-200 rounded">
<h4 class="font-semibold mb-2 text-sm">
Noch kein Account?
</h4>
<p class="text-sm text-gray-700">
Nach Abschluss deiner Buchung wird automatisch ein Account für dich erstellt.
Du erhältst dann Zugangsdaten per E-Mail und kannst deine Buchungen jederzeit verwalten.
</p>
</div>
</div>
</div>
{% endblock %}
+19 -3
View File
@@ -16,8 +16,24 @@
</p>
</div>
<a href="https://www.ep-reisen.de" class="button bg-button bg-button--primary">
Zurück zur Startseite
</a>
{% if app.user %}
{# Authenticated user - show account-related actions #}
<div class="space-y-4">
<a href="{{ path('app_personal_data') }}" class="button bg-button bg-button--primary inline-block">
Zu meinen persönlichen Daten
</a>
<a href="{{ path('app_bookings') }}" class="button bg-button bg-button--secondary inline-block ml-2">
Meine Buchungen anzeigen
</a>
<a href="{{ path('app_logout') }}" class="button bg-button bg-button--outline inline-block ml-2">
Abmelden
</a>
</div>
{% else %}
{# Guest user - show simple homepage link #}
<a href="https://www.ep-reisen.de" class="button bg-button bg-button--primary">
Zurück zur Startseite
</a>
{% endif %}
</div>
{% endblock %}