feat(#13): Show form elements depending on other form element values

This commit is contained in:
2025-11-30 18:10:51 +01:00
parent 79fbf7ce1b
commit 9dc690715b
19 changed files with 1187 additions and 116 deletions

View File

@@ -1,5 +1,5 @@
<template>
<template v-for="(formElement, index) in props.modelValue" :key="formElement.id">
<template v-for="(formElement, index) in visibleFormElements" :key="formElement.id">
<div class="group flex py-3 lg:py-4">
<div class="flex-auto">
<p v-if="formElement.title" class="font-semibold">{{ formElement.title }}</p>
@@ -8,7 +8,7 @@
:is="getResolvedComponent(formElement)"
:form-options="formElement.options"
:disabled="props.disabled"
@update:form-options="updateFormOptions($event, index)"
@update:form-options="updateFormOptions($event, formElement.id)"
/>
<TheComment
v-if="applicationFormId && activeFormElement === formElement.id"
@@ -32,7 +32,7 @@
</UDropdownMenu>
</div>
</div>
<USeparator v-if="index < props.modelValue.length - 1" />
<USeparator v-if="index < visibleFormElements.length - 1" />
</template>
</template>
@@ -45,6 +45,7 @@ import { useCommentStore } from '~~/stores/useCommentStore'
const props = defineProps<{
modelValue: FormElementDto[]
visibilityMap: Map<string, boolean>
applicationFormId?: string
disabled?: boolean
}>()
@@ -68,6 +69,10 @@ const route = useRoute()
const activeFormElement = ref('')
const openDropdownId = ref<string | null>(null)
const visibleFormElements = computed(() => {
return props.modelValue.filter((element) => props.visibilityMap.get(element.id) !== false)
})
function handleDropdownToggle(formElementId: string, isOpen: boolean) {
openDropdownId.value = isOpen ? formElementId : null
}
@@ -112,14 +117,15 @@ function getDropdownItems(formElementId: string, formElementPosition: number): D
return [items]
}
function updateFormOptions(formOptions: FormOptionDto[], formElementIndex: number) {
console.log('Updating form options for element index:', formElementIndex, formOptions)
const updatedModelValue = [...props.modelValue]
const currentElement = updatedModelValue[formElementIndex]
if (currentElement) {
updatedModelValue[formElementIndex] = { ...currentElement, options: formOptions }
emit('update:modelValue', updatedModelValue)
}
function updateFormOptions(formOptions: FormOptionDto[], formElementId: string) {
console.log('Updating form options for element ID:', formElementId, formOptions)
const updatedModelValue = props.modelValue.map((element) => {
if (element.id === formElementId) {
return { ...element, options: formOptions }
}
return element
})
emit('update:modelValue', updatedModelValue)
}
function toggleComments(formElementId: string) {

View File

@@ -8,25 +8,31 @@
{{ currentFormElementSection.title }}
</h1>
<template v-if="currentFormElementSection?.formElementSubSections">
<UCard
v-for="subsection in currentFormElementSection.formElementSubSections"
:key="subsection.id"
variant="subtle"
class="mb-6"
>
<div class="mb-4">
<h2 class="text-lg font-semibold text-highlighted">{{ subsection.title }}</h2>
<p v-if="subsection.subtitle" class="text-sm text-dimmed">{{ subsection.subtitle }}</p>
</div>
<UCard
v-for="subsection in visibleSubsections"
:key="subsection.id"
variant="subtle"
class="mb-6"
>
<div class="mb-4">
<h2 class="text-lg font-semibold text-highlighted">{{ subsection.title }}</h2>
<p v-if="subsection.subtitle" class="text-sm text-dimmed">{{ subsection.subtitle }}</p>
</div>
<FormEngine
v-model="subsection.formElements"
:visibility-map="visibilityMap"
:application-form-id="applicationFormId"
:disabled="disabled"
@add:input-form="(position) => handleAddInputForm(position, subsection.id)"
/>
</UCard>
</template>
</UCard>
<UCard v-if="visibleSubsections.length === 0" variant="subtle" class="mb-6">
<div class="text-center py-8 text-dimmed">
<UIcon name="i-lucide-eye-off" class="w-12 h-12 mx-auto mb-3 opacity-50" />
<p>{{ $t('applicationForms.noVisibleElements') }}</p>
</div>
</UCard>
<div class="flex gap-2 justify-between">
<UButton leading-icon="i-lucide-arrow-left" :disabled="!stepper?.hasPrev" @click="handleNavigate('backward')">
@@ -76,6 +82,30 @@ const { stepper, activeStepperItemIndex, stepperItems, currentFormElementSection
computed(() => props.formElementSections)
)
const allFormElements = computed(() => {
return props.formElementSections.flatMap(section =>
section.formElementSubSections?.flatMap(subsection =>
subsection.formElements
) ?? []
)
})
const { evaluateVisibility } = useFormElementVisibility()
const visibilityMap = computed(() => {
return evaluateVisibility(allFormElements.value)
})
const visibleSubsections = computed(() => {
if (!currentFormElementSection.value?.formElementSubSections) {
return []
}
return currentFormElementSection.value.formElementSubSections.filter(subsection => {
return subsection.formElements.some(element => visibilityMap.value.get(element.id) !== false)
})
})
onMounted(() => {
if (props.initialSectionIndex !== undefined) {
activeStepperItemIndex.value = props.initialSectionIndex