feat: unique email addresses of participants unless child, cleanup
addresses #869axbn21
This commit is contained in:
@@ -96,10 +96,13 @@ class Step2Controller extends AbstractController
|
||||
return $this->hxRedirect($request, $this->generateUrl('app_booking_create_step_3'));
|
||||
}
|
||||
|
||||
// Extract participant indices with validation errors
|
||||
$participantErrors = [];
|
||||
// Extract participant validation errors
|
||||
$participantErrorIndices = [];
|
||||
$participantErrorMessages = [];
|
||||
if (true === $form->isSubmitted() && false === $form->isValid()) {
|
||||
$participantErrors = $this->extractParticipantErrorIndices($form);
|
||||
$extractedErrors = $this->extractParticipantValidationErrors($form);
|
||||
$participantErrorIndices = $extractedErrors['errorIndices'];
|
||||
$participantErrorMessages = $extractedErrors['errorMessages'];
|
||||
}
|
||||
|
||||
// Generate cards data
|
||||
@@ -117,7 +120,8 @@ class Step2Controller extends AbstractController
|
||||
'cardsData' => $cardsData,
|
||||
'summaryData' => $summaryData,
|
||||
'pricingData' => $summary['pricing'],
|
||||
'participantErrors' => $participantErrors,
|
||||
'participantErrors' => $participantErrorIndices,
|
||||
'participantErrorMessages' => $participantErrorMessages,
|
||||
];
|
||||
|
||||
// HTMX request: render blocks only
|
||||
|
||||
@@ -156,10 +156,13 @@ class IndexController extends AbstractController
|
||||
return $this->hxRedirect($request, $this->generateUrl('app_booking_edit', ['id' => $id]));
|
||||
}
|
||||
|
||||
// Extract participant indices with validation errors
|
||||
// Extract participant validation errors
|
||||
$participantErrors = [];
|
||||
$participantErrorMessages = [];
|
||||
if ($form->isSubmitted() && false === $form->isValid()) {
|
||||
$participantErrors = $this->extractParticipantErrorIndices($form);
|
||||
$extractedErrors = $this->extractParticipantValidationErrors($form);
|
||||
$participantErrors = $extractedErrors['errorIndices'];
|
||||
$participantErrorMessages = $extractedErrors['errorMessages'];
|
||||
}
|
||||
|
||||
// Generate card data for all participants
|
||||
@@ -189,6 +192,7 @@ class IndexController extends AbstractController
|
||||
'isDirty' => $this->fingerprintService->isDirty($bookingDto),
|
||||
'hasValidationErrors' => count($participantErrors) > 0,
|
||||
'participantErrors' => $participantErrors,
|
||||
'participantErrorMessages' => $participantErrorMessages,
|
||||
];
|
||||
|
||||
// If HTMX request, render only blocks to avoid layout duplication
|
||||
|
||||
@@ -13,16 +13,18 @@ namespace App\Controller\Booking\Traits;
|
||||
trait ParticipantValidationTrait
|
||||
{
|
||||
/**
|
||||
* Extracts participant indices that have validation errors.
|
||||
* Extracts participant validation errors from form.
|
||||
*
|
||||
* Parses form errors to identify which participants have validation issues.
|
||||
* Returns an array of participant indices (e.g., [0, 2, 5]).
|
||||
* Returns two arrays:
|
||||
* - errorIndices: Array of participant indices with errors (e.g., [0, 2, 5])
|
||||
* - errorMessages: Map of participant index to error messages (e.g., [0 => ['E-Mail: ...', 'Vorname: ...']])
|
||||
*
|
||||
* @return array<int> Array of participant indices with errors
|
||||
* @return array{errorIndices: array<int>, errorMessages: array<int, array<string>>}
|
||||
*/
|
||||
private function extractParticipantErrorIndices($form): array
|
||||
private function extractParticipantValidationErrors($form): array
|
||||
{
|
||||
$errorIndices = [];
|
||||
$errorMessages = [];
|
||||
$errors = $form->getErrors(true); // Get all errors recursively
|
||||
|
||||
foreach ($errors as $error) {
|
||||
@@ -31,13 +33,66 @@ trait ParticipantValidationTrait
|
||||
continue;
|
||||
}
|
||||
|
||||
// Property paths look like "participants[0].firstName" or "participants[1].email"
|
||||
if (preg_match('/participants\[(\d+)]/', $propertyPath, $matches)) {
|
||||
// Property paths from BookingDto validation look like "participants[0].email"
|
||||
// Note: Using more flexible regex to capture field path after index
|
||||
if (preg_match('/participants\[(\d+)\]\.?(.*)/', (string) $propertyPath, $matches)) {
|
||||
$index = (int) $matches[1];
|
||||
$errorIndices[$index] = true; // Use array key to avoid duplicates
|
||||
$fieldPath = $matches[2] ?? '';
|
||||
$message = $error->getMessage();
|
||||
|
||||
// Mark this participant as having errors
|
||||
$errorIndices[$index] = true;
|
||||
|
||||
// Initialize error messages array for this participant if needed
|
||||
if (false === isset($errorMessages[$index])) {
|
||||
$errorMessages[$index] = [];
|
||||
}
|
||||
|
||||
// Add formatted error message
|
||||
$errorMessages[$index][] = $this->formatErrorMessage($fieldPath, $message);
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($errorIndices);
|
||||
return [
|
||||
'errorIndices' => array_keys($errorIndices),
|
||||
'errorMessages' => $errorMessages,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an error message with field context.
|
||||
*
|
||||
* @param string $fieldPath The field path that has the error (may be empty or nested)
|
||||
* @param string $message The error message
|
||||
*
|
||||
* @return string Formatted error message
|
||||
*/
|
||||
private function formatErrorMessage(string $fieldPath, string $message): string
|
||||
{
|
||||
// If no field path, return just the message (error is on participant level)
|
||||
if ('' === trim($fieldPath)) {
|
||||
return $message;
|
||||
}
|
||||
|
||||
// Extract the first part of the path for nested fields (e.g., "address.street" -> "address")
|
||||
$fieldName = explode('.', $fieldPath)[0];
|
||||
|
||||
// Field name translations for better user understanding
|
||||
$fieldLabels = [
|
||||
'email' => 'E-Mail',
|
||||
'firstName' => 'Vorname',
|
||||
'lastName' => 'Nachname',
|
||||
'dateOfBirth' => 'Geburtsdatum',
|
||||
'assignedRoomId' => 'Zimmer',
|
||||
'skiPass' => 'Skipass',
|
||||
'transportationOutbound' => 'Anreise',
|
||||
'transportationInbound' => 'Rückreise',
|
||||
'mobile' => 'Mobilnummer',
|
||||
'address' => 'Adresse',
|
||||
];
|
||||
|
||||
$fieldLabel = $fieldLabels[$fieldName] ?? $fieldName;
|
||||
|
||||
return sprintf('%s: %s', $fieldLabel, $message);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user