168 lines
5.3 KiB
Vue
168 lines
5.3 KiB
Vue
<template>
|
|
<UDashboardPanel id="home">
|
|
<template #header>
|
|
<UDashboardNavbar title="Home" :ui="{ right: 'gap-3' }">
|
|
<template #leading>
|
|
<UDashboardSidebarCollapse />
|
|
</template>
|
|
|
|
<template #right />
|
|
</UDashboardNavbar>
|
|
|
|
<UDashboardToolbar>
|
|
<template #left />
|
|
</UDashboardToolbar>
|
|
</template>
|
|
|
|
<template #body>
|
|
<div class="flex flex-col gap-4 sm:gap-6 lg:gap-12 w-full lg:max-w-4xl mx-auto">
|
|
Erstelle Forumular für Organisation: {{ selectedOrganization?.name }}
|
|
<UPageCard title="Ampelstatus" variant="naked" orientation="horizontal" class="mb-4">
|
|
{{ ampelStatusEmoji }}
|
|
</UPageCard>
|
|
|
|
<UPageCard variant="subtle">
|
|
<UForm class="space-y-4" :state="{}" @submit="onSubmit">
|
|
<UFormField label="Name">
|
|
<UInput v-if="applicationFormTemplate" v-model="applicationFormTemplate.name" />
|
|
</UFormField>
|
|
<UStepper ref="stepper" v-model="activeStepperItemIndex" :items="stepperItems" class="w-full" />
|
|
<h1 v-if="currentFormElementSection?.title" class="text-xl text-pretty font-bold text-highlighted">
|
|
{{ currentFormElementSection.title }}
|
|
</h1>
|
|
<FormEngine
|
|
v-if="currentFormElementSection?.formElements"
|
|
v-model="currentFormElementSection.formElements"
|
|
/>
|
|
<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" @click="onSubmit"> Submit </UButton>
|
|
</div>
|
|
</UForm>
|
|
</UPageCard>
|
|
</div>
|
|
</template>
|
|
</UDashboardPanel>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ComplianceStatus, type FormElementSectionDto, type PagedApplicationFormDto } from '~/.api-client'
|
|
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
|
|
import type { FormElementId } from '~/types/FormElement'
|
|
import type { StepperItem } from '@nuxt/ui'
|
|
|
|
const { getAllApplicationFormTemplates } = useApplicationFormTemplate()
|
|
const { createApplicationForm } = useApplicationForm()
|
|
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
|
|
const { userDto, selectedOrganization } = useAuth()
|
|
|
|
const stepper = useTemplateRef('stepper')
|
|
const activeStepperItemIndex = ref<number>(0)
|
|
|
|
const currentFormElementSection = computed(
|
|
() => applicationFormTemplate.value?.formElementSections[activeStepperItemIndex.value]
|
|
)
|
|
|
|
watch(activeStepperItemIndex, async (newActiveStepperItem: number) => {
|
|
activeStepperItemIndex.value = newActiveStepperItem
|
|
})
|
|
|
|
const { data, error } = await useAsyncData<PagedApplicationFormDto>(async () => {
|
|
return await getAllApplicationFormTemplates()
|
|
})
|
|
|
|
if (error.value) {
|
|
throw createError({ statusText: error.value.message })
|
|
}
|
|
|
|
const stepperItems = computed(() => {
|
|
const stepperItems: StepperItem[] = []
|
|
if (!applicationFormTemplate.value) {
|
|
return stepperItems
|
|
}
|
|
|
|
applicationFormTemplate.value.formElementSections.forEach((section: FormElementSectionDto) => {
|
|
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 applicationFormTemplate = computed(
|
|
// TODO: Don't select always the first item, allow user to select a template
|
|
() => data?.value?.content[0] ?? undefined
|
|
)
|
|
|
|
const formElements = computed({
|
|
get: () => currentFormElementSection?.value?.formElements ?? [],
|
|
set: (val) => {
|
|
if (val && applicationFormTemplate.value) {
|
|
if (!currentFormElementSection.value) return
|
|
currentFormElementSection.value.formElements = val
|
|
}
|
|
}
|
|
})
|
|
const validationMap = ref<Map<FormElementId, ComplianceStatus> | undefined>()
|
|
const validationStatus = ref<ComplianceStatus>(ComplianceStatus.NonCritical)
|
|
|
|
watch(
|
|
() => formElements,
|
|
(updatedFormElements) => {
|
|
validationMap.value = validateFormElements(updatedFormElements.value)
|
|
validationStatus.value = getHighestComplianceStatus()
|
|
},
|
|
{ deep: true }
|
|
)
|
|
|
|
const ampelStatusEmoji = computed(() => {
|
|
switch (validationStatus.value) {
|
|
case ComplianceStatus.Critical:
|
|
return '🔴'
|
|
case ComplianceStatus.Warning:
|
|
return '🟡'
|
|
case ComplianceStatus.NonCritical:
|
|
return '🟢'
|
|
default:
|
|
return '🟢'
|
|
}
|
|
})
|
|
|
|
async function onSubmit() {
|
|
if (applicationFormTemplate.value) {
|
|
applicationFormTemplate.value.createdBy = userDto.value
|
|
applicationFormTemplate.value.lastModifiedBy = userDto.value
|
|
applicationFormTemplate.value.organizationId = selectedOrganization.value?.id ?? ''
|
|
|
|
await createApplicationForm(applicationFormTemplate.value)
|
|
await navigateTo('/')
|
|
} else {
|
|
console.error('Application form data is undefined')
|
|
}
|
|
}
|
|
</script>
|