ADD new frontend

This commit is contained in:
Urtzi Alfaro
2025-08-28 10:41:04 +02:00
parent 9c247a5f99
commit 0fd273cfce
492 changed files with 114979 additions and 1632 deletions

View File

@@ -0,0 +1,650 @@
/**
* 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<void>;
createBatch: (data: ProductionBatchCreate) => Promise<boolean>;
updateBatch: (id: string, data: ProductionBatchUpdate) => Promise<boolean>;
deleteBatch: (id: string) => Promise<boolean>;
getBatch: (id: string) => Promise<ProductionBatch | null>;
startBatch: (id: string) => Promise<boolean>;
completeBatch: (id: string) => Promise<boolean>;
cancelBatch: (id: string, reason: string) => Promise<boolean>;
// Recipes
fetchRecipes: (params?: QueryParams) => Promise<void>;
createRecipe: (data: RecipeCreate) => Promise<boolean>;
updateRecipe: (id: string, data: RecipeUpdate) => Promise<boolean>;
deleteRecipe: (id: string) => Promise<boolean>;
getRecipe: (id: string) => Promise<Recipe | null>;
duplicateRecipe: (id: string, name: string) => Promise<boolean>;
// Production Scheduling
fetchSchedules: (params?: QueryParams) => Promise<void>;
createSchedule: (data: ProductionScheduleCreate) => Promise<boolean>;
updateSchedule: (id: string, data: Partial<ProductionScheduleCreate>) => Promise<boolean>;
deleteSchedule: (id: string) => Promise<boolean>;
getCapacityAnalysis: (date: string) => Promise<any>;
// Quality Control
fetchQualityControls: (params?: QueryParams) => Promise<void>;
createQualityControl: (data: QualityControlCreate) => Promise<boolean>;
updateQualityControl: (id: string, data: Partial<QualityControlCreate>) => Promise<boolean>;
// Analytics
getProductionAnalytics: (startDate?: string, endDate?: string) => Promise<any>;
getEfficiencyReport: (period: string) => Promise<any>;
getRecipePerformance: (recipeId?: string) => Promise<any>;
// Utilities
clearError: () => void;
refresh: () => Promise<void>;
}
export const useProduction = (): ProductionState & ProductionActions => {
const [state, setState] = useState<ProductionState>({
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<boolean> => {
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<boolean> => {
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<boolean> => {
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<ProductionBatch | null> => {
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<boolean> => {
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<boolean> => {
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<boolean> => {
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<boolean> => {
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<boolean> => {
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<boolean> => {
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<Recipe | null> => {
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<boolean> => {
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<boolean> => {
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<ProductionScheduleCreate>): Promise<boolean> => {
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<boolean> => {
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<boolean> => {
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<QualityControlCreate>): Promise<boolean> => {
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,
};
};