diff --git a/frontend/components/DataInputRedesigned.tsx b/frontend/components/DataInputRedesigned.tsx index 016696f..ca9490b 100644 --- a/frontend/components/DataInputRedesigned.tsx +++ b/frontend/components/DataInputRedesigned.tsx @@ -1,12 +1,11 @@ // components/DataInputRedesigned.tsx -// Interfaz de entrada de datos rediseñada y organizada +// Interfaz de entrada de datos simplificada import React, { useState } from 'react'; import { motion } from 'framer-motion'; -import { - Download, CheckCircle, AlertCircle, FileText, Database, - UploadCloud, File, Sheet, Loader2, Sparkles, Table, - Info, ExternalLink, X +import { + AlertCircle, FileText, Database, + UploadCloud, File, Loader2, Info, X } from 'lucide-react'; import clsx from 'clsx'; import toast from 'react-hot-toast'; @@ -27,55 +26,23 @@ interface DataInputRedesignedProps { isAnalyzing: boolean; } -const DataInputRedesigned: React.FC = ({ - onAnalyze, - isAnalyzing +const DataInputRedesigned: React.FC = ({ + onAnalyze, + isAnalyzing }) => { - // Estados para datos manuales - const [costPerHour, setCostPerHour] = useState(20); - const [avgCsat, setAvgCsat] = useState(85); - + // Estados para datos manuales - valores vacíos por defecto + const [costPerHour, setCostPerHour] = useState(''); + const [avgCsat, setAvgCsat] = useState(''); + // Estados para mapeo de segmentación const [highValueQueues, setHighValueQueues] = useState(''); const [mediumValueQueues, setMediumValueQueues] = useState(''); const [lowValueQueues, setLowValueQueues] = useState(''); - + // Estados para carga de datos - const [uploadMethod, setUploadMethod] = useState<'file' | 'url' | 'synthetic' | null>(null); const [file, setFile] = useState(null); - const [sheetUrl, setSheetUrl] = useState(''); - const [isGenerating, setIsGenerating] = useState(false); const [isDragging, setIsDragging] = useState(false); - - // Campos CSV requeridos - const csvFields = [ - { name: 'interaction_id', type: 'String único', example: 'call_8842910', required: true }, - { name: 'datetime_start', type: 'DateTime', example: '2024-10-01 09:15:22', required: true }, - { name: 'queue_skill', type: 'String', example: 'Soporte_Nivel1, Ventas', required: true }, - { name: 'channel', type: 'String', example: 'Voice, Chat, WhatsApp', required: true }, - { name: 'duration_talk', type: 'Segundos', example: '345', required: true }, - { name: 'hold_time', type: 'Segundos', example: '45', required: true }, - { name: 'wrap_up_time', type: 'Segundos', example: '30', required: true }, - { name: 'agent_id', type: 'String', example: 'Agente_045', required: true }, - { name: 'transfer_flag', type: 'Boolean', example: 'TRUE / FALSE', required: true }, - { name: 'caller_id', type: 'String (hash)', example: 'Hash_99283', required: false }, - { name: 'csat_score', type: 'Float', example: '4', required: false } - ]; - - const handleDownloadTemplate = () => { - const headers = csvFields.map(f => f.name).join(','); - const exampleRow = csvFields.map(f => f.example).join(','); - const csvContent = `${headers}\n${exampleRow}\n`; - - const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = 'plantilla_beyond_diagnostic.csv'; - link.click(); - - toast.success('Plantilla CSV descargada', { icon: '📥' }); - }; - + const handleFileChange = (selectedFile: File | null) => { if (selectedFile) { const allowedTypes = [ @@ -83,456 +50,263 @@ const DataInputRedesigned: React.FC = ({ 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ]; - if (allowedTypes.includes(selectedFile.type) || - selectedFile.name.endsWith('.csv') || - selectedFile.name.endsWith('.xlsx') || - selectedFile.name.endsWith('.xls')) { + if (allowedTypes.includes(selectedFile.type) || + selectedFile.name.endsWith('.csv') || + selectedFile.name.endsWith('.xlsx') || + selectedFile.name.endsWith('.xls')) { setFile(selectedFile); - setUploadMethod('file'); toast.success(`Archivo "${selectedFile.name}" cargado`, { icon: '📄' }); } else { - toast.error('Tipo de archivo no válido. Sube un CSV.', { icon: '❌' }); + toast.error('Tipo de archivo no válido. Sube un CSV o Excel.', { icon: '❌' }); } } }; - + const onDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(true); }; - + const onDragLeave = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); }; - + const onDrop = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); - + const droppedFile = e.dataTransfer.files[0]; if (droppedFile) { handleFileChange(droppedFile); } }; - - const handleGenerateSynthetic = () => { - setIsGenerating(true); - setTimeout(() => { - setUploadMethod('synthetic'); - setIsGenerating(false); - toast.success('Datos sintéticos generados para demo', { icon: '✨' }); - }, 1500); + + const canAnalyze = file !== null && costPerHour !== '' && parseFloat(costPerHour) > 0; + + const handleSubmit = () => { + // Preparar segment_mapping + const segmentMapping = (highValueQueues || mediumValueQueues || lowValueQueues) ? { + high_value_queues: (highValueQueues || '').split(',').map(q => q.trim()).filter(q => q), + medium_value_queues: (mediumValueQueues || '').split(',').map(q => q.trim()).filter(q => q), + low_value_queues: (lowValueQueues || '').split(',').map(q => q.trim()).filter(q => q) + } : undefined; + + onAnalyze({ + costPerHour: parseFloat(costPerHour) || 0, + avgCsat: parseFloat(avgCsat) || 0, + segmentMapping, + file: file || undefined, + useSynthetic: false + }); }; - - const handleSheetUrlSubmit = () => { - if (sheetUrl.trim()) { - setUploadMethod('url'); - toast.success('URL de Google Sheets conectada', { icon: '🔗' }); - } else { - toast.error('Introduce una URL válida', { icon: '❌' }); - } - }; - - const canAnalyze = uploadMethod !== null && costPerHour > 0; - + return ( -
+
{/* Sección 1: Datos Manuales */}
-

