/** * Production hook for managing production batches, recipes, and scheduling */ import { useState, useEffect, useCallback } from 'react'; import { ProductionService } from '../../services/api/production.service'; import { ProductionBatch, ProductionBatchCreate, ProductionBatchUpdate, Recipe, RecipeCreate, RecipeUpdate, ProductionSchedule, ProductionScheduleCreate, QualityControl, QualityControlCreate } from '../../types/production.types'; import { ApiResponse, PaginatedResponse, QueryParams } from '../../types/api.types'; interface ProductionState { batches: ProductionBatch[]; recipes: Recipe[]; schedules: ProductionSchedule[]; qualityControls: QualityControl[]; isLoading: boolean; error: string | null; pagination: { total: number; page: number; pages: number; limit: number; }; } interface ProductionActions { // Production Batches fetchBatches: (params?: QueryParams) => Promise; createBatch: (data: ProductionBatchCreate) => Promise; updateBatch: (id: string, data: ProductionBatchUpdate) => Promise; deleteBatch: (id: string) => Promise; getBatch: (id: string) => Promise; startBatch: (id: string) => Promise; completeBatch: (id: string) => Promise; cancelBatch: (id: string, reason: string) => Promise; // Recipes fetchRecipes: (params?: QueryParams) => Promise; createRecipe: (data: RecipeCreate) => Promise; updateRecipe: (id: string, data: RecipeUpdate) => Promise; deleteRecipe: (id: string) => Promise; getRecipe: (id: string) => Promise; duplicateRecipe: (id: string, name: string) => Promise; // Production Scheduling fetchSchedules: (params?: QueryParams) => Promise; createSchedule: (data: ProductionScheduleCreate) => Promise; updateSchedule: (id: string, data: Partial) => Promise; deleteSchedule: (id: string) => Promise; getCapacityAnalysis: (date: string) => Promise; // Quality Control fetchQualityControls: (params?: QueryParams) => Promise; createQualityControl: (data: QualityControlCreate) => Promise; updateQualityControl: (id: string, data: Partial) => Promise; // Analytics getProductionAnalytics: (startDate?: string, endDate?: string) => Promise; getEfficiencyReport: (period: string) => Promise; getRecipePerformance: (recipeId?: string) => Promise; // Utilities clearError: () => void; refresh: () => Promise; } export const useProduction = (): ProductionState & ProductionActions => { const [state, setState] = useState({ batches: [], recipes: [], schedules: [], qualityControls: [], isLoading: false, error: null, pagination: { total: 0, page: 1, pages: 1, limit: 20, }, }); const productionService = new ProductionService(); // Fetch production batches const fetchBatches = useCallback(async (params?: QueryParams) => { setState(prev => ({ ...prev, isLoading: true, error: null })); try { const response = await productionService.getBatches(params); if (response.success && response.data) { setState(prev => ({ ...prev, batches: Array.isArray(response.data) ? response.data : response.data.items || [], pagination: response.data.pagination || prev.pagination, isLoading: false, })); } else { setState(prev => ({ ...prev, isLoading: false, error: response.error || 'Error al cargar lotes de producción', })); } } catch (error) { setState(prev => ({ ...prev, isLoading: false, error: 'Error de conexión al servidor', })); } }, [productionService]); // Create production batch const createBatch = useCallback(async (data: ProductionBatchCreate): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.createBatch(data); if (response.success) { await fetchBatches(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al crear lote de producción', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchBatches]); // Update production batch const updateBatch = useCallback(async (id: string, data: ProductionBatchUpdate): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.updateBatch(id, data); if (response.success) { await fetchBatches(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al actualizar lote de producción', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchBatches]); // Delete production batch const deleteBatch = useCallback(async (id: string): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.deleteBatch(id); if (response.success) { setState(prev => ({ ...prev, batches: prev.batches.filter(batch => batch.id !== id), })); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al eliminar lote de producción', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService]); // Get single production batch const getBatch = useCallback(async (id: string): Promise => { try { const response = await productionService.getBatch(id); return response.success ? response.data : null; } catch (error) { console.error('Error fetching batch:', error); return null; } }, [productionService]); // Start production batch const startBatch = useCallback(async (id: string): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.startBatch(id); if (response.success) { await fetchBatches(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al iniciar lote de producción', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchBatches]); // Complete production batch const completeBatch = useCallback(async (id: string): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.completeBatch(id); if (response.success) { await fetchBatches(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al completar lote de producción', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchBatches]); // Cancel production batch const cancelBatch = useCallback(async (id: string, reason: string): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.cancelBatch(id, reason); if (response.success) { await fetchBatches(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al cancelar lote de producción', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchBatches]); // Fetch recipes const fetchRecipes = useCallback(async (params?: QueryParams) => { setState(prev => ({ ...prev, isLoading: true, error: null })); try { const response = await productionService.getRecipes(params); if (response.success && response.data) { setState(prev => ({ ...prev, recipes: Array.isArray(response.data) ? response.data : response.data.items || [], isLoading: false, })); } else { setState(prev => ({ ...prev, isLoading: false, error: response.error || 'Error al cargar recetas', })); } } catch (error) { setState(prev => ({ ...prev, isLoading: false, error: 'Error de conexión al servidor', })); } }, [productionService]); // Create recipe const createRecipe = useCallback(async (data: RecipeCreate): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.createRecipe(data); if (response.success) { await fetchRecipes(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al crear receta', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchRecipes]); // Update recipe const updateRecipe = useCallback(async (id: string, data: RecipeUpdate): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.updateRecipe(id, data); if (response.success) { await fetchRecipes(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al actualizar receta', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchRecipes]); // Delete recipe const deleteRecipe = useCallback(async (id: string): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.deleteRecipe(id); if (response.success) { setState(prev => ({ ...prev, recipes: prev.recipes.filter(recipe => recipe.id !== id), })); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al eliminar receta', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService]); // Get single recipe const getRecipe = useCallback(async (id: string): Promise => { try { const response = await productionService.getRecipe(id); return response.success ? response.data : null; } catch (error) { console.error('Error fetching recipe:', error); return null; } }, [productionService]); // Duplicate recipe const duplicateRecipe = useCallback(async (id: string, name: string): Promise => { setState(prev => ({ ...prev, error: null })); try { const response = await productionService.duplicateRecipe(id, name); if (response.success) { await fetchRecipes(); return true; } else { setState(prev => ({ ...prev, error: response.error || 'Error al duplicar receta', })); return false; } } catch (error) { setState(prev => ({ ...prev, error: 'Error de conexión al servidor', })); return false; } }, [productionService, fetchRecipes]); // Fetch production schedules const fetchSchedules = useCallback(async (params?: QueryParams) => { try { const response = await productionService.getSchedules(params); if (response.success && response.data) { setState(prev => ({ ...prev, schedules: Array.isArray(response.data) ? response.data : response.data.items || [], })); } } catch (error) { console.error('Error fetching schedules:', error); } }, [productionService]); // Create production schedule const createSchedule = useCallback(async (data: ProductionScheduleCreate): Promise => { try { const response = await productionService.createSchedule(data); if (response.success) { await fetchSchedules(); return true; } return false; } catch (error) { console.error('Error creating schedule:', error); return false; } }, [productionService, fetchSchedules]); // Update production schedule const updateSchedule = useCallback(async (id: string, data: Partial): Promise => { try { const response = await productionService.updateSchedule(id, data); if (response.success) { await fetchSchedules(); return true; } return false; } catch (error) { console.error('Error updating schedule:', error); return false; } }, [productionService, fetchSchedules]); // Delete production schedule const deleteSchedule = useCallback(async (id: string): Promise => { try { const response = await productionService.deleteSchedule(id); if (response.success) { setState(prev => ({ ...prev, schedules: prev.schedules.filter(schedule => schedule.id !== id), })); return true; } return false; } catch (error) { console.error('Error deleting schedule:', error); return false; } }, [productionService]); // Get capacity analysis const getCapacityAnalysis = useCallback(async (date: string) => { try { const response = await productionService.getCapacityAnalysis(date); return response.success ? response.data : null; } catch (error) { console.error('Error fetching capacity analysis:', error); return null; } }, [productionService]); // Fetch quality controls const fetchQualityControls = useCallback(async (params?: QueryParams) => { try { const response = await productionService.getQualityControls(params); if (response.success && response.data) { setState(prev => ({ ...prev, qualityControls: Array.isArray(response.data) ? response.data : response.data.items || [], })); } } catch (error) { console.error('Error fetching quality controls:', error); } }, [productionService]); // Create quality control const createQualityControl = useCallback(async (data: QualityControlCreate): Promise => { try { const response = await productionService.createQualityControl(data); if (response.success) { await fetchQualityControls(); return true; } return false; } catch (error) { console.error('Error creating quality control:', error); return false; } }, [productionService, fetchQualityControls]); // Update quality control const updateQualityControl = useCallback(async (id: string, data: Partial): Promise => { try { const response = await productionService.updateQualityControl(id, data); if (response.success) { await fetchQualityControls(); return true; } return false; } catch (error) { console.error('Error updating quality control:', error); return false; } }, [productionService, fetchQualityControls]); // Get production analytics const getProductionAnalytics = useCallback(async (startDate?: string, endDate?: string) => { try { const response = await productionService.getAnalytics(startDate, endDate); return response.success ? response.data : null; } catch (error) { console.error('Error fetching production analytics:', error); return null; } }, [productionService]); // Get efficiency report const getEfficiencyReport = useCallback(async (period: string) => { try { const response = await productionService.getEfficiencyReport(period); return response.success ? response.data : null; } catch (error) { console.error('Error fetching efficiency report:', error); return null; } }, [productionService]); // Get recipe performance const getRecipePerformance = useCallback(async (recipeId?: string) => { try { const response = await productionService.getRecipePerformance(recipeId); return response.success ? response.data : null; } catch (error) { console.error('Error fetching recipe performance:', error); return null; } }, [productionService]); // Clear error const clearError = useCallback(() => { setState(prev => ({ ...prev, error: null })); }, []); // Refresh all data const refresh = useCallback(async () => { await Promise.all([ fetchBatches(), fetchRecipes(), fetchSchedules(), ]); }, [fetchBatches, fetchRecipes, fetchSchedules]); // Initialize data on mount useEffect(() => { refresh(); }, []); return { ...state, fetchBatches, createBatch, updateBatch, deleteBatch, getBatch, startBatch, completeBatch, cancelBatch, fetchRecipes, createRecipe, updateRecipe, deleteRecipe, getRecipe, duplicateRecipe, fetchSchedules, createSchedule, updateSchedule, deleteSchedule, getCapacityAnalysis, fetchQualityControls, createQualityControl, updateQualityControl, getProductionAnalytics, getEfficiencyReport, getRecipePerformance, clearError, refresh, }; };