Improve the frontend 2

This commit is contained in:
Urtzi Alfaro
2025-10-29 06:58:05 +01:00
parent 858d985c92
commit 36217a2729
98 changed files with 6652 additions and 4230 deletions

View File

@@ -13,7 +13,7 @@ import {
useModelPerformance,
useTenantTrainingStatistics
} from '../../../../api/hooks/training';
import { ModelDetailsModal } from '../../../../components/domain/forecasting';
import { ModelDetailsModal, RetrainModelModal } from '../../../../components/domain/forecasting';
import type { IngredientResponse } from '../../../../api/types/inventory';
import type { TrainedModelResponse, SingleProductTrainingRequest } from '../../../../api/types/training';
@@ -47,6 +47,7 @@ const ModelsConfigPage: React.FC = () => {
const [selectedIngredient, setSelectedIngredient] = useState<IngredientResponse | null>(null);
const [selectedModel, setSelectedModel] = useState<TrainedModelResponse | null>(null);
const [showTrainingModal, setShowTrainingModal] = useState(false);
const [showRetrainModal, setShowRetrainModal] = useState(false);
const [showModelDetailsModal, setShowModelDetailsModal] = useState(false);
const [trainingSettings, setTrainingSettings] = useState<Partial<SingleProductTrainingRequest>>({
seasonality_mode: 'additive',
@@ -183,9 +184,38 @@ const ModelsConfigPage: React.FC = () => {
setShowTrainingModal(true);
};
const handleStartRetraining = (ingredient: IngredientResponse) => {
setSelectedIngredient(ingredient);
// Find and set the model for this ingredient
const model = modelStatuses.find(status => status.ingredient.id === ingredient.id)?.model;
if (model) {
setSelectedModel(model);
}
setShowRetrainModal(true);
};
const handleRetrain = async (settings: SingleProductTrainingRequest) => {
if (!selectedIngredient) return;
try {
await trainMutation.mutateAsync({
tenantId,
inventoryProductId: selectedIngredient.id,
request: settings
});
addToast(`Reentrenamiento iniciado para ${selectedIngredient.name}`, { type: 'success' });
setShowRetrainModal(false);
setSelectedIngredient(null);
setSelectedModel(null);
} catch (error) {
addToast('Error al reentrenar el modelo', { type: 'error' });
}
};
if (ingredientsLoading || modelsLoading) {
return (
@@ -238,7 +268,7 @@ const ModelsConfigPage: React.FC = () => {
},
{
title: 'Precisión Promedio',
value: statsError ? 'N/A' : (statistics?.average_accuracy ? `${Number(statistics.average_accuracy).toFixed(1)}%` : 'N/A'),
value: statsError ? 'N/A' : (statistics?.models?.average_accuracy !== undefined && statistics?.models?.average_accuracy !== null ? `${Number(statistics.models.average_accuracy).toFixed(1)}%` : 'N/A'),
icon: TrendingUp,
variant: 'success',
},
@@ -354,7 +384,7 @@ const ModelsConfigPage: React.FC = () => {
...(status.hasModel ? [{
label: 'Reentrenar',
icon: RotateCcw,
onClick: () => handleStartTraining(status.ingredient),
onClick: () => handleStartRetraining(status.ingredient),
priority: 'secondary' as const
}] : [])
]}
@@ -451,6 +481,22 @@ const ModelsConfigPage: React.FC = () => {
model={selectedModel}
/>
)}
{/* Retrain Model Modal */}
{selectedIngredient && (
<RetrainModelModal
isOpen={showRetrainModal}
onClose={() => {
setShowRetrainModal(false);
setSelectedIngredient(null);
setSelectedModel(null);
}}
ingredient={selectedIngredient}
currentModel={selectedModel}
onRetrain={handleRetrain}
isLoading={trainMutation.isPending}
/>
)}
</div>
);
};