import { FormApi, FieldApi } from '@tanstack/form-core'
import { z } from 'zod'
interface FormData {
username: string
email: string
password: string
passwordConfirm: string
}
const form = new FormApi<FormData>({
defaultValues: {
username: '',
email: '',
password: '',
passwordConfirm: '',
},
})
const usernameField = new FieldApi({
form,
name: 'username',
defaultValue: '',
validators: {
onChange: ({ value }) => {
if (!value) return 'Username is required'
if (value.length < 3) return 'Username must be at least 3 characters'
if (!/^[a-zA-Z0-9_]+$/.test(value)) {
return 'Username can only contain letters, numbers, and underscores'
}
return undefined
},
onChangeAsync: async ({ value, signal }) => {
if (!value || value.length < 3) return undefined
try {
const response = await fetch(
`/api/check-username?username=${value}`,
{ signal }
)
const data = await response.json()
return data.available ? undefined : 'Username already taken'
} catch (error) {
if (signal.aborted) return undefined
return 'Error checking username availability'
}
},
onChangeAsyncDebounceMs: 500,
},
listeners: {
onChange: ({ value }) => {
console.log('Username changed to:', value)
},
onBlur: ({ value }) => {
console.log('Username field blurred with value:', value)
},
},
})
const emailField = new FieldApi({
form,
name: 'email',
validators: {
onChange: z.string().email('Invalid email format'),
},
})
const passwordField = new FieldApi({
form,
name: 'password',
validators: {
onChange: ({ value }) => {
if (!value) return 'Password is required'
if (value.length < 8) return 'Password must be at least 8 characters'
if (!/[A-Z]/.test(value)) return 'Password must contain an uppercase letter'
if (!/[a-z]/.test(value)) return 'Password must contain a lowercase letter'
if (!/[0-9]/.test(value)) return 'Password must contain a number'
return undefined
},
},
})
const passwordConfirmField = new FieldApi({
form,
name: 'passwordConfirm',
validators: {
onChange: ({ value, fieldApi }) => {
const password = fieldApi.form.getFieldValue('password')
if (value !== password) return 'Passwords do not match'
return undefined
},
onChangeListenTo: ['password'],
},
})