fix: compact options layout, consistent ImageUploadField across app

- Replace card-based multi-line options with compact single-line rows
  (grip + label + description + delete all on one row)
- Standardize event registration appearance page on ImageUploadField
  (was VFileInput + manual preview, now consistent with email branding)
- Fix EmailBrandingTab logoUrl ref to properly handle null from
  ImageUploadField, ensuring existing image preview works on page load

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 19:15:03 +02:00
parent 6a8d21a5b6
commit b647d2827a
4 changed files with 96 additions and 172 deletions

View File

@@ -323,46 +323,39 @@ defineExpose({ setErrors })
<div
v-for="(option, index) in form.options"
:key="index"
class="mb-3"
class="mb-2"
>
<VCard
variant="outlined"
class="pa-3"
>
<div class="d-flex align-start gap-2">
<VIcon
icon="tabler-grip-vertical"
class="mt-2 text-medium-emphasis"
style="cursor: grab;"
/>
<div class="flex-grow-1">
<AppTextField
v-model="option.label"
:placeholder="`Optie ${index + 1}`"
density="compact"
hide-details="auto"
class="mb-2"
/>
<AppTextField
v-model="option.description"
label="Beschrijving (optioneel)"
density="compact"
placeholder="Korte toelichting die onder de optie verschijnt"
counter="200"
maxlength="200"
hide-details="auto"
/>
</div>
<VBtn
icon="tabler-trash"
variant="text"
color="error"
size="small"
class="mt-1"
@click="removeOption(index)"
/>
</div>
</VCard>
<div class="d-flex align-center gap-2">
<VIcon
icon="tabler-grip-vertical"
size="16"
class="text-medium-emphasis flex-shrink-0"
style="cursor: grab;"
/>
<AppTextField
v-model="option.label"
placeholder="Optie"
density="compact"
hide-details
class="flex-grow-1"
style="max-inline-size: 200px;"
/>
<AppTextField
v-model="option.description"
placeholder="Beschrijving (optioneel)"
density="compact"
hide-details
class="flex-grow-1"
/>
<VBtn
icon="tabler-trash"
variant="text"
color="error"
size="x-small"
class="flex-shrink-0"
@click="removeOption(index)"
/>
</div>
</div>
<div

View File

@@ -19,7 +19,7 @@ const form = ref<InstanceType<typeof VForm>>()
const snackbar = ref(false)
const serverErrors = ref<Record<string, string[]>>({})
const logoUrl = ref('')
const logoUrl = ref<string | null>(null)
const primaryColor = ref('#6366F1')
const secondaryColor = ref('#4F46E5')
const footerText = ref('')
@@ -31,7 +31,7 @@ const showSecondaryPicker = ref(false)
watch(settings, s => {
if (s) {
logoUrl.value = s.logo_url ?? ''
logoUrl.value = s.logo_url ?? null
primaryColor.value = s.primary_color ?? '#6366F1'
secondaryColor.value = s.secondary_color ?? '#4F46E5'
footerText.value = s.footer_text ?? ''

View File

@@ -562,46 +562,39 @@ function activate(template: RegistrationFieldTemplate) {
<div
v-for="(option, index) in form.options"
:key="index"
class="mb-3"
class="mb-2"
>
<VCard
variant="outlined"
class="pa-3"
>
<div class="d-flex align-start gap-2">
<VIcon
icon="tabler-grip-vertical"
class="mt-2 text-medium-emphasis"
style="cursor: grab;"
/>
<div class="flex-grow-1">
<AppTextField
v-model="option.label"
:placeholder="`Optie ${index + 1}`"
density="compact"
hide-details="auto"
class="mb-2"
/>
<AppTextField
v-model="option.description"
label="Beschrijving (optioneel)"
density="compact"
placeholder="Korte toelichting die onder de optie verschijnt"
counter="200"
maxlength="200"
hide-details="auto"
/>
</div>
<VBtn
icon="tabler-trash"
variant="text"
color="error"
size="small"
class="mt-1"
@click="removeOption(index)"
/>
</div>
</VCard>
<div class="d-flex align-center gap-2">
<VIcon
icon="tabler-grip-vertical"
size="16"
class="text-medium-emphasis flex-shrink-0"
style="cursor: grab;"
/>
<AppTextField
v-model="option.label"
placeholder="Optie"
density="compact"
hide-details
class="flex-grow-1"
style="max-inline-size: 200px;"
/>
<AppTextField
v-model="option.description"
placeholder="Beschrijving (optioneel)"
density="compact"
hide-details
class="flex-grow-1"
/>
<VBtn
icon="tabler-trash"
variant="text"
color="error"
size="x-small"
class="flex-shrink-0"
@click="removeOption(index)"
/>
</div>
</div>
<div