- - 1. Datos Manuales +

+ + Configuración Manual

-

+

Introduce los parámetros de configuración para tu análisis

- +
{/* Coste por Hora */}
-
- + {/* CSAT Promedio */}
-
- + {/* Segmentación por Cola/Skill */}
-
-

- +
+

Segmentación de Clientes por Cola/Skill - - - Opcional - + (Opcional)

-

- Identifica qué colas/skills corresponden a cada segmento de cliente. Separa múltiples colas con comas. +

+ Identifica qué colas corresponden a cada segmento. Separa múltiples colas con comas.

- +
- {/* High Value */}
-
- - {/* Medium Value */} +
-
- - {/* Low Value */} +
-
- -
-

- - - Nota: Las colas no mapeadas se clasificarán automáticamente como "Medium". - El matching es flexible (no distingue mayúsculas y permite coincidencias parciales). - -

-
+ +

+ + Las colas no mapeadas se clasificarán como "Valor Medio" por defecto. +

- - {/* Sección 2: Datos CSV */} + + {/* Sección 2: Subir Archivo */} -
-

- - 2. Datos CSV (Raw Data de ACD) +
+

+ + Datos CSV

-

- Exporta estos campos desde tu sistema ACD/CTI (Genesys, Avaya, Talkdesk, Zendesk, etc.) +

+ Sube el archivo exportado desde tu sistema ACD/CTI

- - {/* Tabla de campos requeridos */} -
-
- - - - - - - - - - {csvFields.map((field, index) => ( - - - - - - - ))} - -
CampoTipoEjemploObligatorio
{field.name}{field.type}{field.example} - {field.required ? ( - - - Sí - - ) : ( - - - No - - )} -
-

- - {/* Botón de descarga de plantilla */} -
- -

- Descarga una plantilla con la estructura exacta de campos requeridos -

-
- - {/* Opciones de carga */} -
-

Elige cómo proporcionar tus datos:

- - {/* Opción 1: Subir archivo */} -
-
- setUploadMethod('file')} - className="mt-1" - /> -
-

- - Subir Archivo CSV -

- - {uploadMethod === 'file' && ( -
- {file ? ( -
- -
-

{file.name}

-

{(file.size / 1024).toFixed(1)} KB

-
- -
- ) : ( - <> - -

- Arrastra tu archivo aquí o haz click para seleccionar -

- handleFileChange(e.target.files?.[0] || null)} - className="hidden" - id="file-upload" - /> - - - )} -
- )} -
-
-
- - {/* Opción 2: URL Google Sheets -
-
- setUploadMethod('url')} - className="mt-1" - /> -
-

- - Conectar Google Sheets -

- - {uploadMethod === 'url' && ( -
- setSheetUrl(e.target.value)} - placeholder="https://docs.google.com/spreadsheets/d/..." - className="flex-1 px-4 py-2 border-2 border-slate-300 rounded-lg focus:ring-2 focus:ring-[#6D84E3] focus:border-[#6D84E3] transition" - /> - -
- )} + {/* Zona de subida */} +
+ {file ? ( +
+ +
+

{file.name}

+

{(file.size / 1024).toFixed(1)} KB

+
-
- */} - - {/* Opción 3: Datos sintéticos */} -
-
+ ) : ( + <> + +

+ Arrastra tu archivo aquí o haz click para seleccionar +

+

+ Formatos aceptados: CSV, Excel (.xlsx, .xls) +

setUploadMethod('synthetic')} - className="mt-1" + type="file" + accept=".csv,.xlsx,.xls" + onChange={(e) => handleFileChange(e.target.files?.[0] || null)} + className="hidden" + id="file-upload" /> -
-

- - Generar Datos Sintéticos (Demo) -

- - {uploadMethod === 'synthetic' && ( - - )} -
-
-
+ + + )}
- + {/* Botón de análisis */} = ({ className="flex justify-center" > - - {/* Tier Selection */} - -
-

- Selecciona tu Tier de Análisis -

-

- Elige el nivel de profundidad que necesitas para tu diagnóstico -

+
+ {/* Header estilo dashboard */} +
+
+
+

+ AIR EUROPA - Beyond CX Analytics +

+
+ {formatDate()} + +
+
+
- - - - {/* Data Input - Using redesigned component */} + {/* Contenido principal */} +
-
+
);