From 126fce96871cce34afaae1cfde613f93df7a64c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Tue, 25 Nov 2025 16:42:39 +0100 Subject: [PATCH] feat: step input for room type selection --- assets/controllers/step_input_controller.js | 44 +++++++++++++++++++++ assets/styles/components/button.css | 6 ++- src/Form/RoomSelectType.php | 5 ++- src/Form/StepSelectChoiceType.php | 31 +++++++++++++++ templates/booking/create/step_1.html.twig | 17 +------- templates/forms.html.twig | 19 +++++++++ 6 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 assets/controllers/step_input_controller.js create mode 100644 src/Form/StepSelectChoiceType.php diff --git a/assets/controllers/step_input_controller.js b/assets/controllers/step_input_controller.js new file mode 100644 index 0000000..24a5b80 --- /dev/null +++ b/assets/controllers/step_input_controller.js @@ -0,0 +1,44 @@ +import {Controller} from '@hotwired/stimulus' + +export default class extends Controller { + + static targets = ['field', 'display', 'buttonInc', 'buttonDec'] + + static values = { + current: Number, + min: Number, + max: Number + } + + connect() { + this.currentValue = parseInt(this.fieldTarget.value) || 0 + this.updateForm() + } + + increase() { + if (null !== this.maxValue && this.currentValue >= this.maxValue) { + return + } + this.currentValue = this.currentValue + 1 + this.updateForm() + } + + decrease() { + if (null !== this.minValue && this.currentValue <= this.minValue) { + return + } + this.currentValue = this.currentValue - 1 + this.updateForm() + } + + updateForm() { + this.displayTarget.innerText = this.currentValue + this.fieldTarget.value = this.currentValue + + this.buttonIncTarget.disabled = null !== this.maxValue && this.currentValue >= this.maxValue + this.buttonDecTarget.disabled = null !== this.minValue && this.currentValue <= this.minValue + + // Trigger change event to fire HTMX request + this.fieldTarget.dispatchEvent(new Event('change', {bubbles: true})) + } +} diff --git a/assets/styles/components/button.css b/assets/styles/components/button.css index c8afba0..09bf382 100644 --- a/assets/styles/components/button.css +++ b/assets/styles/components/button.css @@ -20,7 +20,7 @@ .bg-button--active, .bg-button--secondary { - @apply bg-badge-gradient; + @apply bg-badge-gradient text-white; @apply hover:bg-none hover:bg-pink; } @@ -43,3 +43,7 @@ @apply bg-white; @apply border-secondary text-secondary; } + +.button[disabled] { + @apply cursor-not-allowed; +} diff --git a/src/Form/RoomSelectType.php b/src/Form/RoomSelectType.php index 439b5cf..844869e 100644 --- a/src/Form/RoomSelectType.php +++ b/src/Form/RoomSelectType.php @@ -4,7 +4,6 @@ namespace App\Form; use App\Form\Model\RoomSelectionDto; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; @@ -28,9 +27,11 @@ class RoomSelectType extends AbstractType $label .= sprintf(' (€%s pro Person)', $formattedPrice); } - $form->add('quantity', ChoiceType::class, [ + $form->add('quantity', StepSelectChoiceType::class, [ 'label' => $label, 'required' => true, + 'min_value' => 0, + 'max_value' => $data->maxQuantity, 'choices' => ['-' => 0] + array_combine(range(1, $data->maxQuantity), range(1, $data->maxQuantity)), ]); }); diff --git a/src/Form/StepSelectChoiceType.php b/src/Form/StepSelectChoiceType.php new file mode 100644 index 0000000..f38e4a3 --- /dev/null +++ b/src/Form/StepSelectChoiceType.php @@ -0,0 +1,31 @@ +vars['min_value'] = $options['min_value']; + $view->vars['max_value'] = $options['max_value']; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'min_value' => null, + 'max_value' => null, + ]); + } +} diff --git a/templates/booking/create/step_1.html.twig b/templates/booking/create/step_1.html.twig index 9cee07c..83f5c9c 100644 --- a/templates/booking/create/step_1.html.twig +++ b/templates/booking/create/step_1.html.twig @@ -13,19 +13,6 @@ {# This block contains the room selection form fields #} {% block room_selection_form %}
- {% if bookingCreateDto.bookingStatus == 'A' %} -
-
- - - -
-

Buchung auf Anfrage

-

Diese Reise kann nur auf Anfrage gebucht werden. Deine Buchung wird nach Eingang geprüft und du erhältst eine Bestätigung.

-
-
-
- {% endif %} {{ form_errors(form) }} {% if groupedRooms.by_room is not empty %}

@@ -36,7 +23,7 @@ 'attr': { 'hx-post': path('app_booking_create_step_1_refresh'), 'hx-swap': 'none', - 'hx-trigger': 'change', + 'hx-trigger': 'change delay:300ms', } }) }} {% endfor %} @@ -50,7 +37,7 @@ 'attr': { 'hx-post': path('app_booking_create_step_1_refresh'), 'hx-swap': 'none', - 'hx-trigger': 'change' + 'hx-trigger': 'change delay:300ms' } }) }} {% endfor %} diff --git a/templates/forms.html.twig b/templates/forms.html.twig index c983d29..3513ecd 100644 --- a/templates/forms.html.twig +++ b/templates/forms.html.twig @@ -318,3 +318,22 @@ {{- parent() -}} {%- endif -%} {% endblock %} + +{% block step_select_choice_widget %} +
+ {{ form_widget(form, { 'attr': { + 'data-step-input-target': 'field', + 'class': 'hidden', + } }) }} +
+ +
+ +
+
+{% endblock %} +