import React, { useState, useRef, useEffect } from 'react'; import { Upload, Brain, CheckCircle, AlertCircle, Download, FileText, Activity, TrendingUp } from 'lucide-react'; import { Button, Card, Badge } from '../../../ui'; import { OnboardingStepProps } from '../OnboardingWizard'; type ProcessingStage = 'upload' | 'validating' | 'analyzing' | 'completed' | 'error'; interface ProcessingResult { // Validation data is_valid: boolean; total_records: number; unique_products: number; product_list: string[]; validation_errors: string[]; validation_warnings: string[]; summary: { date_range: string; total_sales: number; average_daily_sales: number; }; // Analysis data productsIdentified: number; categoriesDetected: number; businessModel: string; confidenceScore: number; recommendations: string[]; } // Unified mock service that handles both validation and analysis const mockDataProcessingService = { processFile: async (file: File, onProgress: (progress: number, stage: string, message: string) => void) => { return new Promise((resolve, reject) => { let progress = 0; const stages = [ { threshold: 20, stage: 'validating', message: 'Validando estructura del archivo...' }, { threshold: 40, stage: 'validating', message: 'Verificando integridad de datos...' }, { threshold: 60, stage: 'analyzing', message: 'Identificando productos únicos...' }, { threshold: 80, stage: 'analyzing', message: 'Analizando patrones de venta...' }, { threshold: 90, stage: 'analyzing', message: 'Generando recomendaciones con IA...' }, { threshold: 100, stage: 'completed', message: 'Procesamiento completado' } ]; const interval = setInterval(() => { if (progress < 100) { progress += 10; const currentStage = stages.find(s => progress <= s.threshold); if (currentStage) { onProgress(progress, currentStage.stage, currentStage.message); } } if (progress >= 100) { clearInterval(interval); // Return combined validation + analysis results resolve({ // Validation results is_valid: true, total_records: Math.floor(Math.random() * 1000) + 100, unique_products: Math.floor(Math.random() * 50) + 10, product_list: ['Pan Integral', 'Croissant', 'Baguette', 'Empanadas', 'Pan de Centeno', 'Medialunas'], validation_errors: [], validation_warnings: [ 'Algunas fechas podrían tener formato inconsistente', '3 productos sin categoría definida' ], summary: { date_range: '2024-01-01 to 2024-12-31', total_sales: 15420.50, average_daily_sales: 42.25 }, // Analysis results productsIdentified: 15, categoriesDetected: 4, businessModel: 'artisan', confidenceScore: 94, recommendations: [ 'Se detectó un modelo de panadería artesanal con producción propia', 'Los productos más vendidos son panes tradicionales y bollería', 'Recomendamos categorizar el inventario por tipo de producto', 'Considera ampliar la línea de productos de repostería' ] }); } }, 400); }); } }; export const DataProcessingStep: React.FC = ({ data, onDataChange, onNext, onPrevious, isFirstStep, isLastStep }) => { const [stage, setStage] = useState(data.processingStage || 'upload'); const [uploadedFile, setUploadedFile] = useState(data.files?.salesData || null); const [progress, setProgress] = useState(data.processingProgress || 0); const [currentMessage, setCurrentMessage] = useState(data.currentMessage || ''); const [results, setResults] = useState(data.processingResults || null); const [dragActive, setDragActive] = useState(false); const fileInputRef = useRef(null); useEffect(() => { // Update parent data when state changes onDataChange({ ...data, processingStage: stage, processingProgress: progress, currentMessage: currentMessage, processingResults: results, files: { ...data.files, salesData: uploadedFile } }); }, [stage, progress, currentMessage, results, uploadedFile]); const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setDragActive(true); }; const handleDragLeave = (e: React.DragEvent) => { e.preventDefault(); setDragActive(false); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setDragActive(false); const files = Array.from(e.dataTransfer.files); if (files.length > 0) { handleFileUpload(files[0]); } }; const handleFileSelect = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { handleFileUpload(e.target.files[0]); } }; const handleFileUpload = async (file: File) => { // Validate file type const validExtensions = ['.csv', '.xlsx', '.xls']; const fileExtension = file.name.toLowerCase().substring(file.name.lastIndexOf('.')); if (!validExtensions.includes(fileExtension)) { alert('Formato de archivo no válido. Usa CSV o Excel (.xlsx, .xls)'); return; } // Check file size (max 10MB) if (file.size > 10 * 1024 * 1024) { alert('El archivo es demasiado grande. Máximo 10MB permitido.'); return; } setUploadedFile(file); setStage('validating'); setProgress(0); try { const result = await mockDataProcessingService.processFile( file, (newProgress, newStage, message) => { setProgress(newProgress); setStage(newStage as ProcessingStage); setCurrentMessage(message); } ); setResults(result); setStage('completed'); } catch (error) { console.error('Processing error:', error); setStage('error'); setCurrentMessage('Error en el procesamiento de datos'); } }; const downloadTemplate = () => { const csvContent = `fecha,producto,cantidad,precio_unitario,precio_total,cliente,canal_venta 2024-01-15,Pan Integral,5,2.50,12.50,Cliente A,Tienda 2024-01-15,Croissant,3,1.80,5.40,Cliente B,Online 2024-01-15,Baguette,2,3.00,6.00,Cliente C,Tienda 2024-01-16,Pan de Centeno,4,2.80,11.20,Cliente A,Tienda 2024-01-16,Empanadas,6,4.50,27.00,Cliente D,Delivery`; const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', 'plantilla_ventas.csv'); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const resetProcess = () => { setStage('upload'); setUploadedFile(null); setProgress(0); setCurrentMessage(''); setResults(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; return (
{/* Improved Upload Stage */} {stage === 'upload' && ( <>
fileInputRef.current?.click()} >
{uploadedFile ? ( <>

¡Perfecto! Archivo listo

📄 {uploadedFile.name}

{(uploadedFile.size / 1024 / 1024).toFixed(2)} MB • Listo para procesar

) : ( <>

Sube tu historial de ventas

Arrastra y suelta tu archivo aquí, o haz clic para seleccionar

{/* Visual indicators */}
📊
CSV
📈
Excel
Hasta 10MB
)}
💡 Formatos aceptados: CSV, Excel (XLSX, XLS) • Tamaño máximo: 10MB
{/* Improved Template Download Section */}

¿Necesitas ayuda con el formato?

Descarga nuestra plantilla Excel con ejemplos y formato correcto para tus datos de ventas

)} {/* Processing Stages */} {(stage === 'validating' || stage === 'analyzing') && (
{stage === 'validating' ? ( ) : ( )}

{stage === 'validating' ? 'Validando datos...' : 'Analizando con IA...'}

{currentMessage}

{/* Progress Bar */}
Progreso {progress}%
{/* Processing Steps */}
= 40 ? 'bg-[var(--color-success)]/10 text-[var(--color-success)]' : 'bg-[var(--bg-secondary)]' }`}> Validación
= 70 ? 'bg-[var(--color-success)]/10 text-[var(--color-success)]' : 'bg-[var(--bg-secondary)]' }`}> Análisis IA
= 100 ? 'bg-[var(--color-success)]/10 text-[var(--color-success)]' : 'bg-[var(--bg-secondary)]' }`}> Completo
)} {/* Simplified Results Stage */} {stage === 'completed' && results && (
{/* Success Header */}

¡Procesamiento Completado!

Tus datos han sido procesados exitosamente

{/* Simple Stats Cards */}

{results.total_records}

Registros

{results.productsIdentified}

Productos

{results.confidenceScore}%

Confianza

{results.businessModel === 'artisan' ? 'Artesanal' : results.businessModel === 'retail' ? 'Retail' : 'Híbrido'}

Modelo

)} {/* Error State */} {stage === 'error' && (

Error en el procesamiento

{currentMessage}

)}
); };