feat: extended insurance parsing, pass info urls to view

This commit is contained in:
Björn Fromme
2025-10-02 16:32:50 +02:00
parent 875b181aff
commit 25029dff5d
8 changed files with 277 additions and 23 deletions
+1 -1
View File
@@ -250,7 +250,7 @@ class BookingCreateParticipantType extends AbstractType
'parking' => CheckboxType::class,
'licensePlate' => TextType::class,
'bulkInsuranceBooking' => CheckboxType::class,
'insurance' => ChoiceType::class,
'insurance' => InsuranceChoiceType::class,
];
foreach ($dynamicFields as $fieldName => $fieldType) {
+86
View File
@@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
namespace App\Form;
use App\BusProNet\Model\Insurance;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Custom form type for insurance selection that provides full Insurance objects to templates.
*
* This type extends ChoiceType to pass complete Insurance model data to the template layer,
* enabling flexible rendering of insurance details including URLs, pricing, and coverage information.
*/
class InsuranceChoiceType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setRequired('insurances');
$resolver->setAllowedTypes('insurances', 'array');
$resolver->setDefault('choices', function (Options $options) {
// Prepend "no insurance" option to eligible insurances
return array_merge(
[0 => null],
$options['insurances']
);
});
$resolver->setDefault('choice_value', function ($insurance) {
// Handle "no insurance" option (null value at index 0)
// instanceof check required because closures in configureOptions receive mixed types
if ($insurance instanceof Insurance) {
return (string) $insurance->id;
}
return '';
});
$resolver->setDefault('choice_label', function ($insurance) {
// Handle "no insurance" option (null value at index 0)
// instanceof check required because closures in configureOptions receive mixed types
if (!$insurance instanceof Insurance) {
return 'Keine Versicherung';
}
$label = $insurance->label;
if (null !== $insurance->price && $insurance->price > 0) {
$label .= sprintf(' (€%s)', number_format($insurance->price, 2, ',', '.'));
}
return $label;
});
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
// Index insurances by ID for template lookup
$insurances = [];
foreach ($options['insurances'] as $insurance) {
if ($insurance instanceof Insurance) {
$insurances[(string) $insurance->id] = $insurance;
}
}
// Pass Insurance objects to template indexed by choice value
$view->vars['insurances'] = $insurances;
}
public function getParent(): string
{
return ChoiceType::class;
}
public function getBlockPrefix(): string
{
return 'insurance_choice';
}
}
@@ -422,12 +422,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
'multiple' => false,
'expanded' => true,
'required' => false,
'choices' => array_merge(
[0 => null], // "no insurance" option
$this->getEligibleInsurances($bookingDto, $participantIndex)
),
'choice_label' => fn (?Insurance $insurance) => $this->formatInsuranceLabel($insurance),
'choice_value' => 'id',
'insurances' => $this->getEligibleInsurances($bookingDto, $participantIndex),
'attr' => [
'hx-post' => $this->urlGenerator->generate('app_booking_create_step_2_refresh'),
'hx-swap' => 'none',
@@ -729,6 +724,10 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
$availableInsurances = $bookingDto->travel->insurances ?? [];
// Exclude complementary insurances from standalone selection
// They are only available as part of packages
$availableInsurances = array_filter($availableInsurances, fn ($insurance) => !$insurance->complementary);
// Only apply insurance filtering for BookingCreateDto (creation workflow)
if (!$bookingDto instanceof BookingCreateDto) {
return $availableInsurances;