import React, { useState, useCallback } from 'react'; import { Button } from '../../../ui/Button'; import { useCurrentTenant } from '../../../../stores/tenant.store'; import { useCreateTrainingJob, useTrainingWebSocket } from '../../../../api/hooks/training'; interface MLTrainingStepProps { onNext: () => void; onPrevious: () => void; onComplete: (data?: any) => void; isFirstStep: boolean; isLastStep: boolean; } interface TrainingProgress { stage: string; progress: number; message: string; currentStep?: string; estimatedTimeRemaining?: number; } export const MLTrainingStep: React.FC = ({ onPrevious, onComplete, isFirstStep }) => { const [trainingProgress, setTrainingProgress] = useState(null); const [isTraining, setIsTraining] = useState(false); const [error, setError] = useState(''); const [jobId, setJobId] = useState(null); const currentTenant = useCurrentTenant(); const createTrainingJob = useCreateTrainingJob(); // Memoized WebSocket callbacks to prevent reconnections const handleProgress = useCallback((data: any) => { setTrainingProgress({ stage: 'training', progress: data.data?.progress || 0, message: data.data?.message || 'Entrenando modelo...', currentStep: data.data?.current_step, estimatedTimeRemaining: data.data?.estimated_time_remaining }); }, []); const handleCompleted = useCallback((_data: any) => { setTrainingProgress({ stage: 'completed', progress: 100, message: 'Entrenamiento completado exitosamente' }); setIsTraining(false); setTimeout(() => { onComplete({ jobId: jobId, success: true, message: 'Modelo entrenado correctamente' }); }, 2000); }, [onComplete, jobId]); const handleError = useCallback((data: any) => { setError(data.data?.error || data.error || 'Error durante el entrenamiento'); setIsTraining(false); setTrainingProgress(null); }, []); const handleStarted = useCallback((_data: any) => { setTrainingProgress({ stage: 'starting', progress: 5, message: 'Iniciando entrenamiento del modelo...' }); }, []); // WebSocket for real-time training progress - only connect when we have a jobId const { isConnected, connectionError } = useTrainingWebSocket( currentTenant?.id || '', jobId || '', undefined, // token will be handled by the service jobId ? { onProgress: handleProgress, onCompleted: handleCompleted, onError: handleError, onStarted: handleStarted } : undefined ); const handleStartTraining = async () => { if (!currentTenant?.id) { setError('No se encontró información del tenant'); return; } setIsTraining(true); setError(''); setTrainingProgress({ stage: 'preparing', progress: 0, message: 'Preparando datos para entrenamiento...' }); try { const response = await createTrainingJob.mutateAsync({ tenantId: currentTenant.id, request: { // Use the exact backend schema - all fields are optional // This will train on all available data } }); setJobId(response.job_id); setTrainingProgress({ stage: 'queued', progress: 10, message: 'Trabajo de entrenamiento en cola...' }); } catch (err) { setError('Error al iniciar el entrenamiento del modelo'); setIsTraining(false); setTrainingProgress(null); } }; const formatTime = (seconds?: number) => { if (!seconds) return ''; if (seconds < 60) { return `${Math.round(seconds)}s`; } else if (seconds < 3600) { return `${Math.round(seconds / 60)}m`; } else { return `${Math.round(seconds / 3600)}h ${Math.round((seconds % 3600) / 60)}m`; } }; return (

Ahora entrenaremos tu modelo de inteligencia artificial utilizando los datos de ventas e inventario que has proporcionado. Este proceso puede tomar varios minutos.

{/* Training Status Card */}
{!isTraining && !trainingProgress && (

Listo para Entrenar

Tu modelo está listo para ser entrenado con los datos proporcionados.

)} {trainingProgress && (
{trainingProgress.stage === 'completed' ? (
) : (
)} {trainingProgress.progress > 0 && trainingProgress.stage !== 'completed' && (
{trainingProgress.progress}%
)}

{trainingProgress.stage === 'completed' ? '¡Entrenamiento Completo!' : 'Entrenando Modelo IA' }

{trainingProgress.message}

{trainingProgress.stage !== 'completed' && (
{trainingProgress.currentStep || 'Procesando...'}
{jobId && ( {isConnected ? '🟢 Conectado' : '🔴 Desconectado'} )} {trainingProgress.estimatedTimeRemaining && ( Tiempo estimado: {formatTime(trainingProgress.estimatedTimeRemaining)} )}
)}
)}
{/* Training Info */}

¿Qué sucede durante el entrenamiento?

  • • Análisis de patrones de ventas históricos
  • • Creación de modelos predictivos de demanda
  • • Optimización de algoritmos de inventario
  • • Validación y ajuste de precisión
{(error || connectionError) && (

{error || connectionError}

)} {/* Actions */}
{!isTraining && !trainingProgress && ( )} {trainingProgress?.stage === 'completed' && ( )}
); };