diff --git a/src/Form/BookingParticipantType.php b/src/Form/BookingParticipantType.php index d84d1f2..3fdc9c1 100644 --- a/src/Form/BookingParticipantType.php +++ b/src/Form/BookingParticipantType.php @@ -166,9 +166,16 @@ class BookingParticipantType extends AbstractType ], $getFieldState('lastName'))) ->add('dateOfBirth', BirthdayType::class, $this->mergeFieldState([ 'label' => 'Geburtsdatum', - 'html5' => true, - 'widget' => 'single_text', + 'widget' => 'text', 'input' => 'datetime_immutable', + 'attr' => [ + 'class' => 'flex items-center space-x-2', + ], + 'placeholder' => [ + 'year' => 'Jahr', + 'month' => 'Monat', + 'day' => 'Tag', + ], ], $getFieldState('dateOfBirth'))) ->add('gender', ChoiceType::class, $this->mergeFieldState([ 'label' => 'Geschlecht', diff --git a/src/Form/Service/ParticipantDateOfBirthFieldHandler.php b/src/Form/Service/ParticipantDateOfBirthFieldHandler.php index 521f99f..32ea507 100644 --- a/src/Form/Service/ParticipantDateOfBirthFieldHandler.php +++ b/src/Form/Service/ParticipantDateOfBirthFieldHandler.php @@ -53,7 +53,7 @@ class ParticipantDateOfBirthFieldHandler extends AbstractParticipantFieldHandler * 4. Updates the participant's dateOfBirth property * * @param array $submittedData The submitted participant form data - * @param BookingDto $bookingDto The booking DTO to update (create or edit) + * @param BookingDto $bookingDto The booking DTO to update (create or edit) * @param int $participantIndex The index of the participant being processed */ public function processField(array $submittedData, BookingDto $bookingDto, int $participantIndex): void @@ -76,7 +76,14 @@ class ParticipantDateOfBirthFieldHandler extends AbstractParticipantFieldHandler * Normalizes a date value from form submission to DateTimeImmutable or null. * * This method handles the conversion of form date values to proper DateTimeImmutable - * objects. It gracefully handles empty strings, null values, and invalid date formats. + * objects. It gracefully handles empty strings, null values, invalid date formats, + * and array input from multi-field date widgets (BirthdayType). + * + * Supported input formats: + * - Array: ['year' => int, 'month' => int, 'day' => int] from BirthdayType + * - DateTimeInterface: Already converted DateTime objects + * - String: ISO date strings or any format parseable by DateTimeImmutable + * - Null/empty: No date selected * * @param mixed $value The raw value from form submission * @@ -84,18 +91,50 @@ class ParticipantDateOfBirthFieldHandler extends AbstractParticipantFieldHandler */ private function normalizeDateValue(mixed $value): ?\DateTimeImmutable { - // Handle null or empty string (no date selected) - if (null === $value || '' === trim((string) $value)) { + // Handle null first + if (null === $value) { return null; } + // Handle array input from multi-field date widget (BirthdayType) + if (true === is_array($value)) { + // Check if all required fields are present and valid + if (false === isset($value['year'], $value['month'], $value['day']) + || '' === trim((string) ($value['year'] ?? '')) + || '' === trim((string) ($value['month'] ?? '')) + || '' === trim((string) ($value['day'] ?? '')) + ) { + return null; + } + + try { + // Create date string in ISO format (YYYY-MM-DD) + $dateString = sprintf( + '%04d-%02d-%02d', + (int) $value['year'], + (int) $value['month'], + (int) $value['day'] + ); + + return new \DateTimeImmutable($dateString); + } catch (\Exception $e) { + // Invalid date components (e.g., Feb 31, invalid year) + return null; + } + } + // If already a DateTimeInterface, convert to DateTimeImmutable if ($value instanceof \DateTimeInterface) { return \DateTimeImmutable::createFromInterface($value); } - // Try to parse string date - if (is_string($value)) { + // Handle string date (including empty string check) + if (true === is_string($value)) { + // Empty string means no date selected + if ('' === trim($value)) { + return null; + } + try { return new \DateTimeImmutable($value); } catch (\Exception $e) {