feat(api): extend registration endpoints with dynamic fields and section preferences

- PublicRegistrationData now returns registration_fields (portal-visible only),
  form toggles, and available_tags for tag_picker fields
- Volunteer registration accepts field_values and section_preferences with
  festival_section_id, processed via existing services
- PortalMe eager-loads fieldValues and sectionPreferences
- Section preferences now use the proper relational table instead of custom_fields JSON

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 23:44:26 +02:00
parent a9dcee0fc7
commit 73c8e6c466
6 changed files with 395 additions and 9 deletions

View File

@@ -19,6 +19,8 @@ final class VolunteerRegistrationService
{
public function __construct(
private readonly PersonIdentityService $identityService,
private readonly RegistrationFormFieldService $registrationFormFieldService,
private readonly PersonSectionPreferenceService $personSectionPreferenceService,
) {}
/**
@@ -62,17 +64,26 @@ final class VolunteerRegistrationService
'driving_licence' => $validated['driving_licence'] ?? false,
'motivation' => $validated['motivation'] ?? null,
'motivation_other' => $validated['motivation_other'] ?? null,
'section_preferences' => collect($validated['section_preferences'] ?? [])
->map(fn ($pref) => [
'section_name' => $pref['section_name'],
'priority' => $pref['priority'],
])->toArray(),
],
]
);
$this->syncAvailabilities($person, $festivalEvent, $validated['availabilities'] ?? []);
if (!empty($validated['field_values'])) {
$this->registrationFormFieldService->upsertPersonValues(
$person,
$validated['field_values']
);
}
if (!empty($validated['section_preferences'])) {
$this->personSectionPreferenceService->replacePreferences(
$person,
$validated['section_preferences']
);
}
if ($user === null) {
$this->detectIdentityMatch($person);
}