From 4ef8e7b1f3e9d656d50a0d6612dc70bf963e8530 Mon Sep 17 00:00:00 2001 From: donpat1to Date: Thu, 30 Oct 2025 21:52:34 +0100 Subject: [PATCH] error handling in frontend together with validation in backend --- frontend/src/services/errorService.ts | 38 ++++++++++ .../src/services/scheduling/useScheduling.ts | 71 ------------------- 2 files changed, 38 insertions(+), 71 deletions(-) create mode 100644 frontend/src/services/errorService.ts delete mode 100644 frontend/src/services/scheduling/useScheduling.ts diff --git a/frontend/src/services/errorService.ts b/frontend/src/services/errorService.ts new file mode 100644 index 0000000..ec51a9a --- /dev/null +++ b/frontend/src/services/errorService.ts @@ -0,0 +1,38 @@ +// frontend/src/services/errorService.ts +export interface ValidationError { + field: string; + message: string; + value?: any; +} + +export interface ApiError { + error: string; + details?: ValidationError[]; + message?: string; +} + +export class ErrorService { + static extractValidationErrors(error: any): ValidationError[] { + if (error?.details && Array.isArray(error.details)) { + return error.details; + } + + // Fallback for different error formats + if (error.message && typeof error.message === 'string') { + return [{ field: 'general', message: error.message }]; + } + + return [{ field: 'general', message: 'An unknown error occurred' }]; + } + + static getFieldErrors(errors: ValidationError[], fieldName: string): string[] { + return errors + .filter(error => error.field === fieldName) + .map(error => error.message); + } + + static getFirstFieldError(errors: ValidationError[], fieldName: string): string | null { + const fieldErrors = this.getFieldErrors(errors, fieldName); + return fieldErrors.length > 0 ? fieldErrors[0] : null; + } +} \ No newline at end of file diff --git a/frontend/src/services/scheduling/useScheduling.ts b/frontend/src/services/scheduling/useScheduling.ts deleted file mode 100644 index 64c41dd..0000000 --- a/frontend/src/services/scheduling/useScheduling.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { useState, useCallback } from 'react'; -import { ScheduleRequest, ScheduleResult } from '../../models/scheduling'; - -export const useScheduling = () => { - const [loading, setLoading] = useState(false); - const [error, setError] = useState(null); - const [result, setResult] = useState(null); - - const generateSchedule = useCallback(async (request: ScheduleRequest) => { - setLoading(true); - setError(null); - - try { - console.log('📤 Sending scheduling request:', { - shiftPlan: request.shiftPlan.name, - employees: request.employees.length, - availabilities: request.availabilities.length, - constraints: request.constraints.length - }); - - const response = await fetch('/api/scheduling/generate-schedule', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(request) - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`Scheduling request failed: ${response.status} ${errorText}`); - } - - const data: ScheduleResult = await response.json(); - - console.log('📥 Received scheduling result:', { - success: data.success, - assignments: Object.keys(data.assignments).length, - violations: data.violations.length, - processingTime: data.processingTime - }); - - setResult(data); - return data; - } catch (err) { - const errorMessage = err instanceof Error ? err.message : 'Unknown scheduling error'; - console.error('❌ Scheduling error:', errorMessage); - setError(errorMessage); - throw err; - } finally { - setLoading(false); - } - }, []); - - const reset = useCallback(() => { - setLoading(false); - setError(null); - setResult(null); - }, []); - - return { - generateSchedule, - loading, - error, - result, - reset - }; -}; - -// Export for backward compatibility -export default useScheduling; \ No newline at end of file