Chat client changes
- Form values shown correct in MessageHistory of Chat client - Improements to CSS - Move css en js to assets directory - Introduce better Personal Contact Form & Professional Contact Form - Start working on actual Selection Specialist
This commit is contained in:
244
eveai_chat_client/static/assets/js/components/DynamicForm.js
Normal file
244
eveai_chat_client/static/assets/js/components/DynamicForm.js
Normal file
@@ -0,0 +1,244 @@
|
||||
export const DynamicForm = {
|
||||
name: 'DynamicForm',
|
||||
created() {
|
||||
// Zorg ervoor dat het icoon geladen wordt als iconManager beschikbaar is
|
||||
if (window.iconManager && this.formData && this.formData.icon) {
|
||||
window.iconManager.loadIcon(this.formData.icon);
|
||||
}
|
||||
},
|
||||
props: {
|
||||
formData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
validator: (formData) => {
|
||||
// Controleer eerst of formData een geldig object is
|
||||
if (!formData || typeof formData !== 'object') {
|
||||
console.error('FormData is niet een geldig object');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Controleer of er een titel of naam is
|
||||
if (!formData.title && !formData.name) {
|
||||
console.error('FormData heeft geen title of name');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Controleer of er velden zijn
|
||||
if (!formData.fields) {
|
||||
console.error('FormData heeft geen fields eigenschap');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Controleer of velden een array of object zijn
|
||||
if (!Array.isArray(formData.fields) && typeof formData.fields !== 'object') {
|
||||
console.error('FormData.fields is geen array of object');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('FormData is geldig:', formData);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
formValues: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
isSubmitting: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideActions: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['submit', 'cancel', 'update:formValues'],
|
||||
data() {
|
||||
return {
|
||||
localFormValues: { ...this.formValues }
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
formValues: {
|
||||
handler(newValues) {
|
||||
// Gebruik een vlag om recursieve updates te voorkomen
|
||||
if (JSON.stringify(newValues) !== JSON.stringify(this.localFormValues)) {
|
||||
this.localFormValues = JSON.parse(JSON.stringify(newValues));
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
localFormValues: {
|
||||
handler(newValues) {
|
||||
// Gebruik een vlag om recursieve updates te voorkomen
|
||||
if (JSON.stringify(newValues) !== JSON.stringify(this.formValues)) {
|
||||
this.$emit('update:formValues', JSON.parse(JSON.stringify(newValues)));
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
'formData.icon': {
|
||||
handler(newIcon) {
|
||||
if (newIcon && window.iconManager) {
|
||||
window.iconManager.loadIcon(newIcon);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSubmit() {
|
||||
// Basic validation
|
||||
const missingFields = [];
|
||||
|
||||
if (Array.isArray(this.formData.fields)) {
|
||||
// Valideer array-gebaseerde velden
|
||||
this.formData.fields.forEach(field => {
|
||||
const fieldId = field.id || field.name;
|
||||
if (field.required) {
|
||||
const value = this.localFormValues[fieldId];
|
||||
if (value === undefined || value === null ||
|
||||
(typeof value === 'string' && !value.trim()) ||
|
||||
(Array.isArray(value) && value.length === 0)) {
|
||||
missingFields.push(field.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Valideer object-gebaseerde velden
|
||||
Object.entries(this.formData.fields).forEach(([fieldId, field]) => {
|
||||
if (field.required) {
|
||||
const value = this.localFormValues[fieldId];
|
||||
if (value === undefined || value === null ||
|
||||
(typeof value === 'string' && !value.trim()) ||
|
||||
(Array.isArray(value) && value.length === 0)) {
|
||||
missingFields.push(field.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const fieldNames = missingFields.join(', ');
|
||||
alert(`De volgende velden zijn verplicht: ${fieldNames}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.$emit('submit', this.localFormValues);
|
||||
},
|
||||
|
||||
handleCancel() {
|
||||
this.$emit('cancel');
|
||||
},
|
||||
|
||||
updateFieldValue(fieldId, value) {
|
||||
this.localFormValues[fieldId] = value;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="dynamic-form" :class="{ 'read-only': readOnly }">
|
||||
<div class="form-header" v-if="formData.title || formData.name || formData.icon" style="margin-bottom: 20px; display: flex; align-items: center;">
|
||||
<div class="form-icon" v-if="formData.icon" style="margin-right: 10px; display: flex; align-items: center;">
|
||||
<span class="material-symbols-outlined" style="font-size: 24px; color: #4285f4;">{{ formData.icon }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-title" style="font-weight: bold; font-size: 1.2em; color: #333;">{{ formData.title || formData.name }}</div>
|
||||
<div v-if="formData.description" class="form-description" style="margin-top: 5px; color: #666; font-size: 0.9em;">{{ formData.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="readOnly" class="form-readonly" style="display: grid; grid-template-columns: 35% 65%; gap: 8px; width: 100%;">
|
||||
<!-- Array-based fields -->
|
||||
<template v-if="Array.isArray(formData.fields)">
|
||||
<template v-for="field in formData.fields" :key="field.id || field.name">
|
||||
<div class="field-label" style="font-weight: 500; color: #555; padding: 4px 0;">{{ field.name }}:</div>
|
||||
<div class="field-value" style="padding: 4px 0;">
|
||||
<template v-if="field.type === 'enum' && (field.allowedValues || field.allowed_values)">
|
||||
{{ localFormValues[field.id || field.name] || field.default || '-' }}
|
||||
</template>
|
||||
<template v-else-if="field.type === 'boolean'">
|
||||
{{ localFormValues[field.id || field.name] ? 'Ja' : 'Nee' }}
|
||||
</template>
|
||||
<template v-else-if="field.type === 'text'">
|
||||
<div class="text-value" style="white-space: pre-wrap;">{{ localFormValues[field.id || field.name] || '-' }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ localFormValues[field.id || field.name] || field.default || '-' }}
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<!-- Object-based fields -->
|
||||
<template v-else>
|
||||
<template v-for="(field, fieldId) in formData.fields" :key="fieldId">
|
||||
<div class="field-label" style="font-weight: 500; color: #555; padding: 4px 0;">{{ field.name }}:</div>
|
||||
<div class="field-value" style="padding: 4px 0;">
|
||||
<template v-if="field.type === 'enum' && (field.allowedValues || field.allowed_values)">
|
||||
{{ localFormValues[fieldId] || field.default || '-' }}
|
||||
</template>
|
||||
<template v-else-if="field.type === 'boolean'">
|
||||
{{ localFormValues[fieldId] ? 'Ja' : 'Nee' }}
|
||||
</template>
|
||||
<template v-else-if="field.type === 'text'">
|
||||
<div class="text-value" style="white-space: pre-wrap;">{{ localFormValues[fieldId] || '-' }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ localFormValues[fieldId] || field.default || '-' }}
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<form v-else @submit.prevent="handleSubmit" novalidate>
|
||||
<div class="form-fields" style="margin-top: 10px;">
|
||||
<template v-if="Array.isArray(formData.fields)">
|
||||
<form-field
|
||||
v-for="field in formData.fields"
|
||||
:key="field.id || field.name"
|
||||
:field-id="field.id || field.name"
|
||||
:field="field"
|
||||
:model-value="localFormValues[field.id || field.name]"
|
||||
@update:model-value="localFormValues[field.id || field.name] = $event"
|
||||
></form-field>
|
||||
</template>
|
||||
<template v-else>
|
||||
<form-field
|
||||
v-for="(field, fieldId) in formData.fields"
|
||||
:key="fieldId"
|
||||
:field-id="fieldId"
|
||||
:field="field"
|
||||
:model-value="localFormValues[fieldId]"
|
||||
@update:model-value="localFormValues[fieldId] = $event"
|
||||
></form-field>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="form-actions" v-if="!hideActions">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:disabled="isSubmitting"
|
||||
:class="{ 'loading': isSubmitting }"
|
||||
>
|
||||
<span v-if="isSubmitting" class="spinner"></span>
|
||||
{{ isSubmitting ? 'Verzenden...' : (formData.submitText || 'Versturen') }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
@click="handleCancel"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
{{ formData.cancelText || 'Annuleren' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
Reference in New Issue
Block a user