fix: don't disable room selection field with single option
This commit is contained in:
@@ -10,11 +10,13 @@ use App\BusProNet\Model\Pickup;
|
|||||||
use App\BusProNet\Model\Service;
|
use App\BusProNet\Model\Service;
|
||||||
use App\BusProNet\Utility\DirectionMapper;
|
use App\BusProNet\Utility\DirectionMapper;
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
|
use App\Form\Model\RoomSelectionDto;
|
||||||
use App\Form\Service\Abstract\AbstractFieldOptionsProvider;
|
use App\Form\Service\Abstract\AbstractFieldOptionsProvider;
|
||||||
use App\Form\Service\Factory\ParticipantRoomChoiceLoaderFactory;
|
use App\Form\Service\Factory\ParticipantRoomChoiceLoaderFactory;
|
||||||
use App\Service\BookingPriceCalculatorService;
|
use App\Service\BookingPriceCalculatorService;
|
||||||
use App\Service\InsuranceService;
|
use App\Service\InsuranceService;
|
||||||
use App\Service\ServiceAvailabilityCalculator;
|
use App\Service\ServiceAvailabilityCalculator;
|
||||||
|
use App\Validator\Constraints\RoomSelection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides dynamic field options for participant form fields.
|
* Provides dynamic field options for participant form fields.
|
||||||
@@ -119,35 +121,35 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
|||||||
// Room assignment field provider (available for both create and edit workflows)
|
// Room assignment field provider (available for both create and edit workflows)
|
||||||
$this->fieldOptionProviders['assignedRoomId'] = function (BookingDto $bookingDto, int $participantIndex, array $options = []) {
|
$this->fieldOptionProviders['assignedRoomId'] = function (BookingDto $bookingDto, int $participantIndex, array $options = []) {
|
||||||
$choiceLoader = null;
|
$choiceLoader = null;
|
||||||
$disabled = false;
|
$singleChoice = false;
|
||||||
|
|
||||||
if (BookingDto::MODE_CREATE === $bookingDto->getMode()) {
|
if (BookingDto::MODE_CREATE === $bookingDto->getMode()) {
|
||||||
// Create context: use selected rooms from step 1
|
// Create context: use selected rooms from step 1, filtered by participant age
|
||||||
$choiceLoader = $this->roomChoiceLoaderFactory->createForCreate(
|
$filteredRooms = $this->filterRoomsByParticipantAge(
|
||||||
$bookingDto->getSelectedRooms()
|
$bookingDto->getSelectedRooms(),
|
||||||
|
$bookingDto,
|
||||||
|
$participantIndex
|
||||||
);
|
);
|
||||||
// Disable when only one room type selected (auto-assigned)
|
$choiceLoader = $this->roomChoiceLoaderFactory->createForCreate($filteredRooms);
|
||||||
$disabled = 1 === count($bookingDto->getSelectedRooms());
|
$singleChoice = 1 === count($filteredRooms);
|
||||||
} elseif (BookingDto::MODE_EDIT === $bookingDto->getMode()) {
|
} elseif (BookingDto::MODE_EDIT === $bookingDto->getMode()) {
|
||||||
// Edit context: use already-booked rooms from booking
|
// Edit context: use already-booked rooms from booking
|
||||||
$choiceLoader = $this->roomChoiceLoaderFactory->createForEdit(
|
$choiceLoader = $this->roomChoiceLoaderFactory->createForEdit(
|
||||||
$bookingDto->booking->rooms
|
$bookingDto->booking->rooms
|
||||||
);
|
);
|
||||||
// Disable when only one room in booking (no reassignment needed)
|
$singleChoice = 1 === count($bookingDto->booking->rooms);
|
||||||
$disabled = 1 === count($bookingDto->booking->rooms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'label' => 'Zimmer',
|
'label' => 'Zimmer',
|
||||||
'placeholder' => 'Nicht zugeordnet',
|
// No placeholder when only one room available - the only option is pre-selected
|
||||||
|
'placeholder' => $singleChoice ? false : 'Nicht zugeordnet',
|
||||||
// Use factory to create context-aware choice loader that:
|
// Use factory to create context-aware choice loader that:
|
||||||
// - Shows only available rooms for this participant
|
// - Shows only available rooms for this participant
|
||||||
// - Excludes rooms already assigned to other participants
|
// - Excludes rooms already assigned to other participants
|
||||||
// - Respects room capacity and booking constraints
|
// - Respects room capacity and booking constraints
|
||||||
|
// - Filters Baby rooms for participants over 2 years old
|
||||||
'choice_loader' => $choiceLoader,
|
'choice_loader' => $choiceLoader,
|
||||||
// Make field read-only when only one room type is available
|
|
||||||
// Room is auto-assigned or cannot be changed, no user choice needed
|
|
||||||
'disabled' => $disabled,
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -540,6 +542,54 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
|||||||
// ];
|
// ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters room selections by participant age constraints.
|
||||||
|
*
|
||||||
|
* Baby rooms (code 'Baby') are only available for participants aged 2 years or younger.
|
||||||
|
* Other room types are available for all participants regardless of age.
|
||||||
|
*
|
||||||
|
* @param RoomSelectionDto[] $roomSelections Array of room selections from Step 1
|
||||||
|
* @param BookingDto $bookingDto The booking DTO containing participant and travel data
|
||||||
|
* @param int $participantIndex Index of the participant to evaluate
|
||||||
|
*
|
||||||
|
* @return RoomSelectionDto[] Filtered array of room selections available for this participant
|
||||||
|
*/
|
||||||
|
private function filterRoomsByParticipantAge(array $roomSelections, BookingDto $bookingDto, int $participantIndex): array
|
||||||
|
{
|
||||||
|
$participant = $bookingDto->getParticipant($participantIndex);
|
||||||
|
|
||||||
|
// If no participant or no date of birth, return all rooms (field visibility handles this case)
|
||||||
|
if (null === $participant || null === $participant->dateOfBirth) {
|
||||||
|
return $roomSelections;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate participant's age at travel start date
|
||||||
|
$age = $participant->getAge($bookingDto->travel->dateFrom);
|
||||||
|
if (null === $age) {
|
||||||
|
return $roomSelections;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get available rooms from travel data to look up room codes
|
||||||
|
$availableRooms = $bookingDto->travel->getAvailableRooms();
|
||||||
|
|
||||||
|
return array_filter($roomSelections, function (RoomSelectionDto $roomSelection) use ($availableRooms, $age) {
|
||||||
|
$room = $availableRooms[$roomSelection->roomId] ?? null;
|
||||||
|
|
||||||
|
// Exclude rooms not found in travel data to avoid validation issues
|
||||||
|
if (null === $room) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Baby rooms only available for participants 2 years or younger
|
||||||
|
if (RoomSelection::BABY_ROOM_CODE === $room->code) {
|
||||||
|
return $age <= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other rooms available for all ages
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters rental services by selected skipass duration.
|
* Filters rental services by selected skipass duration.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user