121 lines
3.3 KiB
TypeScript
121 lines
3.3 KiB
TypeScript
|
|
/**
|
||
|
|
* Form Validation Utilities
|
||
|
|
* Utilities for applying API validation errors to form fields
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { ApiError } from '@/types/api';
|
||
|
|
import { getValidationErrors, getErrorCategory } from './apiErrorHandler';
|
||
|
|
import type { UseFormSetError, Path } from 'react-hook-form';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Applies API validation errors to react-hook-form fields
|
||
|
|
* @param error - The API error containing validation details
|
||
|
|
* @param setError - react-hook-form's setError function
|
||
|
|
* @param fieldNameMap - Optional mapping from API field names to form field names
|
||
|
|
* @returns true if validation errors were applied, false otherwise
|
||
|
|
*/
|
||
|
|
export function applyApiValidationErrors<T extends Record<string, any>>(
|
||
|
|
error: ApiError | Error | unknown,
|
||
|
|
setError: UseFormSetError<T>,
|
||
|
|
fieldNameMap?: Record<string, keyof T>
|
||
|
|
): boolean {
|
||
|
|
// Check if this is a validation error
|
||
|
|
const apiError = error && typeof error === 'object' && 'message' in error
|
||
|
|
? (error as ApiError)
|
||
|
|
: null;
|
||
|
|
|
||
|
|
if (!apiError) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
const category = getErrorCategory(apiError);
|
||
|
|
if (category !== 'validation') {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Extract validation errors from error.details
|
||
|
|
const validationErrors = getValidationErrors(apiError);
|
||
|
|
|
||
|
|
if (Object.keys(validationErrors).length === 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Apply errors to form fields
|
||
|
|
let appliedCount = 0;
|
||
|
|
for (const [apiFieldName, message] of Object.entries(validationErrors)) {
|
||
|
|
// Map API field name to form field name if mapping provided
|
||
|
|
const formFieldName = (fieldNameMap?.[apiFieldName] || apiFieldName) as Path<T>;
|
||
|
|
|
||
|
|
// Set error on the form field
|
||
|
|
setError(formFieldName, {
|
||
|
|
type: 'server',
|
||
|
|
message: message,
|
||
|
|
});
|
||
|
|
|
||
|
|
appliedCount++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return appliedCount > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gets validation error for a specific field from an API error
|
||
|
|
* @param error - The API error
|
||
|
|
* @param fieldName - The field name to get error for
|
||
|
|
* @param fieldNameMap - Optional mapping from API field names to form field names
|
||
|
|
* @returns Error message for the field, or undefined if no error
|
||
|
|
*/
|
||
|
|
export function getFieldValidationError(
|
||
|
|
error: ApiError | Error | unknown,
|
||
|
|
fieldName: string,
|
||
|
|
fieldNameMap?: Record<string, string>
|
||
|
|
): string | undefined {
|
||
|
|
const apiError = error && typeof error === 'object' && 'message' in error
|
||
|
|
? (error as ApiError)
|
||
|
|
: null;
|
||
|
|
|
||
|
|
if (!apiError) {
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
const category = getErrorCategory(apiError);
|
||
|
|
if (category !== 'validation') {
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
const validationErrors = getValidationErrors(apiError);
|
||
|
|
|
||
|
|
// Check direct field name
|
||
|
|
if (validationErrors[fieldName]) {
|
||
|
|
return validationErrors[fieldName];
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check mapped field name
|
||
|
|
if (fieldNameMap) {
|
||
|
|
for (const [apiFieldName, formFieldName] of Object.entries(fieldNameMap)) {
|
||
|
|
if (formFieldName === fieldName && validationErrors[apiFieldName]) {
|
||
|
|
return validationErrors[apiFieldName];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Checks if an error is a validation error
|
||
|
|
* @param error - The error to check
|
||
|
|
* @returns true if the error is a validation error
|
||
|
|
*/
|
||
|
|
export function isValidationError(error: ApiError | Error | unknown): boolean {
|
||
|
|
const apiError = error && typeof error === 'object' && 'message' in error
|
||
|
|
? (error as ApiError)
|
||
|
|
: null;
|
||
|
|
|
||
|
|
if (!apiError) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return getErrorCategory(apiError) === 'validation';
|
||
|
|
}
|