2026-01-13 10:46:40 +07:00
|
|
|
export interface ValidationRule {
|
|
|
|
|
required?: boolean
|
|
|
|
|
minLength?: number
|
|
|
|
|
maxLength?: number
|
|
|
|
|
email?: boolean
|
|
|
|
|
pattern?: RegExp
|
|
|
|
|
match?: string
|
|
|
|
|
custom?: (value: string) => string | null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FieldErrors {
|
|
|
|
|
[key: string]: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useFormValidation() {
|
|
|
|
|
const errors = ref<FieldErrors>({})
|
|
|
|
|
|
|
|
|
|
const validateEmail = (email: string): boolean => {
|
|
|
|
|
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
|
|
|
return re.test(email)
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-14 16:47:29 +07:00
|
|
|
const validateField = (value: string, rules: ValidationRule, fieldName: string, formData?: Record<string, string>, messages?: Record<string, string>): string | null => {
|
2026-01-13 10:46:40 +07:00
|
|
|
if (rules.required && !value.trim()) {
|
2026-01-14 16:47:29 +07:00
|
|
|
return messages?.required || `กรุณากรอก${fieldName}`
|
2026-01-13 10:46:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules.minLength && value.length < rules.minLength) {
|
2026-01-14 16:47:29 +07:00
|
|
|
return messages?.minLength || `${fieldName}ต้องมีอย่างน้อย ${rules.minLength} ตัวอักษร`
|
2026-01-13 10:46:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules.maxLength && value.length > rules.maxLength) {
|
2026-01-14 16:47:29 +07:00
|
|
|
return messages?.maxLength || `${fieldName}ต้องไม่เกิน ${rules.maxLength} ตัวอักษร`
|
2026-01-13 10:46:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules.email && value && !validateEmail(value)) {
|
2026-01-14 16:47:29 +07:00
|
|
|
return messages?.email || 'รูปแบบอีเมลไม่ถูกต้อง'
|
2026-01-13 10:46:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules.pattern && value && !rules.pattern.test(value)) {
|
2026-01-14 16:47:29 +07:00
|
|
|
return messages?.pattern || `${fieldName}รูปแบบไม่ถูกต้อง`
|
2026-01-13 10:46:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules.match && formData && value !== formData[rules.match]) {
|
2026-01-14 16:47:29 +07:00
|
|
|
return messages?.match || 'รหัสผ่านไม่ตรงกัน'
|
2026-01-13 10:46:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules.custom) {
|
|
|
|
|
return rules.custom(value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const validate = (
|
|
|
|
|
formData: Record<string, string>,
|
2026-01-14 16:47:29 +07:00
|
|
|
validationRules: Record<string, { rules: ValidationRule; label: string; messages?: Record<string, string> }>
|
2026-01-13 10:46:40 +07:00
|
|
|
): boolean => {
|
|
|
|
|
const newErrors: FieldErrors = {}
|
|
|
|
|
let isValid = true
|
|
|
|
|
|
|
|
|
|
for (const [fieldKey, config] of Object.entries(validationRules)) {
|
2026-01-14 16:47:29 +07:00
|
|
|
const error = validateField(formData[fieldKey] || '', config.rules, config.label, formData, config.messages)
|
2026-01-13 10:46:40 +07:00
|
|
|
if (error) {
|
|
|
|
|
newErrors[fieldKey] = error
|
|
|
|
|
isValid = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errors.value = newErrors
|
|
|
|
|
return isValid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearErrors = () => {
|
|
|
|
|
errors.value = {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearFieldError = (field: string) => {
|
|
|
|
|
if (errors.value[field]) {
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
|
|
|
delete errors.value[field]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
errors,
|
|
|
|
|
validate,
|
|
|
|
|
clearErrors,
|
|
|
|
|
clearFieldError
|
|
|
|
|
}
|
|
|
|
|
}
|