wip: refactor forms

This commit is contained in:
Björn Fromme
2026-03-16 11:59:09 +01:00
parent b44d8505b2
commit d205cd09ef
7 changed files with 112 additions and 87 deletions
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class BodyDimensionsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('height', ChoiceType::class, [
'label' => 'Körpergröße',
'required' => false,
'expanded' => false,
'multiple' => false,
'placeholder' => 'Keine Angabe',
'choices' => [
'bis 148cm' => '-148',
'149 - 157cm' => '149-157',
'158 - 166cm' => '158-166',
'167 - 178cm' => '167-178',
'179 - 194cm' => '179-197',
'195cm oder mehr' => '195cm+',
],
])
->add('shoeSize', ChoiceType::class, [
'label' => 'Schuhgröße',
'required' => false,
'expanded' => false,
'multiple' => false,
'placeholder' => 'Keine Angabe',
'choices' => array_combine(range(36, 48), range(36, 48)),
])
->add('weight', ChoiceType::class, [
'label' => 'Gewicht',
'required' => false,
'expanded' => false,
'multiple' => false,
'placeholder' => 'Keine Angabe',
'choices' => [
'42 - 48kg' => '42-48',
'49 - 57kg' => '49-57',
'58 - 66kg' => '58-66',
'67 - 78kg' => '67-78',
'79 - 94kg' => '79-94',
'95kg oder mehr' => '95k+',
],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'inherit_data' => true,
]);
}
}
+2 -2
View File
@@ -65,6 +65,7 @@ class BookingCreateParticipantType extends AbstractType
'required' => false,
'clean_xss' => true,
])
->add('bodyDimensions', BodyDimensionsType::class)
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options) {
/** @var ParticipantDto|null $participantData */
$participantData = $event->getData();
@@ -95,8 +96,7 @@ class BookingCreateParticipantType extends AbstractType
'placeholder' => 'Bitte wählen',
'choice_loader' => $choiceLoader,
]);
})
;
});
}
public function configureOptions(OptionsResolver $resolver): void
+2 -4
View File
@@ -17,8 +17,7 @@ class BookingCreateStep2Type extends AbstractType
{
$builder
->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'onPreSetData'])
->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'onPreSubmit'])
;
->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'onPreSubmit']);
}
/**
@@ -60,7 +59,7 @@ class BookingCreateStep2Type extends AbstractType
if (isset($participantData['assignedRoomId']) && isset($bookingDto->participants[$index])) {
$roomId = $participantData['assignedRoomId'];
// An unselected choice submits an empty string.
$bookingDto->participants[$index]->assignedRoomId = '' === $roomId ? null : (int) $roomId;
$bookingDto->participants[$index]->assignedRoomId = empty($roomId) ? null : (int) $roomId;
}
}
@@ -77,7 +76,6 @@ class BookingCreateStep2Type extends AbstractType
'entry_type' => BookingCreateParticipantType::class,
'allow_add' => false,
'allow_delete' => false,
'by_reference' => false,
'entry_options' => [
'selected_rooms' => $data->getSelectedRooms(),
],
+38 -77
View File
@@ -99,45 +99,7 @@ class BookingEditParticipantType extends AbstractType
],
'clean_xss' => true,
])
->add('height', ChoiceType::class, [
'label' => 'Körpergröße',
'required' => false,
'expanded' => false,
'multiple' => false,
'placeholder' => 'Keine Angabe',
'choices' => [
'bis 148cm' => '-148',
'149 - 157cm' => '149-157',
'158 - 166cm' => '158-166',
'167 - 178cm' => '167-178',
'179 - 194cm' => '179-197',
'195cm oder mehr' => '195cm+',
],
])
->add('shoeSize', ChoiceType::class, [
'label' => 'Schuhgröße',
'required' => false,
'expanded' => false,
'multiple' => false,
'placeholder' => 'Keine Angabe',
'choices' => array_combine(range(36, 48), range(36, 48)),
])
->add('weight', ChoiceType::class, [
'label' => 'Gewicht',
'required' => false,
'expanded' => false,
'multiple' => false,
'placeholder' => 'Keine Angabe',
'choices' => [
'42 - 48kg' => '42-48',
'49 - 57kg' => '49-57',
'58 - 66kg' => '58-66',
'67 - 78kg' => '67-78',
'79 - 94kg' => '79-94',
'95kg oder mehr' => '95k+',
],
])
;
->add('bodyDimensions', BodyDimensionsType::class);
$commonChoiceFieldOptions = [
'required' => false,
@@ -278,8 +240,7 @@ class BookingEditParticipantType extends AbstractType
'multiple' => false,
'choices' => $options['selectable_transportation_services_fro'],
'choice_attr' => $transportationChoiceAttributes,
])
;
]);
// Pickup
$form->add('pickup', ChoiceType::class, [
@@ -296,7 +257,7 @@ class BookingEditParticipantType extends AbstractType
$pickupLabel = $pickup->city;
if (null !== $pickup->street) {
$pickupLabel .= ' ('.$pickup->street.')';
$pickupLabel .= ' (' . $pickup->street . ')';
}
$price = $pickup->price;
@@ -324,46 +285,46 @@ class BookingEditParticipantType extends AbstractType
],
]);
})
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) {
$data = $event->getData();
$form = $event->getForm();
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) {
$data = $event->getData();
$form = $event->getForm();
// skip processing for canceled participants
if ('F' !== $form->getData()->status) {
return;
}
$transportationId = $data['transportationServiceTo'] ?? null;
$transportation = $options['travel']->pickups[$transportationId] ?? null;
if (null !== $transportation && 'PKW' === $transportation->subType) {
$form->remove('pickup');
unset($data['pickup']);
}
// forcibly select mandatory services that potentially have been disabled in PRE_SET_DATA
$mandatoryServices = array_filter($options['selectable_services'], function (Service $service) use ($form) {
$participantIndex = $form->getData()->index;
return true === $service->mandatory
|| (Constants::SOURCE_BOOKING === $service->source && in_array($participantIndex, $service->mapping));
});
if (0 < count($mandatoryServices)) {
if (false === isset($data['additionalServices'])) {
$data['additionalServices'] = [];
// skip processing for canceled participants
if ('F' !== $form->getData()->status) {
return;
}
$mandatoryServiceIds = array_map(function (Service $service) {
return $service->id;
}, $mandatoryServices);
$transportationId = $data['transportationServiceTo'] ?? null;
$transportation = $options['travel']->pickups[$transportationId] ?? null;
$allServiceIds = [...$mandatoryServiceIds, ...$data['additionalServices']];
$data['additionalServices'] = array_unique($allServiceIds);
}
if (null !== $transportation && 'PKW' === $transportation->subType) {
$form->remove('pickup');
unset($data['pickup']);
}
$event->setData($data);
});
// forcibly select mandatory services that potentially have been disabled in PRE_SET_DATA
$mandatoryServices = array_filter($options['selectable_services'], function (Service $service) use ($form) {
$participantIndex = $form->getData()->index;
return true === $service->mandatory
|| (Constants::SOURCE_BOOKING === $service->source && in_array($participantIndex, $service->mapping));
});
if (0 < count($mandatoryServices)) {
if (false === isset($data['additionalServices'])) {
$data['additionalServices'] = [];
}
$mandatoryServiceIds = array_map(function (Service $service) {
return $service->id;
}, $mandatoryServices);
$allServiceIds = [...$mandatoryServiceIds, ...$data['additionalServices']];
$data['additionalServices'] = array_unique($allServiceIds);
}
$event->setData($data);
});
}
public function configureOptions(OptionsResolver $resolver): void
+1 -1
View File
@@ -47,7 +47,7 @@ class BookingEditType extends AbstractType
});
}
private function mergeSelectableServices(BookingEditDto $data, mixed $subType): array
private function mergeSelectableServices(BookingEditDto $data, string|array $subType): array
{
// combine selectable services from travel data with additional services
// from booking data
@@ -27,6 +27,11 @@
{{ form_row(participant.email) }}
{{ form_row(participant.mobile) }}
</div>
<div class="grid grid-cols-2 gap-4">
{{ form_row(participant.bodyDimensions.height) }}
{{ form_row(participant.bodyDimensions.shoeSize) }}
{{ form_row(participant.bodyDimensions.weight) }}
</div>
<div class="grid grid-cols-1 gap-4 pt-4">
{# hx-swap="none" tells HTMX not to do a normal swap, as OOB will handle it #}
{{ form_row(participant.assignedRoomId, {
+3 -3
View File
@@ -175,9 +175,9 @@
{{ form_row(child.mobile) }}
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-4">
{{ form_row(child.height) }}
{{ form_row(child.shoeSize) }}
{{ form_row(child.weight) }}
{{ form_row(child.bodyDimensions.height) }}
{{ form_row(child.bodyDimensions.shoeSize) }}
{{ form_row(child.bodyDimensions.weight) }}
</div>
{% if not travelData.participantDataMutable %}
<div class="absolute top-0 left-0 inset-0 cursor-not-allowed"></div>