wip: show pricing
This commit is contained in:
1 parent
6bd483d768
commit
bd5c6359fe
19 files changed
+602
-183
No files matched your search
@@ -39,10 +39,11 @@ abstract class AbstractFieldOptionsProvider implements FieldOptionsProviderInter
|
||||
* @param string $fieldName The name of the field to configure
|
||||
* @param BookingDtoInterface $bookingDto The current booking data for context (create or edit)
|
||||
* @param int $participantIndex The index of the participant being configured
|
||||
* @param array $options Additional options to customize field behavior
|
||||
*
|
||||
* @return array<string, mixed> Symfony form field options, or empty array if field not supported
|
||||
*/
|
||||
public function getFieldOptions(string $fieldName, BookingDtoInterface $bookingDto, int $participantIndex): array
|
||||
public function getFieldOptions(string $fieldName, BookingDtoInterface $bookingDto, int $participantIndex, array $options = []): array
|
||||
{
|
||||
// Check if we have a provider for this field
|
||||
if (false === isset($this->fieldOptionProviders[$fieldName])) {
|
||||
@@ -50,7 +51,7 @@ abstract class AbstractFieldOptionsProvider implements FieldOptionsProviderInter
|
||||
}
|
||||
|
||||
// Execute the provider with current context to generate dynamic options
|
||||
return $this->fieldOptionProviders[$fieldName]($bookingDto, $participantIndex);
|
||||
return $this->fieldOptionProviders[$fieldName]($bookingDto, $participantIndex, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,10 +44,11 @@ interface FieldOptionsProviderInterface
|
||||
* @param string $fieldName The name of the field to configure
|
||||
* @param BookingDtoInterface $bookingDto The current booking data for context (create or edit)
|
||||
* @param int $participantIndex The index of the participant being configured
|
||||
* @param array $options Additional options to customize field behavior
|
||||
*
|
||||
* @return array<string, mixed> Symfony form field options, or empty array if field not supported
|
||||
*/
|
||||
public function getFieldOptions(string $fieldName, BookingDtoInterface $bookingDto, int $participantIndex): array;
|
||||
public function getFieldOptions(string $fieldName, BookingDtoInterface $bookingDto, int $participantIndex, array $options = []): array;
|
||||
|
||||
/**
|
||||
* Checks whether a field has option provider support.
|
||||
|
||||
@@ -137,7 +137,11 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
|
||||
foreach ($selectedServices as $selectedService) {
|
||||
if ($this->isServiceValidForParticipant($selectedService, $availableServices, $bookingDto, $participantIndex)) {
|
||||
$validSelections[] = $selectedService;
|
||||
// Convert the selected service ID/data back to the actual Service object
|
||||
$serviceObject = $this->findServiceInAvailableServices($selectedService, $availableServices);
|
||||
if (null !== $serviceObject) {
|
||||
$validSelections[] = $serviceObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,11 @@ class ParticipantBoardFieldHandler extends AbstractParticipantFieldHandler
|
||||
|
||||
foreach ($selectedServices as $selectedService) {
|
||||
if ($this->isServiceValidForParticipant($selectedService, $availableServices, $bookingDto, $participantIndex)) {
|
||||
$validSelections[] = $selectedService;
|
||||
// Convert the selected service ID/data back to the actual Service object
|
||||
$serviceObject = $this->findServiceInAvailableServices($selectedService, $availableServices);
|
||||
if (null !== $serviceObject) {
|
||||
$validSelections[] = $serviceObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,11 @@ class ParticipantCoursesFieldHandler extends AbstractParticipantFieldHandler
|
||||
|
||||
foreach ($selectedServices as $selectedService) {
|
||||
if ($this->isServiceValidForParticipant($selectedService, $availableServices, $bookingDto, $participantIndex)) {
|
||||
$validSelections[] = $selectedService;
|
||||
// Convert the selected service ID/data back to the actual Service object
|
||||
$serviceObject = $this->findServiceInAvailableServices($selectedService, $availableServices);
|
||||
if (null !== $serviceObject) {
|
||||
$validSelections[] = $serviceObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace App\Form\Service;
|
||||
|
||||
use App\BusProNet\Model\Service;
|
||||
use App\Form\Model\BookingDtoInterface;
|
||||
use App\Form\Model\ParticipantDto;
|
||||
use App\Form\Service\Contract\ParticipantFieldHandlerInterface;
|
||||
|
||||
/**
|
||||
@@ -17,7 +18,7 @@ use App\Form\Service\Contract\ParticipantFieldHandlerInterface;
|
||||
*/
|
||||
class ParticipantFieldHandlerRegistry
|
||||
{
|
||||
/** @var ParticipantFieldHandlerInterface[] Registered handlers indexed by field name */
|
||||
/** @var array<string, ParticipantFieldHandlerInterface> Registered handlers indexed by field name */
|
||||
private array $handlers = [];
|
||||
|
||||
/** @var string[]|null Cached array of handler names sorted by dependency order */
|
||||
@@ -274,11 +275,11 @@ class ParticipantFieldHandlerRegistry
|
||||
* been processed by checking against registered handlers.
|
||||
*
|
||||
* @param array<string, mixed> $participantData The submitted participant data
|
||||
* @param object $participant The cleaned participant DTO
|
||||
* @param ParticipantDto $participant The cleaned participant DTO
|
||||
*
|
||||
* @return array<string, mixed> Updated participant data with synchronized field values
|
||||
*/
|
||||
private function syncParticipantData(array $participantData, object $participant): array
|
||||
private function syncParticipantData(array $participantData, ParticipantDto $participant): array
|
||||
{
|
||||
// Sync fields for all registered handlers
|
||||
foreach ($this->handlers as $fieldName => $handler) {
|
||||
|
||||
@@ -69,7 +69,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
protected function registerFieldOptionProviders(): void
|
||||
{
|
||||
// Room assignment field provider (only available for create workflow)
|
||||
$this->fieldOptionProviders['assignedRoomId'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['assignedRoomId'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Zimmer',
|
||||
'placeholder' => 'Bitte wählen',
|
||||
// Use factory to create context-aware choice loader that:
|
||||
@@ -86,7 +86,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
];
|
||||
|
||||
// Courses field provider - provides age-appropriate courses from travel data
|
||||
$this->fieldOptionProviders['courses'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['courses'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Kurse',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
@@ -97,11 +97,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
$participantIndex
|
||||
),
|
||||
'choice_value' => 'id',
|
||||
'choice_label' => 'label',
|
||||
'choice_label' => fn (?Service $service) => $this->formatServiceLabelWithPrice($service),
|
||||
];
|
||||
|
||||
// Additional services field provider - provides age-appropriate additional services with mandatory pre-selection
|
||||
$this->fieldOptionProviders['additionalServices'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['additionalServices'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Zusatzleistungen',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
@@ -112,7 +112,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
$participantIndex
|
||||
),
|
||||
'choice_value' => 'id',
|
||||
'choice_label' => 'label',
|
||||
'choice_label' => fn (?Service $service) => $this->formatServiceLabelWithPrice($service),
|
||||
'choice_attr' => function (?Service $service) {
|
||||
if (null === $service) {
|
||||
return [];
|
||||
@@ -133,7 +133,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
];
|
||||
|
||||
// Board field provider - provides age-appropriate board options from travel data
|
||||
$this->fieldOptionProviders['board'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['board'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Verpflegung',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
@@ -144,11 +144,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
$participantIndex
|
||||
),
|
||||
'choice_value' => 'id',
|
||||
'choice_label' => 'label',
|
||||
'choice_label' => fn (?Service $service) => $this->formatServiceLabelWithPrice($service),
|
||||
];
|
||||
|
||||
// Rentals field provider - provides age-appropriate rental options from travel data filtered by date range
|
||||
$this->fieldOptionProviders['rentals'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['rentals'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Leihmaterial',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
@@ -159,11 +159,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
$participantIndex
|
||||
),
|
||||
'choice_value' => 'id',
|
||||
'choice_label' => 'label',
|
||||
'choice_label' => fn (?Service $service) => $this->formatServiceLabelWithPrice($service),
|
||||
];
|
||||
|
||||
// Skipass field provider - provides age-appropriate skipass options from travel data filtered by date range
|
||||
$this->fieldOptionProviders['skiPass'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['skiPass'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Skipass',
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
@@ -174,11 +174,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
$participantIndex
|
||||
),
|
||||
'choice_value' => 'id',
|
||||
'choice_label' => 'label',
|
||||
'choice_label' => fn (?Service $service) => $this->formatServiceLabelWithPrice($service),
|
||||
];
|
||||
|
||||
// Room remarks field provider - provides textarea for room-specific remarks (only for 'mbz' rooms)
|
||||
$this->fieldOptionProviders['remarksRoom'] = fn (BookingDtoInterface $bookingDto, int $participantIndex) => [
|
||||
$this->fieldOptionProviders['remarksRoom'] = fn (BookingDtoInterface $bookingDto, int $participantIndex, array $options = []) => [
|
||||
'label' => 'Wünsche oder Anmerkungen zum Zimmer',
|
||||
'required' => false,
|
||||
'clean_xss' => true,
|
||||
@@ -199,6 +199,26 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
// ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats service label with pricing information.
|
||||
*
|
||||
* @param Service|null $service The service to format
|
||||
*
|
||||
* @return string The formatted label
|
||||
*/
|
||||
private function formatServiceLabelWithPrice(?Service $service): string
|
||||
{
|
||||
if (null === $service) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $service->price || 0.0 === $service->price) {
|
||||
return $service->label;
|
||||
}
|
||||
|
||||
return sprintf('%s (€%s)', $service->label, number_format($service->price, 2, ',', '.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters services based on participant's age constraints.
|
||||
*
|
||||
|
||||
@@ -79,7 +79,11 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
|
||||
foreach ($selectedServices as $selectedService) {
|
||||
if ($this->isServiceValidForParticipant($selectedService, $availableServices, $bookingDto, $participantIndex)) {
|
||||
$validSelections[] = $selectedService;
|
||||
// Convert the selected service ID/data back to the actual Service object
|
||||
$serviceObject = $this->findServiceInAvailableServices($selectedService, $availableServices);
|
||||
if (null !== $serviceObject) {
|
||||
$validSelections[] = $serviceObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user