feat(fullstack): Add form element section and stepper
This commit is contained in:
159
legalconsenthub/pages/application-forms/[id]/[sectionIndex].vue
Normal file
159
legalconsenthub/pages/application-forms/[id]/[sectionIndex].vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<UDashboardPanel id="home">
|
||||
<template #header>
|
||||
<UDashboardNavbar title="Home" :ui="{ right: 'gap-3' }">
|
||||
<template #leading>
|
||||
<UDashboardSidebarCollapse />
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
<UDropdownMenu :items="items">
|
||||
<UButton icon="i-lucide-plus" size="md" class="rounded-full" />
|
||||
</UDropdownMenu>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UDashboardToolbar>
|
||||
<template #left> toolbar left </template>
|
||||
</UDashboardToolbar>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<div class="flex flex-col w-full lg:max-w-4xl mx-auto">
|
||||
<UStepper ref="stepper" v-model="activeStepperItemIndex" :items="stepperItems" class="w-full" />
|
||||
<h1 class="text-xl text-pretty font-bold text-highlighted">
|
||||
{{ currentFormElementSection.title }}
|
||||
</h1>
|
||||
<UCard variant="subtle">
|
||||
<FormEngine
|
||||
v-if="applicationForm"
|
||||
v-model="currentFormElementSection.formElements"
|
||||
:application-form-id="applicationForm.id"
|
||||
:disabled="isReadOnly"
|
||||
@click:comments="openComments"
|
||||
/>
|
||||
<div class="flex gap-2 justify-between mt-4">
|
||||
<UButton
|
||||
leading-icon="i-lucide-arrow-left"
|
||||
:disabled="!stepper?.hasPrev"
|
||||
@click="navigateStepper('backward')"
|
||||
>
|
||||
Prev
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
v-if="stepper?.hasNext"
|
||||
trailing-icon="i-lucide-arrow-right"
|
||||
:disabled="!stepper?.hasNext"
|
||||
@click="navigateStepper('forward')"
|
||||
>
|
||||
Next
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="!stepper?.hasNext"
|
||||
trailing-icon="i-lucide-send-horizontal"
|
||||
:disabled="isReadOnly"
|
||||
@click="onSubmit"
|
||||
>
|
||||
Submit
|
||||
</UButton>
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
</template>
|
||||
</UDashboardPanel>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { ApplicationFormDto, FormElementSectionDto } from '~/.api-client'
|
||||
import type { StepperItem } from '@nuxt/ui'
|
||||
|
||||
const { getApplicationFormById, updateApplicationForm } = useApplicationForm()
|
||||
const route = useRoute()
|
||||
const { user } = useAuth()
|
||||
|
||||
const items = [
|
||||
[
|
||||
{
|
||||
label: 'Neuer Mitbestimmungsantrag',
|
||||
icon: 'i-lucide-send',
|
||||
to: '/create'
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
const stepper = useTemplateRef('stepper')
|
||||
const activeStepperItemIndex = ref<number>(0)
|
||||
|
||||
const currentFormElementSection = computed<FormElementSectionDto>(() => {
|
||||
return applicationForm.value?.formElementSections[activeStepperItemIndex.value]
|
||||
})
|
||||
|
||||
watch(activeStepperItemIndex, async (newActiveStepperItem: number) => {
|
||||
activeStepperItemIndex.value = newActiveStepperItem
|
||||
await navigateTo(`/application-forms/${route.params.id}/${newActiveStepperItem}`)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
(_) => {
|
||||
const sectionIndex = parseInt(route.params.sectionIndex[0])
|
||||
activeStepperItemIndex.value = !isNaN(sectionIndex) ? sectionIndex : 0
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const { data, error } = await useAsyncData<ApplicationFormDto>(async () => {
|
||||
return await getApplicationFormById(Array.isArray(route.params.id) ? route.params.id[0] : route.params.id)
|
||||
})
|
||||
|
||||
if (error.value) {
|
||||
throw createError({ statusText: error.value.message })
|
||||
}
|
||||
|
||||
const applicationForm = computed<ApplicationFormDto>({
|
||||
get: () => data?.value as ApplicationFormDto,
|
||||
set: (val: ApplicationFormDto) => {
|
||||
if (val && data.value) {
|
||||
data.value = val
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const isReadOnly = computed(() => {
|
||||
return applicationForm.value?.createdBy.id !== user.value?.id
|
||||
})
|
||||
|
||||
const stepperItems = computed(() => {
|
||||
const stepperItems: StepperItem[] = []
|
||||
applicationForm.value.formElementSections.forEach((section: FormElementSectionDto, index: number, _) => {
|
||||
stepperItems.push({
|
||||
title: section.shortTitle,
|
||||
description: section.description
|
||||
})
|
||||
})
|
||||
return stepperItems
|
||||
})
|
||||
|
||||
async function navigateStepper(direction: 'forward' | 'backward') {
|
||||
if (direction === 'forward') {
|
||||
stepper.value?.next()
|
||||
} else {
|
||||
stepper.value?.prev()
|
||||
}
|
||||
const targetSectionIndex =
|
||||
direction === 'forward' ? activeStepperItemIndex.value + 1 : activeStepperItemIndex.value - 1
|
||||
await navigateTo(`/application-forms/${route.params.id}/${targetSectionIndex}`)
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
if (data?.value) {
|
||||
await updateApplicationForm(data.value.id, data.value)
|
||||
await navigateTo('/')
|
||||
}
|
||||
}
|
||||
|
||||
function openComments(formElementId: string) {
|
||||
console.log('open comments for', formElementId)
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user