feat: implement hx-boost for reliable loading indication

This commit is contained in:
Björn Fromme
2026-03-16 11:59:12 +01:00
parent 602fb31f27
commit 1e107c68b4
32 changed files with 163 additions and 271 deletions
+19 -12
View File
@@ -32,9 +32,9 @@
</h1>
{% if isDirty %}
<button type="button"
hx-post="{{ path('app_booking_edit_reload', {id: bookingData.id}) }}"
hx-confirm="Alle nicht gespeicherten Änderungen gehen verloren. Fortfahren?"
{{ stimulus_action('loading', 'show') }}
hx-get="{{ path('app_booking_edit_reload', {id: bookingData.id}) }}"
hx-target="body"
hx-swap="beforeend"
class="button button--small button--secondary">
Änderungen verwerfen
</button>
@@ -83,19 +83,26 @@
{# Fixed footer #}
<div class="shrink-0 bg-primary-dark px-4 lg:px-8 py-2 lg:py-4 z-20">
<div class="flex justify-between">
<button type="button"
hx-post="{{ path('app_booking_edit_cancel', {id: bookingData.id}) }}"
{{ stimulus_action('loading', 'show') }}
class="inline-flex items-center justify-center bg-gray-200 rounded-md w-10 h-10">
<svg class="w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="200" y1="56" x2="56" y2="200" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="200" y1="200" x2="56" y2="56" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>
</button>
<div class="flex justify-between" hx-disinherit="*">
{% if isDirty %}
<button type="button"
hx-get="{{ path('app_booking_edit_cancel', {id: bookingData.id}) }}"
hx-target="body"
hx-swap="beforeend"
class="inline-flex items-center justify-center bg-gray-200 rounded-md w-10 h-10">
<svg class="w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="200" y1="56" x2="56" y2="200" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="200" y1="200" x2="56" y2="56" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>
</button>
{% else %}
<a href="{{ path('app_bookings') }}"
class="inline-flex items-center justify-center bg-gray-200 rounded-md w-10 h-10">
<svg class="w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="200" y1="56" x2="56" y2="200" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="200" y1="200" x2="56" y2="56" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>
</a>
{% endif %}
{% if isDirty %}
<button type="submit"
{{ stimulus_action('loading', 'show') }}
{% if hasValidationErrors|default(false) %}
disabled
title="Bitte behebe zuerst alle Validierungsfehler"
title="Bitte prüfe zuerst deine Eingaben"
{% endif %}
class="button button--primary {{ hasValidationErrors|default(false) ? 'opacity-50 cursor-not-allowed' : '' }}">
Buchung aktualisieren
@@ -0,0 +1,22 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Sicher?{% endblock %}
{% block content %}
<div class="pb-8">
Willst du die Bearbeitung wirklich abbrechen? Ungespeicherte Änderungen gehen verloren.
</div>
<div class="flex justify-between">
<button type="button"
hx-post="{{ path('app_booking_edit_cancel', {id: bookingId}) }}"
hx-target="body"
class="button button--small button--primary">
Ja
</button>
<button type="button"
{{ stimulus_action('modal', 'close') }}
class="button button--small button--secondary">
Nein
</button>
</div>
{% endblock %}
@@ -0,0 +1,22 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Sicher?{% endblock %}
{% block content %}
<div class="pb-8">
Alle nicht gespeicherten Änderungen gehen verloren. Fortfahren?
</div>
<div class="flex justify-between">
<button type="button"
hx-post="{{ path('app_booking_edit_reload', {id: bookingId}) }}"
hx-target="body"
class="button button--small button--primary">
Ja
</button>
<button type="button"
{{ stimulus_action('modal', 'close') }}
class="button button--small button--secondary">
Nein
</button>
</div>
{% endblock %}
+2 -6
View File
@@ -4,10 +4,7 @@
{{ form_start(form, {
'attr': {
'class': 'flex-1 flex flex-col min-h-0',
'novalidate': 'novalidate',
'hx-post': path(submitRouteName, submitRouteParams|default({index: participantIndex})),
'hx-target': '#main-content',
'hx-swap': 'innerHTML scroll:top'
'novalidate': 'novalidate'
}
}) }}
<div class="flex-1 flex flex-col lg:grid lg:grid-cols-5 min-h-0 relative">
@@ -38,11 +35,10 @@
<div class="flex justify-between">
<a href="{{ path('app_booking_edit', {id: bookingDto.booking.id}) }}"
class="inline-flex items-center justify-center bg-gray-200 rounded-md w-10 h-10"
{{ stimulus_action('loading', 'show') }}
{{ qa_attribute('btn-cancel') }}>
<svg class="w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="200" y1="56" x2="56" y2="200" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="200" y1="200" x2="56" y2="56" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>
</a>
<button type="submit" class="button button--primary" {{ qa_attribute('btn-submit') }} {{ stimulus_action('loading', 'show') }}>
<button type="submit" class="button button--primary" {{ qa_attribute('btn-submit') }}>
Speichern
</button>
</div>