feat(app): registration fields management page in event settings
Adds a new settings sub-page for managing dynamic registration form fields per event. Includes sortable field list, create/edit dialog, template picker, and import-from-event functionality. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
141
apps/app/src/components/event/TemplatePickerDialog.vue
Normal file
141
apps/app/src/components/event/TemplatePickerDialog.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<script setup lang="ts">
|
||||
import { useRegistrationFieldTemplates } from '@/composables/api/useRegistrationFieldTemplates'
|
||||
import { useCreateFieldFromTemplate } from '@/composables/api/useRegistrationFormFields'
|
||||
import { FIELD_TYPE_LABELS } from '@/types/registration-field-template'
|
||||
import type { RegistrationFormField } from '@/types/registration-form-field'
|
||||
|
||||
const props = defineProps<{
|
||||
orgId: string
|
||||
eventId: string
|
||||
existingFields: RegistrationFormField[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
added: []
|
||||
}>()
|
||||
|
||||
const modelValue = defineModel<boolean>({ default: false })
|
||||
|
||||
const orgIdRef = computed(() => props.orgId)
|
||||
const eventIdRef = computed(() => props.eventId)
|
||||
|
||||
const { data: templates, isLoading } = useRegistrationFieldTemplates(orgIdRef)
|
||||
const { mutate: createFromTemplate, isPending } = useCreateFieldFromTemplate(eventIdRef)
|
||||
|
||||
const existingSlugs = computed(() =>
|
||||
new Set(props.existingFields.map(f => f.slug)),
|
||||
)
|
||||
|
||||
const activeTemplates = computed(() =>
|
||||
(templates.value ?? []).filter(t => t.is_active),
|
||||
)
|
||||
|
||||
const addingTemplateId = ref<string | null>(null)
|
||||
|
||||
function isAlreadyAdded(slug: string): boolean {
|
||||
return existingSlugs.value.has(slug)
|
||||
}
|
||||
|
||||
function onAdd(templateId: string) {
|
||||
addingTemplateId.value = templateId
|
||||
createFromTemplate(templateId, {
|
||||
onSuccess: () => {
|
||||
addingTemplateId.value = null
|
||||
emit('added')
|
||||
},
|
||||
onError: () => {
|
||||
addingTemplateId.value = null
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VDialog
|
||||
v-model="modelValue"
|
||||
max-width="600"
|
||||
>
|
||||
<VCard title="Veld uit template toevoegen">
|
||||
<VCardText>
|
||||
<VSkeletonLoader
|
||||
v-if="isLoading"
|
||||
type="list-item@3"
|
||||
/>
|
||||
|
||||
<template v-else-if="activeTemplates.length">
|
||||
<VList density="compact">
|
||||
<VListItem
|
||||
v-for="template in activeTemplates"
|
||||
:key="template.id"
|
||||
:disabled="isAlreadyAdded(template.slug)"
|
||||
class="rounded mb-1"
|
||||
:class="{ 'opacity-50': isAlreadyAdded(template.slug) }"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
:icon="isAlreadyAdded(template.slug) ? 'tabler-check' : 'tabler-forms'"
|
||||
size="20"
|
||||
:color="isAlreadyAdded(template.slug) ? 'success' : undefined"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemTitle>
|
||||
{{ template.label }}
|
||||
<span
|
||||
v-if="isAlreadyAdded(template.slug)"
|
||||
class="text-caption text-disabled ms-2"
|
||||
>(al toegevoegd)</span>
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle>
|
||||
{{ FIELD_TYPE_LABELS[template.field_type] ?? template.field_type }}
|
||||
<template v-if="template.section">
|
||||
· {{ template.section }}
|
||||
</template>
|
||||
<template v-if="template.is_required">
|
||||
· Verplicht
|
||||
</template>
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<VBtn
|
||||
v-if="!isAlreadyAdded(template.slug)"
|
||||
size="small"
|
||||
variant="tonal"
|
||||
color="primary"
|
||||
:loading="isPending && addingTemplateId === template.id"
|
||||
:disabled="isPending"
|
||||
@click="onAdd(template.id)"
|
||||
>
|
||||
Toevoegen
|
||||
</VBtn>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="text-center pa-4"
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-forms"
|
||||
size="40"
|
||||
class="mb-3 text-disabled"
|
||||
/>
|
||||
<p class="text-body-2 text-disabled mb-0">
|
||||
Geen actieve templates beschikbaar. Maak eerst templates aan in de organisatie-instellingen.
|
||||
</p>
|
||||
</div>
|
||||
</VCardText>
|
||||
<VCardActions>
|
||||
<VSpacer />
|
||||
<VBtn
|
||||
variant="text"
|
||||
@click="modelValue = false"
|
||||
>
|
||||
Sluiten
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
Reference in New Issue
Block a user