Sfoglia il codice sorgente

feat: Implement Zod schema generation for form validation and update form component usage

tags/2.0.0-beta.1
twwu 6 mesi fa
parent
commit
d1f0e6e5c2

+ 15
- 3
web/app/components/base/form/form-scenarios/base/index.tsx Vedi File

@@ -1,7 +1,8 @@
import React from 'react'
import React, { useMemo } from 'react'
import { useAppForm } from '../..'
import BaseField from './field'
import type { BaseFormProps } from './types'
import { generateZodSchema } from './utils'

const BaseForm = <T,>({
initialData,
@@ -9,11 +10,22 @@ const BaseForm = <T,>({
onSubmit,
CustomActions,
}: BaseFormProps<T>) => {
const schema = useMemo(() => {
const schema = generateZodSchema<T>(configurations)
return schema
}, [configurations])

const baseForm = useAppForm({
defaultValues: initialData,
validators: {
onSubmit: ({ value }) => {
console.log('onSubmit', value)
onChange: ({ value }) => {
const result = schema.safeParse(value)
if (!result.success) {
const issues = result.error.issues
const firstIssue = issues[0].message
return firstIssue
}
return undefined
},
},
onSubmit: ({ value }) => {

+ 56
- 0
web/app/components/base/form/form-scenarios/base/utils.ts Vedi File

@@ -0,0 +1,56 @@
import type { ZodSchema, ZodString } from 'zod'
import { z } from 'zod'
import { type BaseConfiguration, BaseVarType } from './types'

export const generateZodSchema = <T>(fields: BaseConfiguration<T>[]) => {
const shape: Record<string, ZodSchema> = {}

fields.forEach((field) => {
let zodType

switch (field.type) {
case BaseVarType.textInput:
zodType = z.string()
break
case BaseVarType.numberInput:
zodType = z.number()
break
case BaseVarType.checkbox:
zodType = z.boolean()
break
case BaseVarType.select:
zodType = z.string()
break
default:
zodType = z.any()
break
}

if (field.required) {
if ([BaseVarType.textInput].includes(field.type))
zodType = (zodType as ZodString).nonempty(`${field.label} is required`)
}
else {
zodType = zodType.optional()
}

if (field.maxLength) {
if ([BaseVarType.textInput].includes(field.type))
zodType = (zodType as ZodString).max(field.maxLength, `${field.label} exceeds max length of ${field.maxLength}`)
}

if (field.min) {
if ([BaseVarType.numberInput].includes(field.type))
zodType = (zodType as ZodString).min(field.min, `${field.label} must be at least ${field.min}`)
}

if (field.max) {
if ([BaseVarType.numberInput].includes(field.type))
zodType = (zodType as ZodString).max(field.max, `${field.label} exceeds max value of ${field.max}`)
}

shape[field.variable] = zodType
})

return z.object(shape)
}

+ 12
- 7
web/app/dev-preview/page.tsx Vedi File

@@ -1,16 +1,17 @@
'use client'
import InputFieldForm from '../components/base/form/form-scenarios/base'
import BaseForm from '../components/base/form/form-scenarios/base'
import { BaseVarType } from '../components/base/form/form-scenarios/base/types'

export default function Page() {
return (
<div className='flex h-screen w-full items-center justify-center p-20'>
<div className='w-[400px] rounded-lg border border-components-panel-border bg-components-panel-bg'>
<InputFieldForm
<BaseForm
initialData={{
type: 'option_1',
variable: 'test',
label: 'Test',
maxLength: 48,
required: true,
}}
configurations={[
@@ -19,14 +20,18 @@ export default function Page() {
variable: 'variable',
label: 'Variable',
required: true,
showConditions: [{
variable: 'type',
value: 'option_1',
}],
showConditions: [],
},
{
type: BaseVarType.textInput,
variable: 'label',
label: 'Label',
required: true,
showConditions: [],
},
{
type: BaseVarType.numberInput,
variable: 'max_length',
variable: 'maxLength',
label: 'Max Length',
required: true,
showConditions: [],

Loading…
Annulla
Salva