feat: HEADING field type for registration forms — replace section property with structural field

Replace the per-field `section` text property with a dedicated HEADING field type that
organizers add as a separate block for visual grouping. Also fixes duplicate heading bug
on portal radio fields, replaces cramped VBtnToggle with VSelect for field width, and
adds grouped field type dropdown with structure/input categories.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 16:40:41 +02:00
parent 9718e27029
commit d57dcdb616
27 changed files with 667 additions and 480 deletions

View File

@@ -115,7 +115,6 @@ final class RegistrationFieldTemplateService
'is_portal_visible' => $template->is_portal_visible,
'is_admin_only' => $template->is_admin_only,
'is_filterable' => $template->is_filterable,
'section' => $template->section,
'help_text' => $template->help_text,
'sort_order' => $maxOrder + 1,
'display_width' => $template->display_width,
@@ -140,21 +139,26 @@ final class RegistrationFieldTemplateService
public static function seedSystemTemplates(Organisation $organisation): void
{
$templates = [
['label' => 'Shirtmaat', 'field_type' => 'select', 'options' => ['XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'], 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 1],
['label' => 'Dieetwensen', 'field_type' => 'multiselect', 'options' => ['Vegetarisch', 'Veganistisch', 'Halal', 'Glutenvrij', 'Lactosevrij', 'Geen pinda\'s', 'Geen noten'], 'is_filterable' => true, 'display_width' => 'full', 'sort_order' => 2],
['label' => 'Vergoeding', 'field_type' => 'radio', 'options' => [
['label' => 'Persoonlijke voorkeuren', 'field_type' => 'heading', 'help_text' => 'Vertel ons wat we over jou moeten weten', 'display_width' => 'full', 'sort_order' => 1],
['label' => 'Shirtmaat', 'field_type' => 'select', 'options' => ['XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'], 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 2],
['label' => 'Dieetwensen', 'field_type' => 'multiselect', 'options' => ['Vegetarisch', 'Veganistisch', 'Halal', 'Glutenvrij', 'Lactosevrij', 'Geen pinda\'s', 'Geen noten'], 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 3],
['label' => 'Vergoeding', 'field_type' => 'heading', 'help_text' => 'Kies hoe je wilt worden bedankt voor je inzet', 'display_width' => 'full', 'sort_order' => 4],
['label' => 'Vergoedingstype', 'field_type' => 'radio', 'options' => [
['label' => 'Pro Deo', 'description' => 'Je werkt als vrijwilliger zonder financiële vergoeding'],
['label' => 'Entreeticket', 'description' => 'Je ontvangt een gratis festivalticket als dank voor je inzet'],
['label' => 'Vrijwilligersvergoeding', 'description' => 'Je ontvangt een vergoeding conform de vrijwilligersregeling'],
], 'section' => 'Vergoeding', 'display_width' => 'full', 'sort_order' => 3],
['label' => 'Toestemming gegevensverwerking', 'field_type' => 'boolean', 'is_required' => true, 'section' => 'Toestemming', 'help_text' => 'Ik geef toestemming voor de verwerking van mijn persoonsgegevens ten behoeve van de organisatie van dit evenement, conform de Algemene Verordening Gegevensbescherming (AVG).', 'display_width' => 'full', 'sort_order' => 4],
['label' => 'Noodcontact naam', 'field_type' => 'text', 'section' => 'Noodcontact', 'display_width' => 'half', 'sort_order' => 5],
['label' => 'Noodcontact telefoon', 'field_type' => 'text', 'section' => 'Noodcontact', 'display_width' => 'half', 'sort_order' => 6],
['label' => 'EHBO / BHV diploma', 'field_type' => 'boolean', 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 7],
['label' => 'Rijbewijs', 'field_type' => 'boolean', 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 8],
['label' => 'Eerder vrijwilliger geweest', 'field_type' => 'boolean', 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 9],
['label' => 'Certificaten & vaardigheden', 'field_type' => 'tag_picker', 'tag_category' => null, 'is_filterable' => true, 'display_width' => 'full', 'sort_order' => 10],
['label' => 'Opmerkingen', 'field_type' => 'textarea', 'display_width' => 'full', 'sort_order' => 11],
], 'is_required' => true, 'display_width' => 'full', 'sort_order' => 5],
['label' => 'Noodcontact', 'field_type' => 'heading', 'help_text' => 'Wie kunnen we bereiken bij calamiteiten?', 'display_width' => 'full', 'sort_order' => 6],
['label' => 'Noodcontact naam', 'field_type' => 'text', 'display_width' => 'half', 'sort_order' => 7],
['label' => 'Noodcontact telefoon', 'field_type' => 'text', 'display_width' => 'half', 'sort_order' => 8],
['label' => 'Ervaring & vaardigheden', 'field_type' => 'heading', 'help_text' => 'Welke diploma\'s en skills heb je?', 'display_width' => 'full', 'sort_order' => 9],
['label' => 'EHBO / BHV diploma', 'field_type' => 'boolean', 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 10],
['label' => 'Rijbewijs', 'field_type' => 'boolean', 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 11],
['label' => 'Eerder vrijwilliger geweest', 'field_type' => 'boolean', 'is_filterable' => true, 'display_width' => 'half', 'sort_order' => 12],
['label' => 'Certificaten & vaardigheden', 'field_type' => 'tag_picker', 'tag_category' => null, 'is_filterable' => true, 'display_width' => 'full', 'sort_order' => 13],
['label' => 'Aanvullende informatie', 'field_type' => 'heading', 'display_width' => 'full', 'sort_order' => 14],
['label' => 'Toestemming gegevensverwerking', 'field_type' => 'boolean', 'is_required' => true, 'help_text' => 'Ik geef toestemming voor de verwerking van mijn persoonsgegevens ten behoeve van de organisatie van dit evenement, conform de Algemene Verordening Gegevensbescherming (AVG).', 'display_width' => 'full', 'sort_order' => 15],
['label' => 'Opmerkingen', 'field_type' => 'textarea', 'display_width' => 'full', 'sort_order' => 16],
];
foreach ($templates as $data) {