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

@@ -1,7 +1,8 @@
<script setup lang="ts">
import { VForm } from 'vuetify/components/VForm'
import EventTabsNav from '@/components/events/EventTabsNav.vue'
import { useUpdateEvent, useUploadEventImage } from '@/composables/api/useEvents'
import ImageUploadField from '@/components/common/ImageUploadField.vue'
import { useUpdateEvent } from '@/composables/api/useEvents'
import { useAuthStore } from '@/stores/useAuthStore'
import type { EventItem, UpdateEventPayload } from '@/types/event'
@@ -24,16 +25,29 @@ const settingsTab = computed(() => {
})
const { mutate: updateEvent, isPending: isUpdating } = useUpdateEvent(orgId, eventId)
const { mutate: uploadImage, isPending: isUploading } = useUploadEventImage(orgId, eventId)
const bannerUrl = ref<string | null>(null)
const logoUrl = ref<string | null>(null)
const welcomeText = ref('')
const showSuccess = ref(false)
const refVForm = ref<VForm>()
function initForm(event: EventItem) {
bannerUrl.value = event.registration_banner_url ?? null
logoUrl.value = event.registration_logo_url ?? null
welcomeText.value = event.registration_welcome_text ?? ''
}
function onBannerChange(url: string | null) {
bannerUrl.value = url
updateEvent({ registration_banner_url: url } as UpdateEventPayload)
}
function onLogoChange(url: string | null) {
logoUrl.value = url
updateEvent({ registration_logo_url: url } as UpdateEventPayload)
}
function onSaveWelcomeText() {
updateEvent(
{ registration_welcome_text: welcomeText.value || null },
@@ -44,19 +58,6 @@ function onSaveWelcomeText() {
},
)
}
function onFileSelected(files: File[], type: 'banner' | 'logo') {
const file = files[0]
if (!file) return
uploadImage({ file, type })
}
function onClearImage(event: EventItem, type: 'banner' | 'logo') {
const field = type === 'banner' ? 'registration_banner_url' : 'registration_logo_url'
updateEvent({ [field]: null } as UpdateEventPayload)
}
</script>
<template>
@@ -104,91 +105,28 @@ function onClearImage(event: EventItem, type: 'banner' | 'logo') {
<VCardText>
<!-- Banner Image -->
<div class="mb-6">
<h6 class="text-subtitle-1 font-weight-medium mb-2">
Bannerafbeelding
</h6>
<p class="text-body-2 text-medium-emphasis mb-3">
Wordt bovenaan het registratieformulier getoond. Aanbevolen: 1200x400px.
</p>
<VImg
v-if="event.registration_banner_url"
:src="event.registration_banner_url"
height="160"
cover
rounded="lg"
class="mb-3"
<ImageUploadField
:model-value="bannerUrl"
label="Bannerafbeelding"
purpose="banner"
hint="Wordt bovenaan het registratieformulier getoond. Aanbevolen: 1200x400px."
:preview-height="160"
@update:model-value="onBannerChange"
/>
<div class="d-flex gap-2">
<VFileInput
accept="image/jpeg,image/png,image/webp"
label="Afbeelding uploaden"
prepend-icon=""
prepend-inner-icon="tabler-upload"
density="compact"
variant="outlined"
hide-details
:loading="isUploading"
class="flex-grow-1"
style="max-inline-size: 350px;"
@update:model-value="(files: File[]) => onFileSelected(files, 'banner')"
/>
<VBtn
v-if="event.registration_banner_url"
variant="outlined"
color="error"
density="compact"
@click="onClearImage(event, 'banner')"
>
Verwijder
</VBtn>
</div>
</div>
<VDivider class="mb-6" />
<!-- Logo Image -->
<div class="mb-6">
<h6 class="text-subtitle-1 font-weight-medium mb-2">
Logo
</h6>
<p class="text-body-2 text-medium-emphasis mb-3">
Wordt in de header van het registratieformulier getoond. Aanbevolen: vierkant, max 200x200px.
</p>
<VAvatar
v-if="event.registration_logo_url"
:image="event.registration_logo_url"
size="80"
rounded="lg"
class="mb-3"
<ImageUploadField
:model-value="logoUrl"
label="Logo"
purpose="logo"
hint="Wordt in de header van het registratieformulier getoond. Aanbevolen: vierkant, max 200x200px."
:preview-height="80"
@update:model-value="onLogoChange"
/>
<div class="d-flex gap-2">
<VFileInput
accept="image/jpeg,image/png,image/webp"
label="Logo uploaden"
prepend-icon=""
prepend-inner-icon="tabler-upload"
density="compact"
variant="outlined"
hide-details
:loading="isUploading"
class="flex-grow-1"
style="max-inline-size: 350px;"
@update:model-value="(files: File[]) => onFileSelected(files, 'logo')"
/>
<VBtn
v-if="event.registration_logo_url"
variant="outlined"
color="error"
density="compact"
@click="onClearImage(event, 'logo')"
>
Verwijder
</VBtn>
</div>
</div>
<VDivider class="mb-6" />