From f0c43a17d82ad3dd7c83f359bfd27a4b10acbdf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Mon, 19 Jan 2026 16:05:23 +0100 Subject: [PATCH] feat: body dimensions mandatory with selected rentals, updated help text feat: body dimensions mandatory with selected rentals --- src/Form/BodyDimensionsType.php | 11 ++-- .../Constraints/ParticipantValidator.php | 31 ++++++++++ templates/booking/_participant_form.html.twig | 7 ++- .../Constraints/ParticipantValidatorTest.php | 61 ++++++++++++++++++- 4 files changed, 100 insertions(+), 10 deletions(-) diff --git a/src/Form/BodyDimensionsType.php b/src/Form/BodyDimensionsType.php index e715077..81df486 100644 --- a/src/Form/BodyDimensionsType.php +++ b/src/Form/BodyDimensionsType.php @@ -50,17 +50,14 @@ class BodyDimensionsType extends AbstractType { $resolver->setDefaults([ 'data_class' => ParticipantDto::class, - 'height_required' => false, - 'weight_required' => false, - 'shoeSize_required' => false, + 'height_required' => true, + 'weight_required' => true, + 'shoeSize_required' => true, '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', - ], + 'help' => 'Verleih kann bis 4 Tage vor Anreise in MyE&P nachgebucht werden, sollten dir (noch) nicht alle Angaben vorliegen', ]); $resolver->setAllowedTypes('height_required', 'bool'); diff --git a/src/Validator/Constraints/ParticipantValidator.php b/src/Validator/Constraints/ParticipantValidator.php index fb71fad..5b19838 100644 --- a/src/Validator/Constraints/ParticipantValidator.php +++ b/src/Validator/Constraints/ParticipantValidator.php @@ -22,6 +22,7 @@ class ParticipantValidator extends ConstraintValidator $participant = $value; $this->assertPickupSelected($participant); + $this->assertBodyDimensionsWhenRentalsSelected($participant); } public function assertPickupSelected(ParticipantDto $participant): void @@ -40,4 +41,34 @@ class ParticipantValidator extends ConstraintValidator ; } } + + public function assertBodyDimensionsWhenRentalsSelected(ParticipantDto $participant): void + { + // Check if any rental services are selected + if (true === empty($participant->rentals)) { + return; + } + + // Require body dimensions when rentals are selected + if (null === $participant->height || '' === $participant->height) { + $this->context->buildViolation('Bitte auswählen') + ->atPath('height') + ->addViolation() + ; + } + + if (null === $participant->weight || '' === $participant->weight) { + $this->context->buildViolation('Bitte auswählen') + ->atPath('weight') + ->addViolation() + ; + } + + if (null === $participant->shoeSize || '' === $participant->shoeSize) { + $this->context->buildViolation('Bitte auswählen') + ->atPath('shoeSize') + ->addViolation() + ; + } + } } diff --git a/templates/booking/_participant_form.html.twig b/templates/booking/_participant_form.html.twig index 4c2bac7..e08f2c0 100644 --- a/templates/booking/_participant_form.html.twig +++ b/templates/booking/_participant_form.html.twig @@ -398,7 +398,12 @@ {{ form_row(form.bodyDimensions.height) }} {{ form_row(form.bodyDimensions.shoeSize) }} {{ form_row(form.bodyDimensions.weight) }} - {{ form_help(form.bodyDimensions) }} +
+ + + + {{ form.bodyDimensions.vars.help }} +
{% endif %} diff --git a/tests/Validator/Constraints/ParticipantValidatorTest.php b/tests/Validator/Constraints/ParticipantValidatorTest.php index 30a94a9..542ed9c 100644 --- a/tests/Validator/Constraints/ParticipantValidatorTest.php +++ b/tests/Validator/Constraints/ParticipantValidatorTest.php @@ -17,17 +17,74 @@ class ParticipantValidatorTest extends ConstraintValidatorTestCase return new ParticipantValidator(); } - public function testParticipantWithRentalsButNoBodyMeasurementsPassesValidation(): void + public function testParticipantWithRentalsAndBodyMeasurementsPassesValidation(): void { $participant = $this->createValidParticipant(); $participant->rentals = [$this->createMockService()]; + $participant->height = '170'; + $participant->weight = '70'; + $participant->shoeSize = '42'; + + $this->validator->validate($participant, new Participant()); + + $this->assertNoViolation(); + } + + public function testParticipantWithRentalsButNoHeightFailsValidation(): void + { + $participant = $this->createValidParticipant(); + $participant->rentals = [$this->createMockService()]; + $participant->height = null; + $participant->weight = '70'; + $participant->shoeSize = '42'; + + $this->validator->validate($participant, new Participant()); + + $this->buildViolation('Bitte auswählen') + ->atPath('property.path.height') + ->assertRaised(); + } + + public function testParticipantWithRentalsButNoWeightFailsValidation(): void + { + $participant = $this->createValidParticipant(); + $participant->rentals = [$this->createMockService()]; + $participant->height = '170'; + $participant->weight = null; + $participant->shoeSize = '42'; + + $this->validator->validate($participant, new Participant()); + + $this->buildViolation('Bitte auswählen') + ->atPath('property.path.weight') + ->assertRaised(); + } + + public function testParticipantWithRentalsButNoShoeSizeFailsValidation(): void + { + $participant = $this->createValidParticipant(); + $participant->rentals = [$this->createMockService()]; + $participant->height = '170'; + $participant->weight = '70'; + $participant->shoeSize = null; + + $this->validator->validate($participant, new Participant()); + + $this->buildViolation('Bitte auswählen') + ->atPath('property.path.shoeSize') + ->assertRaised(); + } + + public function testParticipantWithoutRentalsAndNoBodyMeasurementsPassesValidation(): void + { + $participant = $this->createValidParticipant(); + $participant->rentals = []; $participant->height = null; $participant->weight = null; $participant->shoeSize = null; $this->validator->validate($participant, new Participant()); - // Body measurements are optional and can be provided later $this->assertNoViolation(); }