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

This commit is contained in:
twwu
2025-04-27 09:56:48 +08:00
parent 7deb44f864
commit d1f0e6e5c2
3 changed files with 83 additions and 10 deletions

View 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 }) => {

View 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)
}