# Universal Conditional Field State System This system provides a flexible architecture for implementing conditional field states (readonly, disabled, hidden) based on participant data and interdependent field values. ## Architecture Overview The system consists of several key components: 1. **FieldConditionInterface** - Defines the contract for condition evaluation 2. **Concrete Conditions** - Implement specific business logic (age ranges, field values, etc.) 3. **CompositeCondition** - Combines conditions with AND/OR/NOT logic 4. **FieldStateProviderInterface** - Manages field state calculation 5. **ParticipantFieldOptionsProvider** - Enhanced to support state conditions 6. **Form Integration** - Applied in BookingCreateParticipantType ## Usage Examples ### Basic Age-Based Condition ```php // Make a field readonly for participants under 18 $this->fieldStateConditions['serviceSelection'] = [ 'readonly' => new AgeRangeCondition(null, 17), ]; ``` ### Field Dependency Condition ```php // Disable field if room is not assigned $this->fieldStateConditions['mealPreference'] = [ 'disabled' => FieldValueCondition::empty('assignedRoomId'), ]; ``` ### Complex Composite Condition ```php // Hide field for young participants OR if basic service is selected $this->fieldStateConditions['advancedOptions'] = [ 'hidden' => CompositeCondition::or( new AgeRangeCondition(null, 15), FieldValueCondition::equals('serviceType', 'basic') ), ]; ``` ### Multiple State Conditions ```php // Field with multiple conditional states $this->fieldStateConditions['specialServices'] = [ 'readonly' => new AgeRangeCondition(null, 17), 'required' => FieldValueCondition::equals('roomType', 'premium'), 'disabled' => CompositeCondition::and( FieldValueCondition::empty('assignedRoomId'), FieldValueCondition::notEquals('participantType', 'staff') ), ]; ``` ## Available Conditions ### AgeRangeCondition - `new AgeRangeCondition(18, null)` - At least 18 years old - `new AgeRangeCondition(null, 17)` - Under 18 years old - `new AgeRangeCondition(18, 65)` - Between 18 and 65 years old ### FieldValueCondition - `FieldValueCondition::equals('field', 'value')` - Field equals specific value - `FieldValueCondition::notEquals('field', 'value')` - Field does not equal value - `FieldValueCondition::in('field', ['a', 'b'])` - Field value is in array - `FieldValueCondition::empty('field')` - Field is empty or null - `FieldValueCondition::isNotEmpty('field')` - Field has a value ### CompositeCondition - `CompositeCondition::and($cond1, $cond2)` - All conditions must be true - `CompositeCondition::or($cond1, $cond2)` - At least one condition must be true - `CompositeCondition::not($condition)` - Inverts condition result ## State Types - **readonly** - Field is visible but not editable - **disabled** - Field interaction is disabled - **required** - Field becomes mandatory - **hidden** - Field is not displayed (via CSS display: none) ## Adding New Conditions To register field state conditions, add them to the `registerFieldStateConditions()` method in `ParticipantFieldOptionsProvider`: ```php private function registerFieldStateConditions(): void { // Age-based readonly state $this->fieldStateConditions['assignedRoomId'] = [ 'readonly' => new AgeRangeCondition(null, 17), ]; // Field dependency $this->fieldStateConditions['mealPreference'] = [ 'disabled' => FieldValueCondition::empty('assignedRoomId'), ]; // Complex business logic $this->fieldStateConditions['advancedServices'] = [ 'hidden' => CompositeCondition::or( new AgeRangeCondition(null, 15), FieldValueCondition::equals('membershipLevel', 'basic') ), 'required' => FieldValueCondition::equals('roomType', 'suite'), ]; } ``` ## Performance Considerations - Conditions use lazy evaluation and short-circuit logic - Field state calculations are cached during form processing - Dependency tracking prevents unnecessary re-evaluations - Bulk state calculation optimizes multiple field updates ## Integration with HTMX The system supports real-time field state updates: 1. Field changes trigger dependency re-evaluation 2. State modifications are applied via form rebuilding 3. HTMX can update field states without full page refresh 4. Dependency tracking ensures only affected fields are updated ## Extending the System ### Custom Conditions Create new condition classes implementing `FieldConditionInterface`: ```php class CustomBusinessRuleCondition implements FieldConditionInterface { public function evaluate(BookingCreateDto $bookingDto, int $participantIndex, array $formData): bool { // Custom business logic here return true; } public function getDependentFields(): array { return ['fieldThatTriggersThisCondition']; } public function getDescription(): string { return 'Custom business rule description'; } } ``` This system provides a powerful, maintainable foundation for complex conditional field behavior while maintaining clean separation of concerns and extensibility.