fix: validation error indication on cards

This commit is contained in:
Björn Fromme
2025-10-23 10:19:18 +02:00
parent 3e54a58b9b
commit 2b272ef789
6 changed files with 208 additions and 17 deletions
@@ -94,8 +94,10 @@ class Step2Controller extends AbstractController
return $this->hxRedirect($request, $this->generateUrl('app_booking_create_step_3'));
}
// Generate cards data
$cardsData = $this->generateAllCardsData($bookingCreateDto);
// Generate cards data with validation state if form was submitted and failed
$cardsData = (true === $form->isSubmitted() && false === $form->isValid())
? $this->participantCardService->getAllCardsDataWithValidation($bookingCreateDto, ['booking_create'])
: $this->generateAllCardsData($bookingCreateDto);
// Calculate summary data
$summaryData = $this->calculateSummaryData($bookingCreateDto);
+64 -2
View File
@@ -5,6 +5,8 @@ declare(strict_types=1);
namespace App\Service;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantEditDto;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* Extracts card display data for participants in card-based booking flows.
@@ -16,13 +18,14 @@ class ParticipantCardDataService
{
public function __construct(
private readonly BookingPriceCalculatorService $priceCalculator,
private readonly ValidatorInterface $validator,
) {
}
/**
* Get card data for a single participant.
*
* @return array{name: string, roomName: string, price: string}
* @return array{name: string, roomName: string, price: string, isCanceled: bool}
*/
public function getCardData(BookingDto $bookingDto, int $index): array
{
@@ -41,17 +44,21 @@ class ParticipantCardDataService
// Calculate and format individual price
$price = $this->getFormattedPrice($bookingDto, $index);
// Check if participant is canceled
$isCanceled = $participant->isCanceled();
return [
'name' => $name,
'roomName' => $roomName,
'price' => $price,
'isCanceled' => $isCanceled,
];
}
/**
* Get card data for all participants.
*
* @return array<int, array{name: string, roomName: string, price: string}>
* @return array<int, array{name: string, roomName: string, price: string, isCanceled: bool}>
*/
public function getAllCardsData(BookingDto $bookingDto): array
{
@@ -121,4 +128,59 @@ class ParticipantCardDataService
return number_format($price, 2, ',', '.').' €';
}
/**
* Get card data for a single participant with validation state.
*
* @return array{name: string, roomName: string, price: string, isCanceled: bool, isValid: bool, errorMessages: array<string>}
*/
public function getCardDataWithValidation(BookingDto $bookingDto, int $index, array $validationGroups): array
{
$participant = $bookingDto->participants[$index] ?? null;
if (null === $participant) {
throw new \InvalidArgumentException(sprintf('Participant at index %d does not exist', $index));
}
// Get basic card data
$cardData = $this->getCardData($bookingDto, $index);
// Wrap participant for validation
$wrapper = new ParticipantEditDto(
participant: $participant,
bookingContext: $bookingDto,
);
// Validate the wrapper DTO
$violations = $this->validator->validate($wrapper, null, $validationGroups);
// Extract validation state
$isValid = 0 === count($violations);
$errorMessages = [];
foreach ($violations as $violation) {
$errorMessages[] = $violation->getMessage();
}
return array_merge($cardData, [
'isValid' => $isValid,
'errorMessages' => $errorMessages,
]);
}
/**
* Get card data for all participants with validation state.
*
* @return array<int, array{name: string, roomName: string, price: string, isCanceled: bool, isValid: bool, errorMessages: array<string>}>
*/
public function getAllCardsDataWithValidation(BookingDto $bookingDto, array $validationGroups): array
{
$cardsData = [];
foreach ($bookingDto->participants as $index => $participant) {
$cardsData[$index] = $this->getCardDataWithValidation($bookingDto, $index, $validationGroups);
}
return $cardsData;
}
}