updated form

This commit is contained in:
firdausfazil 2025-07-09 13:10:00 +08:00
parent fb81306a68
commit 82646cf6a9
3 changed files with 200 additions and 7 deletions

View File

@ -33,7 +33,6 @@ const handleError = () => {
<div class="min-h-screen bg-gray-50 flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full space-y-8">
<div>
<img src="@/assets/img/logo/logo-word.svg" alt="Corrad Logo" class="h-12 mx-auto" />
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
{{ error.statusCode === 404 ? 'Page not found' : 'An error occurred' }}
</h2>

View File

@ -35,7 +35,14 @@
<div class="bg-white rounded-lg shadow p-6">
<div v-for="(form, index) in forms" :key="`content-${index}`" v-show="activeTabIndex === index">
<h2 class="text-xl font-semibold mb-4">{{ form.formName || `Form ${index + 1}` }}</h2>
<p class="text-gray-600 mb-4">{{ form.description || 'Please complete this form step' }}</p>
<p class="text-gray-600 mb-1">{{ form.description || 'Please complete this form step' }}</p>
<!-- Conditional Logic Engine -->
<ConditionalLogicEngine
:form-components="form.formComponents"
:form-data="formData[index]"
@script-generated="handleScriptGenerated"
/>
<!-- Form content -->
<FormKit
@ -187,9 +194,10 @@
</template>
<script setup>
import { onMounted, ref, computed } from 'vue'
import { onMounted, ref, computed, watch, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import RsButton from '~/components/RsButton.vue'
import ConditionalLogicEngine from '~/components/ConditionalLogicEngine.vue'
const loading = ref(false)
const error = ref(null)
@ -238,6 +246,178 @@
)
}
// Utility functions for conditional logic
const getField = (fieldName) => {
const currentFormData = formData.value[activeTabIndex.value] || {}
return currentFormData[fieldName]
}
const showField = (fieldName) => {
const field = document.querySelector(`[name="${fieldName}"]`)
if (field) {
const outerDiv = field.closest('.formkit-outer')
if (outerDiv) {
outerDiv.style.display = ''
outerDiv.classList.remove('hidden')
}
}
}
const hideField = (fieldName) => {
const field = document.querySelector(`[name="${fieldName}"]`)
if (field) {
const outerDiv = field.closest('.formkit-outer')
if (outerDiv) {
outerDiv.style.display = 'none'
outerDiv.classList.add('hidden')
}
}
}
const enableField = (fieldName) => {
const field = document.querySelector(`[name="${fieldName}"]`)
if (field) {
field.removeAttribute('disabled')
const outerDiv = field.closest('.formkit-outer')
if (outerDiv) {
outerDiv.classList.remove('opacity-50', 'pointer-events-none')
}
}
}
const disableField = (fieldName) => {
const field = document.querySelector(`[name="${fieldName}"]`)
if (field) {
field.setAttribute('disabled', 'disabled')
const outerDiv = field.closest('.formkit-outer')
if (outerDiv) {
outerDiv.classList.add('opacity-50', 'pointer-events-none')
}
}
}
const onFieldChange = (fieldName, callback) => {
const field = document.querySelector(`[name="${fieldName}"]`)
if (field) {
// Remove existing listeners first to prevent duplicates
field.removeEventListener('change', callback)
field.removeEventListener('input', callback)
// Add new listeners
field.addEventListener('change', callback)
field.addEventListener('input', callback)
}
}
// Function to evaluate and apply conditional logic for all fields
const evaluateAllFieldConditions = () => {
const currentForm = forms.value[activeTabIndex.value]
if (!currentForm?.formComponents) return
currentForm.formComponents.forEach(component => {
if (component.props?.conditionalLogic?.enabled) {
const { conditions, action, operator = 'and' } = component.props.conditionalLogic
const fieldName = component.props.name
// Evaluate all conditions
const results = conditions.map(condition => {
const fieldValue = getField(condition.field)
switch (condition.operator) {
case 'equals':
return fieldValue === condition.value
case 'not_equals':
return fieldValue !== condition.value
case 'contains':
return String(fieldValue || '').includes(condition.value)
case 'not_contains':
return !String(fieldValue || '').includes(condition.value)
case 'is_empty':
return !fieldValue || fieldValue === ''
case 'is_not_empty':
return fieldValue && fieldValue !== ''
case 'greater_than':
return Number(fieldValue) > Number(condition.value)
case 'less_than':
return Number(fieldValue) < Number(condition.value)
default:
return false
}
})
// Check if conditions are met based on operator
const conditionsMet = operator === 'and'
? results.every(result => result)
: results.some(result => result)
// Apply visibility/state based on conditions
if (conditionsMet) {
if (action === 'show') showField(fieldName)
else if (action === 'hide') hideField(fieldName)
else if (action === 'enable') enableField(fieldName)
else if (action === 'disable') disableField(fieldName)
} else {
if (action === 'show') hideField(fieldName)
else if (action === 'hide') showField(fieldName)
else if (action === 'enable') disableField(fieldName)
else if (action === 'disable') enableField(fieldName)
}
}
})
}
// Watch for form data changes to re-evaluate conditional logic
watch(() => formData.value[activeTabIndex.value], () => {
nextTick(() => {
evaluateAllFieldConditions()
})
}, { deep: true })
// Watch for active tab changes to re-evaluate conditional logic
watch(activeTabIndex, () => {
nextTick(() => {
evaluateAllFieldConditions()
})
})
// Watch for forms data to initialize conditional logic
watch(forms, (newForms) => {
if (newForms.length > 0) {
nextTick(() => {
evaluateAllFieldConditions()
})
}
}, { immediate: true })
// Handle script generated from ConditionalLogicEngine
const handleScriptGenerated = (script) => {
if (!script) return
try {
// Create a function with access to our utility functions
const evalScript = new Function(
'getField',
'showField',
'hideField',
'enableField',
'disableField',
'onFieldChange',
script
)
// Execute the script with our utility functions
evalScript(
getField,
showField,
hideField,
enableField,
disableField,
onFieldChange
)
} catch (err) {
console.error('Error executing conditional logic script:', err)
}
}
// Handle form submission
const handleSubmit = async (formIndex) => {
try {
@ -283,8 +463,21 @@
forms.value = response.forms
console.log(response.forms)
// Initialize formData array with empty objects for each form
formData.value = forms.value.map(() => ({}))
// Initialize formData array with default values for each form
formData.value = forms.value.map(form => {
const defaultData = {};
// Set default values for form fields
form.formComponents?.forEach(component => {
// For select fields with options, set first option as default
if (component.type === 'select' && component.props.options?.length > 0) {
defaultData[component.props.name] = component.props.options[0].value;
}
// Add more default value logic for other field types if needed
});
return defaultData;
});
}
} catch (err) {
@ -311,11 +504,11 @@
.grid-preview-container {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
gap: 0.5rem;
}
.grid-preview-container > div {
grid-column: span 12;
grid-column: span 9;
}
/* Apply width classes */

View File

@ -168,6 +168,7 @@ export default defineEventHandler(async (event) => {
timeline: caseInstance.timeline
};
console.log(`response.forms: ${JSON.stringify(response.forms)}`);
return {
success: true,
...response