Refactor form error handling with type guards, enhance API client configuration, and update implementation plan

- Introduced `isAPIErrorArray` type guard to improve error handling in authentication forms, replacing type assertions for better runtime safety.
- Refactored error handling logic across `RegisterForm`, `LoginForm`, `PasswordResetRequestForm`, and `PasswordResetConfirmForm` for unexpected error fallbacks.
- Updated `next.config.ts` and `.eslintrc.json` to exclude generated API client files from linting and align configuration with latest project structure.
- Added comprehensive documentation on Phase 2 completion in `IMPLEMENTATION_PLAN.md`.
This commit is contained in:
Felipe Cardoso
2025-11-01 01:29:17 +01:00
parent 38eb5313fc
commit c58cce358f
8 changed files with 190 additions and 127 deletions

View File

@@ -16,8 +16,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert } from '@/components/ui/alert';
import { useLogin } from '@/lib/api/hooks/useAuth';
import { getGeneralError, getFieldErrors } from '@/lib/api/errors';
import type { APIError } from '@/lib/api/errors';
import { getGeneralError, getFieldErrors, isAPIErrorArray } from '@/lib/api/errors';
import config from '@/config/app.config';
// ============================================================================
@@ -101,22 +100,25 @@ export function LoginForm({
// Success callback
onSuccess?.();
} catch (error) {
// Handle API errors
const errors = error as APIError[];
// Set general error message
const generalError = getGeneralError(errors);
if (generalError) {
setServerError(generalError);
}
// Set field-specific errors
const fieldErrors = getFieldErrors(errors);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field === 'email' || field === 'password') {
form.setError(field, { message });
// Handle API errors with type guard
if (isAPIErrorArray(error)) {
// Set general error message
const generalError = getGeneralError(error);
if (generalError) {
setServerError(generalError);
}
});
// Set field-specific errors
const fieldErrors = getFieldErrors(error);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field === 'email' || field === 'password') {
form.setError(field, { message });
}
});
} else {
// Unexpected error format
setServerError('An unexpected error occurred. Please try again.');
}
}
};

View File

@@ -16,8 +16,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert } from '@/components/ui/alert';
import { usePasswordResetConfirm } from '@/lib/api/hooks/useAuth';
import { getGeneralError, getFieldErrors } from '@/lib/api/errors';
import type { APIError } from '@/lib/api/errors';
import { getGeneralError, getFieldErrors, isAPIErrorArray } from '@/lib/api/errors';
// ============================================================================
// Validation Schema
@@ -146,22 +145,25 @@ export function PasswordResetConfirmForm({
// Success callback
onSuccess?.();
} catch (error) {
// Handle API errors
const errors = error as APIError[];
// Set general error message
const generalError = getGeneralError(errors);
if (generalError) {
setServerError(generalError);
}
// Set field-specific errors
const fieldErrors = getFieldErrors(errors);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field === 'token' || field === 'new_password') {
form.setError(field, { message });
// Handle API errors with type guard
if (isAPIErrorArray(error)) {
// Set general error message
const generalError = getGeneralError(error);
if (generalError) {
setServerError(generalError);
}
});
// Set field-specific errors
const fieldErrors = getFieldErrors(error);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field === 'token' || field === 'new_password') {
form.setError(field, { message });
}
});
} else {
// Unexpected error format
setServerError('An unexpected error occurred. Please try again.');
}
}
};

View File

@@ -16,8 +16,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert } from '@/components/ui/alert';
import { usePasswordResetRequest } from '@/lib/api/hooks/useAuth';
import { getGeneralError, getFieldErrors } from '@/lib/api/errors';
import type { APIError } from '@/lib/api/errors';
import { getGeneralError, getFieldErrors, isAPIErrorArray } from '@/lib/api/errors';
// ============================================================================
// Validation Schema
@@ -100,22 +99,25 @@ export function PasswordResetRequestForm({
// Success callback
onSuccess?.();
} catch (error) {
// Handle API errors
const errors = error as APIError[];
// Set general error message
const generalError = getGeneralError(errors);
if (generalError) {
setServerError(generalError);
}
// Set field-specific errors
const fieldErrors = getFieldErrors(errors);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field === 'email') {
form.setError(field, { message });
// Handle API errors with type guard
if (isAPIErrorArray(error)) {
// Set general error message
const generalError = getGeneralError(error);
if (generalError) {
setServerError(generalError);
}
});
// Set field-specific errors
const fieldErrors = getFieldErrors(error);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field === 'email') {
form.setError(field, { message });
}
});
} else {
// Unexpected error format
setServerError('An unexpected error occurred. Please try again.');
}
}
};

View File

@@ -16,8 +16,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert } from '@/components/ui/alert';
import { useRegister } from '@/lib/api/hooks/useAuth';
import { getGeneralError, getFieldErrors } from '@/lib/api/errors';
import type { APIError } from '@/lib/api/errors';
import { getGeneralError, getFieldErrors, isAPIErrorArray } from '@/lib/api/errors';
import config from '@/config/app.config';
// ============================================================================
@@ -124,22 +123,25 @@ export function RegisterForm({
// Success callback
onSuccess?.();
} catch (error) {
// Handle API errors
const errors = error as APIError[];
// Set general error message
const generalError = getGeneralError(errors);
if (generalError) {
setServerError(generalError);
}
// Set field-specific errors
const fieldErrors = getFieldErrors(errors);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field in form.getValues()) {
form.setError(field as keyof RegisterFormData, { message });
// Handle API errors with type guard
if (isAPIErrorArray(error)) {
// Set general error message
const generalError = getGeneralError(error);
if (generalError) {
setServerError(generalError);
}
});
// Set field-specific errors
const fieldErrors = getFieldErrors(error);
Object.entries(fieldErrors).forEach(([field, message]) => {
if (field in form.getValues()) {
form.setError(field as keyof RegisterFormData, { message });
}
});
} else {
// Unexpected error format
setServerError('An unexpected error occurred. Please try again.');
}
}
};