// Metadata-driven form renderer. // // Given a form definition slug, fetches the JSON Schema + UI Schema // from the metadata API and renders a fully functional @rjsf form // using the VibeErp theme and custom ERP widgets. import { useEffect, useState } from 'react' import Form from '@rjsf/core' import type { IChangeEvent } from '@rjsf/core' import type { RJSFSchema, UiSchema } from '@rjsf/utils' import validator from '@rjsf/validator-ajv8' import { apiFetch } from '@/api/client' import type { FormDefinition } from '@/types/api' import { vibeWidgets } from '@/components/form-widgets' import { vibeTemplates } from '@/components/form-widgets/vibeErpTheme' import { Loading } from '@/components/Loading' import { ErrorBox } from '@/components/ErrorBox' interface MetadataFormRendererProps { slug: string initialValues?: Record onSubmit?: (values: Record) => void readOnly?: boolean } export function MetadataFormRenderer({ slug, initialValues, onSubmit, readOnly = false, }: MetadataFormRendererProps) { const [def, setDef] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [formData, setFormData] = useState>( initialValues ?? {}, ) useEffect(() => { setLoading(true) setError(null) apiFetch(`/api/v1/_meta/metadata/forms/${slug}`) .then((data) => { setDef(data) if (initialValues) setFormData(initialValues) }) .catch((err: unknown) => { if (err instanceof Error) { setError(err) } else { setError(new Error(String(err))) } }) .finally(() => setLoading(false)) }, [slug, initialValues]) if (loading) return if (error) return if (!def) return const handleChange = (e: IChangeEvent) => { setFormData((e.formData as Record) ?? {}) } const handleSubmit = (e: IChangeEvent) => { onSubmit?.((e.formData as Record) ?? {}) } return (
) }