From 0e9c5e6e1a3af82020e69d6d703cb65e7c1eef85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Wed, 10 Dec 2025 13:48:47 +0100 Subject: [PATCH] feat: configurable choices for body dimensions closes #8697phk21 --- config/services.yaml | 20 ++++++++ .../Booking/Create/Step2Controller.php | 39 +++++++++++++++ .../Booking/Edit/IndexController.php | 47 +++++++++++++++++++ .../Traits/ParticipantCardFlowTrait.php | 20 +++++++- src/Form/BodyDimensionsType.php | 41 ++++++++-------- src/Form/BookingEditParticipantType.php | 17 ++++++- src/Form/BookingParticipantType.php | 12 +++++ 7 files changed, 174 insertions(+), 22 deletions(-) diff --git a/config/services.yaml b/config/services.yaml index bab7a49..80cb466 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -7,6 +7,26 @@ parameters: travel_info_base_url: '%env(APP_TRAVEL_INFO_BASE_URL)%' path_to_keys: '%kernel.project_dir%/config/secret' + # Body dimensions choices for BodyDimensionsType + body_dimensions.height_choices: + 'bis 148cm': '-148' + '149 - 157cm': '149-157' + '158 - 166cm': '158-166' + '167 - 178cm': '167-178' + '179 - 185cm': '179-185' + '186 - 194cm': '186-194' + '195cm oder mehr': '195cm+' + body_dimensions.shoe_size_min: 36 + body_dimensions.shoe_size_max: 48 + body_dimensions.weight_choices: + '42 - 48kg': '42-48' + '49 - 57kg': '49-57' + '58 - 66kg': '58-66' + '67 - 78kg': '67-78' + '79 - 85kg': '79-85' + '86 - 94kg': '86-94' + '95kg oder mehr': '95k+' + services: # default configuration for services in *this* file _defaults: diff --git a/src/Controller/Booking/Create/Step2Controller.php b/src/Controller/Booking/Create/Step2Controller.php index b31c178..5047b36 100644 --- a/src/Controller/Booking/Create/Step2Controller.php +++ b/src/Controller/Booking/Create/Step2Controller.php @@ -18,6 +18,7 @@ use App\Service\ParticipantPrepopulationService; use App\Service\RoomAssignmentService; use App\Service\TravelDataService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; @@ -35,6 +36,10 @@ class Step2Controller extends AbstractController use HxTrait; use ParticipantCardFlowTrait; + /** + * @param array $heightChoices + * @param array $weightChoices + */ public function __construct( private readonly BookingService $bookingService, private readonly BookingSummaryDataService $summaryDataService, @@ -43,9 +48,43 @@ class Step2Controller extends AbstractController private readonly ParticipantCardDataService $participantCardService, private readonly ParticipantFieldOptionsProvider $fieldOptionsProvider, private readonly ParticipantPrepopulationService $prepopulationService, + #[Autowire(param: 'body_dimensions.height_choices')] + private readonly array $heightChoices, + #[Autowire(param: 'body_dimensions.weight_choices')] + private readonly array $weightChoices, + #[Autowire(param: 'body_dimensions.shoe_size_min')] + private readonly int $shoeSizeMin, + #[Autowire(param: 'body_dimensions.shoe_size_max')] + private readonly int $shoeSizeMax, ) { } + /** + * @return array + */ + private function getHeightChoices(): array + { + return $this->heightChoices; + } + + /** + * @return array + */ + private function getWeightChoices(): array + { + return $this->weightChoices; + } + + private function getShoeSizeMin(): int + { + return $this->shoeSizeMin; + } + + private function getShoeSizeMax(): int + { + return $this->shoeSizeMax; + } + /** * Display card grid for all participants. */ diff --git a/src/Controller/Booking/Edit/IndexController.php b/src/Controller/Booking/Edit/IndexController.php index d93bc8a..b0ead25 100644 --- a/src/Controller/Booking/Edit/IndexController.php +++ b/src/Controller/Booking/Edit/IndexController.php @@ -25,6 +25,7 @@ use App\Service\ParticipantCardDataService; use App\Service\TravelDataService; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; @@ -45,6 +46,10 @@ class IndexController extends AbstractController use HxTrait; use Traits\ParticipantCardFlowTrait; + /** + * @param array $heightChoices + * @param array $weightChoices + */ public function __construct( private readonly ApiClient $apiClient, private readonly BookingEditDataLoaderService $dataLoader, @@ -55,9 +60,43 @@ class IndexController extends AbstractController private readonly ParticipantCardDataService $participantCardService, private readonly Crypt $crypt, private readonly LoggerInterface $logger, + #[Autowire(param: 'body_dimensions.height_choices')] + private readonly array $heightChoices, + #[Autowire(param: 'body_dimensions.weight_choices')] + private readonly array $weightChoices, + #[Autowire(param: 'body_dimensions.shoe_size_min')] + private readonly int $shoeSizeMin, + #[Autowire(param: 'body_dimensions.shoe_size_max')] + private readonly int $shoeSizeMax, ) { } + /** + * @return array + */ + private function getHeightChoices(): array + { + return $this->heightChoices; + } + + /** + * @return array + */ + private function getWeightChoices(): array + { + return $this->weightChoices; + } + + private function getShoeSizeMin(): int + { + return $this->shoeSizeMin; + } + + private function getShoeSizeMax(): int + { + return $this->shoeSizeMax; + } + /** * Display participant cards overview. */ @@ -181,6 +220,10 @@ class IndexController extends AbstractController // Create form for participant with booking context $form = $this->createForm(BookingParticipantType::class, $wrapper, [ 'booking_context' => $bookingDto, + 'height_choices' => $this->heightChoices, + 'weight_choices' => $this->weightChoices, + 'shoe_size_min' => $this->shoeSizeMin, + 'shoe_size_max' => $this->shoeSizeMax, ]); $form->handleRequest($request); @@ -264,6 +307,10 @@ class IndexController extends AbstractController $form = $this->createForm(BookingParticipantType::class, $wrapper, [ 'booking_context' => $bookingDto, 'validation_groups' => false, + 'height_choices' => $this->heightChoices, + 'weight_choices' => $this->weightChoices, + 'shoe_size_min' => $this->shoeSizeMin, + 'shoe_size_max' => $this->shoeSizeMax, ]); $form->handleRequest($request); diff --git a/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php b/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php index 403a1a5..7d801de 100644 --- a/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php +++ b/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php @@ -71,14 +71,32 @@ trait ParticipantCardFlowTrait bookingContext: $bookingDto, ); - // Merge default options with provided options + // Merge default options with provided options and body dimensions $formOptions = array_merge([ 'booking_context' => $bookingDto, + 'height_choices' => $this->getHeightChoices(), + 'weight_choices' => $this->getWeightChoices(), + 'shoe_size_min' => $this->getShoeSizeMin(), + 'shoe_size_max' => $this->getShoeSizeMax(), ], $options); return $this->createForm(BookingParticipantType::class, $wrapper, $formOptions); } + /** + * @return array + */ + abstract private function getHeightChoices(): array; + + /** + * @return array + */ + abstract private function getWeightChoices(): array; + + abstract private function getShoeSizeMin(): int; + + abstract private function getShoeSizeMax(): int; + /** * Collects notifications from all participants and clears them from DTOs. * diff --git a/src/Form/BodyDimensionsType.php b/src/Form/BodyDimensionsType.php index f5cc370..e715077 100644 --- a/src/Form/BodyDimensionsType.php +++ b/src/Form/BodyDimensionsType.php @@ -1,5 +1,7 @@ add('height', ChoiceType::class, [ 'label' => 'Körpergröße', - 'required' => $options['height_required'] ?? false, + 'required' => $options['height_required'], '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+', - ], + 'choices' => $options['height_choices'], ]) ->add('shoeSize', ChoiceType::class, [ 'label' => 'Schuhgröße', - 'required' => $options['shoeSize_required'] ?? false, + 'required' => $options['shoeSize_required'], 'expanded' => false, 'multiple' => false, 'placeholder' => 'Keine Angabe', - 'choices' => array_combine(range(36, 48), range(36, 48)), + 'choices' => $shoeSizeChoices, ]) ->add('weight', ChoiceType::class, [ 'label' => 'Gewicht', - 'required' => $options['weight_required'] ?? false, + 'required' => $options['weight_required'], '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+', - ], + 'choices' => $options['weight_choices'], ]); } @@ -60,6 +53,10 @@ class BodyDimensionsType extends AbstractType 'height_required' => false, 'weight_required' => false, 'shoeSize_required' => false, + 'height_choices' => [], + 'weight_choices' => [], + 'shoe_size_min' => 36, + 'shoe_size_max' => 48, 'help' => 'Du kannst die Daten auch später nachreichen', 'help_attr' => [ 'class' => 'lg:col-span-3 text-sm -mt-2 px-2', @@ -69,5 +66,9 @@ class BodyDimensionsType extends AbstractType $resolver->setAllowedTypes('height_required', 'bool'); $resolver->setAllowedTypes('weight_required', 'bool'); $resolver->setAllowedTypes('shoeSize_required', 'bool'); + $resolver->setAllowedTypes('height_choices', 'array'); + $resolver->setAllowedTypes('weight_choices', 'array'); + $resolver->setAllowedTypes('shoe_size_min', 'int'); + $resolver->setAllowedTypes('shoe_size_max', 'int'); } } diff --git a/src/Form/BookingEditParticipantType.php b/src/Form/BookingEditParticipantType.php index ff16c07..e147be3 100644 --- a/src/Form/BookingEditParticipantType.php +++ b/src/Form/BookingEditParticipantType.php @@ -88,7 +88,12 @@ class BookingEditParticipantType extends AbstractType 'required' => false, 'sanitize_html' => true, ], $getState('mobile'))) - ->add('bodyDimensions', BodyDimensionsType::class); + ->add('bodyDimensions', BodyDimensionsType::class, [ + 'height_choices' => $options['height_choices'], + 'weight_choices' => $options['weight_choices'], + 'shoe_size_min' => $options['shoe_size_min'], + 'shoe_size_max' => $options['shoe_size_max'], + ]); $commonChoiceFieldOptions = [ 'required' => false, @@ -371,7 +376,17 @@ class BookingEditParticipantType extends AbstractType 'applicant_id' => null, // Booking DTO for field state provider (must be set by parent form) 'booking' => null, + // Body dimensions choices + 'height_choices' => [], + 'weight_choices' => [], + 'shoe_size_min' => 36, + 'shoe_size_max' => 48, ]); + + $resolver->setAllowedTypes('height_choices', 'array'); + $resolver->setAllowedTypes('weight_choices', 'array'); + $resolver->setAllowedTypes('shoe_size_min', 'int'); + $resolver->setAllowedTypes('shoe_size_max', 'int'); } /** diff --git a/src/Form/BookingParticipantType.php b/src/Form/BookingParticipantType.php index 50f8414..f698131 100644 --- a/src/Form/BookingParticipantType.php +++ b/src/Form/BookingParticipantType.php @@ -252,6 +252,10 @@ class BookingParticipantType extends AbstractType if ($this->fieldStateProvider->shouldIncludeField('bodyDimensions', $bookingDto, $participantIndex)) { $form->add('bodyDimensions', BodyDimensionsType::class, [ 'property_path' => 'participant', + 'height_choices' => $form->getConfig()->getOption('height_choices'), + 'weight_choices' => $form->getConfig()->getOption('weight_choices'), + 'shoe_size_min' => $form->getConfig()->getOption('shoe_size_min'), + 'shoe_size_max' => $form->getConfig()->getOption('shoe_size_max'), ]); } } @@ -435,6 +439,10 @@ class BookingParticipantType extends AbstractType 'data_class' => ParticipantEditDto::class, 'selected_rooms' => [], 'booking_context' => null, + 'height_choices' => [], + 'weight_choices' => [], + 'shoe_size_min' => 36, + 'shoe_size_max' => 48, 'validation_groups' => function (FormInterface $form) { /** @var ParticipantEditDto $data */ $data = $form->getData(); @@ -462,5 +470,9 @@ class BookingParticipantType extends AbstractType $resolver->setAllowedTypes('selected_rooms', 'array'); $resolver->setAllowedTypes('booking_context', ['null', BookingDto::class]); + $resolver->setAllowedTypes('height_choices', 'array'); + $resolver->setAllowedTypes('weight_choices', 'array'); + $resolver->setAllowedTypes('shoe_size_min', 'int'); + $resolver->setAllowedTypes('shoe_size_max', 'int'); } }