wip: rentals insurance field

This commit is contained in:
Björn Fromme
2025-09-03 17:54:19 +02:00
parent 2953ed0b2d
commit 195246af89
13 changed files with 315 additions and 83 deletions
+68
View File
@@ -297,4 +297,72 @@ class CustomFieldOptionsProvider extends AbstractFieldOptionsProvider
}
```
## Current Implementation Examples
### Body Dimensions and Rental Insurance Conditional Fields
The current system implements sophisticated conditional field visibility for body dimensions and rental insurance:
```php
// CreateFieldStateProvider.php
protected function registerFieldStateConditions(): void
{
$rentalCondition = new RentalSelectionCondition();
// Hide body dimensions section unless rental services are selected
$this->fieldStateConditions['bodyDimensions'] = [
'hidden' => CompositeCondition::not($rentalCondition),
];
// Hide rental insurance unless rental services are selected
$this->fieldStateConditions['rentalInsurance'] = [
'hidden' => CompositeCondition::not($rentalCondition),
];
// Hide parking unless outbound transportation is PKW (car)
$this->fieldStateConditions['parking'] = [
'hidden' => CompositeCondition::not(
ServiceSubTypeCondition::equals('transportationOutbound', DirectionMapper::SUBTYPE_CAR_API)
),
];
}
```
### Rental Insurance Checkbox Implementation
The rental insurance field demonstrates the checkbox pattern used for service selection:
```php
// Field Options Provider
$this->fieldOptionProviders['rentalInsurance'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
'label' => $this->getRentalInsuranceCheckboxLabel($rentalInsuranceServices),
'required' => false,
'property_path' => 'rentalInsuranceSelected', // Maps to boolean property
];
// Field Handler Processing
public function processField(array $submittedData, BookingDtoInterface $bookingDto, int $participantIndex): void
{
$isRentalInsuranceSelected = (bool) $this->getFieldValue($submittedData, $this->getFieldName());
// Store boolean value for form state
$participant->rentalInsuranceSelected = $isRentalInsuranceSelected;
// Store Service object for pricing calculations
if ($isRentalInsuranceSelected) {
$participant->rentalInsurance = $this->findRentalInsuranceService($bookingDto);
} else {
$participant->rentalInsurance = null;
}
}
```
### Benefits of Current Architecture
1. **Clean Separation**: Boolean properties handle form state, Service objects handle business logic
2. **Automatic Pricing Integration**: Service objects are automatically included in pricing calculations
3. **Dynamic Visibility**: Fields appear/disappear based on related selections
4. **Consistent UX**: Checkbox pattern provides intuitive user interface
5. **Validation-Free**: Conditional visibility eliminates need for complex validation rules
This system provides a powerful, maintainable foundation for complex conditional field behavior while maintaining clean separation of concerns and extensibility.
+49 -10
View File
@@ -35,7 +35,8 @@ class BookingCreateDto implements BookingDtoInterface
#### ParticipantDto (`src/Form/Model/ParticipantDto.php`)
- Individual participant data container
- Includes personal data, body dimensions, and service selections
- Custom validation for body dimensions when rental services are selected
- Body dimensions are hidden unless rental services are selected (conditional visibility)
- Rental insurance field with checkbox interface and boolean state tracking
```php
class ParticipantDto
@@ -46,7 +47,7 @@ class ParticipantDto
public ?\DateTimeImmutable $dateOfBirth = null;
public ?string $email = null;
// Body dimensions (conditional)
// Body dimensions (hidden unless rental services are selected)
public ?string $height = null;
public ?string $weight = null;
public ?string $shoeSize = null;
@@ -56,7 +57,16 @@ class ParticipantDto
public array $courses = [];
public array $additionalServices = [];
public array $rentals = [];
// ... other service arrays
public ?Service $rentalInsurance = null;
public bool $rentalInsuranceSelected = false; // Checkbox state
// Transportation services
public ?Service $transportationOutbound = null;
public ?Service $transportationInbound = null;
public ?Pickup $pickupOutbound = null;
public ?Pickup $pickupInbound = null;
public bool $parking = false;
public ?Service $parkingService = null;
}
```
@@ -87,9 +97,21 @@ Central registry for dynamic field configurations using a provider pattern with
- **`rentals`**: Rental equipment options
- Date-filtered rental services
- Triggers body dimension requirements when selected
- Controls visibility of body dimensions and rental insurance fields
- Populated from `TOKEN_RENTALS` subtype services
- **`rentalInsurance`**: Rental insurance checkbox
- Checkbox interface (similar to parking field)
- Maps to `rentalInsuranceSelected` boolean property
- Only visible when rental services are selected
- Automatically manages Service object for pricing calculations
- Populated from `TOKEN_RENTAL_INSURANCE` subtype services
- **`parking`**: Parking service checkbox
- Boolean checkbox for self-organized transportation
- Only visible when outbound transportation is PKW (car)
- Manages both boolean state and Service object for pricing
**Provider Pattern Implementation:**
```php
protected function registerFieldOptionProviders(): void
@@ -108,7 +130,8 @@ protected function registerFieldOptionProviders(): void
**CreateFieldStateProvider (`src/Form/Service/CreateFieldStateProvider.php`)**
- Manages field states for the booking creation workflow
- Currently implements body dimension requirements for rental services
- Controls conditional field visibility and state based on participant data
- Implements body dimensions and rental insurance conditional visibility
**Field State Types:**
- `readonly`: Field is visible but not editable
@@ -122,10 +145,22 @@ protected function registerFieldStateConditions(): void
{
$rentalCondition = new RentalSelectionCondition();
// Body dimensions become required when rentals are selected
$this->fieldStateConditions['height'] = ['required' => $rentalCondition];
$this->fieldStateConditions['weight'] = ['required' => $rentalCondition];
$this->fieldStateConditions['shoeSize'] = ['required' => $rentalCondition];
// Hide body dimensions section unless rental services are selected
$this->fieldStateConditions['bodyDimensions'] = [
'hidden' => CompositeCondition::not($rentalCondition),
];
// Hide rental insurance unless rental services are selected
$this->fieldStateConditions['rentalInsurance'] = [
'hidden' => CompositeCondition::not($rentalCondition),
];
// Hide parking unless outbound transportation is PKW (car)
$this->fieldStateConditions['parking'] = [
'hidden' => CompositeCondition::not(
ServiceSubTypeCondition::equals('transportationOutbound', DirectionMapper::SUBTYPE_CAR_API)
),
];
}
```
@@ -227,10 +262,14 @@ Base class providing common functionality:
- **`ParticipantCoursesFieldHandler`**: Course selections filtering
- **`ParticipantBoardFieldHandler`**: Board/meal options filtering
- **`ParticipantRentalsFieldHandler`**: Rental equipment filtering
- **`ParticipantRentalInsuranceFieldHandler`**: Rental insurance checkbox handling
- Depends on `['dateOfBirth', 'rentals']` (only visible when rentals selected)
- Processes boolean checkbox input and converts to Service object
- Manages both `rentalInsuranceSelected` (bool) and `rentalInsurance` (Service) properties
All service handlers share these characteristics:
- Depend on `dateOfBirth` field (processed first)
- Filter selections based on age constraints
- Filter selections based on age constraints (except rental insurance which uses conditional visibility)
- Instantiate `ServiceAgeEvaluator` directly when needed
- Remove invalid selections to prevent form validation errors
- **Store complete Service objects** in ParticipantDto (not just IDs) for pricing calculations
+2
View File
@@ -31,6 +31,8 @@
- **Parking Services**: Self-organized transport handling ✅
- **Accommodation Services**: Board selection, room assignment ✅
- **Activity Services**: Ski passes, courses, rentals ✅
- **Rental Insurance**: Checkbox interface with conditional visibility ✅
- **Body Dimensions**: Hidden unless rental services selected ✅
- **Additional Services**: Flexible service extension system ✅
#### Pricing & Display System