435 lines
17 KiB
Plaintext
435 lines
17 KiB
Plaintext
import React, { useState } from 'react';
|
|
import { BarChart3, TrendingUp, Target, AlertCircle, CheckCircle, Eye, Download } from 'lucide-react';
|
|
import { Button, Card, Badge } from '../../../../components/ui';
|
|
import { PageHeader } from '../../../../components/layout';
|
|
|
|
const OnboardingAnalysisPage: React.FC = () => {
|
|
const [selectedPeriod, setSelectedPeriod] = useState('30days');
|
|
|
|
const analysisData = {
|
|
onboardingScore: 87,
|
|
completionRate: 92,
|
|
averageTime: '4.2 días',
|
|
stepsCompleted: 15,
|
|
totalSteps: 16,
|
|
dataQuality: 94
|
|
};
|
|
|
|
const stepProgress = [
|
|
{ step: 'Información Básica', completed: true, quality: 95, timeSpent: '25 min' },
|
|
{ step: 'Configuración de Menú', completed: true, quality: 88, timeSpent: '1.2 horas' },
|
|
{ step: 'Datos de Inventario', completed: true, quality: 92, timeSpent: '45 min' },
|
|
{ step: 'Configuración de Horarios', completed: true, quality: 100, timeSpent: '15 min' },
|
|
{ step: 'Integración de Pagos', completed: true, quality: 85, timeSpent: '30 min' },
|
|
{ step: 'Carga de Productos', completed: true, quality: 90, timeSpent: '2.1 horas' },
|
|
{ step: 'Configuración de Personal', completed: true, quality: 87, timeSpent: '40 min' },
|
|
{ step: 'Pruebas del Sistema', completed: false, quality: 0, timeSpent: '-' }
|
|
];
|
|
|
|
const insights = [
|
|
{
|
|
type: 'success',
|
|
title: 'Excelente Progreso',
|
|
description: 'Has completado el 94% del proceso de configuración inicial',
|
|
recommendation: 'Solo faltan las pruebas finales del sistema para completar tu configuración',
|
|
impact: 'high'
|
|
},
|
|
{
|
|
type: 'info',
|
|
title: 'Calidad de Datos Alta',
|
|
description: 'Tus datos tienen una calidad promedio del 94%',
|
|
recommendation: 'Considera revisar la configuración de pagos para mejorar la puntuación',
|
|
impact: 'medium'
|
|
},
|
|
{
|
|
type: 'warning',
|
|
title: 'Paso Pendiente',
|
|
description: 'Las pruebas del sistema están pendientes',
|
|
recommendation: 'Programa las pruebas para validar la configuración completa',
|
|
impact: 'high'
|
|
}
|
|
];
|
|
|
|
const dataAnalysis = [
|
|
{
|
|
category: 'Información del Negocio',
|
|
completeness: 100,
|
|
accuracy: 95,
|
|
items: 12,
|
|
issues: 0,
|
|
details: 'Toda la información básica está completa y verificada'
|
|
},
|
|
{
|
|
category: 'Menú y Productos',
|
|
completeness: 85,
|
|
accuracy: 88,
|
|
items: 45,
|
|
issues: 3,
|
|
details: '3 productos sin precios definidos'
|
|
},
|
|
{
|
|
category: 'Inventario Inicial',
|
|
completeness: 92,
|
|
accuracy: 90,
|
|
items: 28,
|
|
issues: 2,
|
|
details: '2 ingredientes sin stock mínimo definido'
|
|
},
|
|
{
|
|
category: 'Configuración Operativa',
|
|
completeness: 100,
|
|
accuracy: 100,
|
|
items: 8,
|
|
issues: 0,
|
|
details: 'Horarios y políticas completamente configuradas'
|
|
}
|
|
];
|
|
|
|
const benchmarkComparison = {
|
|
industry: {
|
|
onboardingScore: 74,
|
|
completionRate: 78,
|
|
averageTime: '6.8 días'
|
|
},
|
|
yourData: {
|
|
onboardingScore: 87,
|
|
completionRate: 92,
|
|
averageTime: '4.2 días'
|
|
}
|
|
};
|
|
|
|
const recommendations = [
|
|
{
|
|
priority: 'high',
|
|
title: 'Completar Pruebas del Sistema',
|
|
description: 'Realizar pruebas integrales para validar toda la configuración',
|
|
estimatedTime: '30 minutos',
|
|
impact: 'Garantiza funcionamiento óptimo del sistema'
|
|
},
|
|
{
|
|
priority: 'medium',
|
|
title: 'Revisar Precios de Productos',
|
|
description: 'Definir precios para los 3 productos pendientes',
|
|
estimatedTime: '15 minutos',
|
|
impact: 'Permitirá generar ventas de todos los productos'
|
|
},
|
|
{
|
|
priority: 'medium',
|
|
title: 'Configurar Stocks Mínimos',
|
|
description: 'Establecer niveles mínimos para 2 ingredientes',
|
|
estimatedTime: '10 minutos',
|
|
impact: 'Mejorará el control de inventario automático'
|
|
},
|
|
{
|
|
priority: 'low',
|
|
title: 'Optimizar Configuración de Pagos',
|
|
description: 'Revisar métodos de pago y comisiones',
|
|
estimatedTime: '20 minutos',
|
|
impact: 'Puede reducir costos de transacción'
|
|
}
|
|
];
|
|
|
|
const getInsightIcon = (type: string) => {
|
|
const iconProps = { className: "w-5 h-5" };
|
|
switch (type) {
|
|
case 'success': return <CheckCircle {...iconProps} className="w-5 h-5 text-green-600" />;
|
|
case 'warning': return <AlertCircle {...iconProps} className="w-5 h-5 text-yellow-600" />;
|
|
case 'info': return <Target {...iconProps} className="w-5 h-5 text-blue-600" />;
|
|
default: return <AlertCircle {...iconProps} />;
|
|
}
|
|
};
|
|
|
|
const getInsightColor = (type: string) => {
|
|
switch (type) {
|
|
case 'success': return 'bg-green-50 border-green-200';
|
|
case 'warning': return 'bg-yellow-50 border-yellow-200';
|
|
case 'info': return 'bg-blue-50 border-blue-200';
|
|
default: return 'bg-gray-50 border-gray-200';
|
|
}
|
|
};
|
|
|
|
const getPriorityColor = (priority: string) => {
|
|
switch (priority) {
|
|
case 'high': return 'red';
|
|
case 'medium': return 'yellow';
|
|
case 'low': return 'green';
|
|
default: return 'gray';
|
|
}
|
|
};
|
|
|
|
const getCompletionColor = (percentage: number) => {
|
|
if (percentage >= 95) return 'text-green-600';
|
|
if (percentage >= 80) return 'text-yellow-600';
|
|
return 'text-red-600';
|
|
};
|
|
|
|
return (
|
|
<div className="p-6 space-y-6">
|
|
<PageHeader
|
|
title="Análisis de Configuración"
|
|
description="Análisis detallado de tu proceso de configuración y recomendaciones"
|
|
action={
|
|
<div className="flex space-x-2">
|
|
<Button variant="outline">
|
|
<Eye className="w-4 h-4 mr-2" />
|
|
Ver Detalles
|
|
</Button>
|
|
<Button variant="outline">
|
|
<Download className="w-4 h-4 mr-2" />
|
|
Exportar Reporte
|
|
</Button>
|
|
</div>
|
|
}
|
|
/>
|
|
|
|
{/* Overall Score */}
|
|
<Card className="p-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-6">
|
|
<div className="text-center">
|
|
<div className="relative w-24 h-24 mx-auto mb-3">
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<span className="text-2xl font-bold text-green-600">{analysisData.onboardingScore}</span>
|
|
</div>
|
|
<svg className="w-24 h-24 transform -rotate-90">
|
|
<circle
|
|
cx="48"
|
|
cy="48"
|
|
r="40"
|
|
stroke="currentColor"
|
|
strokeWidth="8"
|
|
fill="none"
|
|
className="text-gray-200"
|
|
/>
|
|
<circle
|
|
cx="48"
|
|
cy="48"
|
|
r="40"
|
|
stroke="currentColor"
|
|
strokeWidth="8"
|
|
fill="none"
|
|
strokeDasharray={`${analysisData.onboardingScore * 2.51} 251`}
|
|
className="text-green-600"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<p className="text-sm font-medium text-gray-700">Puntuación General</p>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-blue-600">{analysisData.completionRate}%</p>
|
|
<p className="text-sm font-medium text-gray-700">Completado</p>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-purple-600">{analysisData.averageTime}</p>
|
|
<p className="text-sm font-medium text-gray-700">Tiempo Promedio</p>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-orange-600">{analysisData.stepsCompleted}/{analysisData.totalSteps}</p>
|
|
<p className="text-sm font-medium text-gray-700">Pasos Completados</p>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<p className="text-3xl font-bold text-teal-600">{analysisData.dataQuality}%</p>
|
|
<p className="text-sm font-medium text-gray-700">Calidad de Datos</p>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<div className="flex items-center justify-center mb-2">
|
|
<TrendingUp className="w-8 h-8 text-green-600" />
|
|
</div>
|
|
<p className="text-sm font-medium text-gray-700">Por encima del promedio</p>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
{/* Progress Analysis */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<Card className="p-6">
|
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Progreso por Pasos</h3>
|
|
<div className="space-y-4">
|
|
{stepProgress.map((step, index) => (
|
|
<div key={index} className="flex items-center justify-between p-3 border rounded-lg">
|
|
<div className="flex items-center space-x-3">
|
|
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${
|
|
step.completed ? 'bg-green-100' : 'bg-gray-100'
|
|
}`}>
|
|
{step.completed ? (
|
|
<CheckCircle className="w-5 h-5 text-green-600" />
|
|
) : (
|
|
<span className="text-sm font-medium text-gray-500">{index + 1}</span>
|
|
)}
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium text-gray-900">{step.step}</p>
|
|
<p className="text-xs text-gray-500">Tiempo: {step.timeSpent}</p>
|
|
</div>
|
|
</div>
|
|
<div className="text-right">
|
|
<p className={`text-sm font-medium ${getCompletionColor(step.quality)}`}>
|
|
{step.quality}%
|
|
</p>
|
|
<p className="text-xs text-gray-500">Calidad</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
|
|
<Card className="p-6">
|
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Comparación con la Industria</h3>
|
|
<div className="space-y-6">
|
|
<div>
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm font-medium text-gray-700">Puntuación de Configuración</span>
|
|
<div className="text-right">
|
|
<span className="text-lg font-bold text-green-600">{benchmarkComparison.yourData.onboardingScore}</span>
|
|
<span className="text-sm text-gray-500 ml-2">vs {benchmarkComparison.industry.onboardingScore}</span>
|
|
</div>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-2">
|
|
<div className="bg-green-600 h-2 rounded-full" style={{ width: `${(benchmarkComparison.yourData.onboardingScore / 100) * 100}%` }}></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm font-medium text-gray-700">Tasa de Completado</span>
|
|
<div className="text-right">
|
|
<span className="text-lg font-bold text-blue-600">{benchmarkComparison.yourData.completionRate}%</span>
|
|
<span className="text-sm text-gray-500 ml-2">vs {benchmarkComparison.industry.completionRate}%</span>
|
|
</div>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-2">
|
|
<div className="bg-blue-600 h-2 rounded-full" style={{ width: `${benchmarkComparison.yourData.completionRate}%` }}></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm font-medium text-gray-700">Tiempo de Configuración</span>
|
|
<div className="text-right">
|
|
<span className="text-lg font-bold text-purple-600">{benchmarkComparison.yourData.averageTime}</span>
|
|
<span className="text-sm text-gray-500 ml-2">vs {benchmarkComparison.industry.averageTime}</span>
|
|
</div>
|
|
</div>
|
|
<div className="bg-green-50 p-3 rounded-lg">
|
|
<p className="text-sm text-green-700">38% más rápido que el promedio de la industria</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Insights */}
|
|
<Card className="p-6">
|
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Insights y Recomendaciones</h3>
|
|
<div className="space-y-4">
|
|
{insights.map((insight, index) => (
|
|
<div key={index} className={`p-4 rounded-lg border ${getInsightColor(insight.type)}`}>
|
|
<div className="flex items-start space-x-3">
|
|
{getInsightIcon(insight.type)}
|
|
<div className="flex-1">
|
|
<h4 className="text-sm font-medium text-gray-900 mb-1">{insight.title}</h4>
|
|
<p className="text-sm text-gray-700 mb-2">{insight.description}</p>
|
|
<p className="text-sm font-medium text-gray-900">
|
|
Recomendación: {insight.recommendation}
|
|
</p>
|
|
</div>
|
|
<Badge variant={insight.impact === 'high' ? 'red' : insight.impact === 'medium' ? 'yellow' : 'green'}>
|
|
{insight.impact === 'high' ? 'Alto' : insight.impact === 'medium' ? 'Medio' : 'Bajo'} Impacto
|
|
</Badge>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
|
|
{/* Data Analysis */}
|
|
<Card className="p-6">
|
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Análisis de Calidad de Datos</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{dataAnalysis.map((category, index) => (
|
|
<div key={index} className="border rounded-lg p-4">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<h4 className="font-medium text-gray-900">{category.category}</h4>
|
|
<div className="flex items-center space-x-2">
|
|
<BarChart3 className="w-4 h-4 text-gray-500" />
|
|
<span className="text-sm text-gray-500">{category.items} elementos</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
<div>
|
|
<div className="flex justify-between text-sm mb-1">
|
|
<span>Completitud</span>
|
|
<span className={getCompletionColor(category.completeness)}>{category.completeness}%</span>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-2">
|
|
<div
|
|
className="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
|
style={{ width: `${category.completeness}%` }}
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="flex justify-between text-sm mb-1">
|
|
<span>Precisión</span>
|
|
<span className={getCompletionColor(category.accuracy)}>{category.accuracy}%</span>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-2">
|
|
<div
|
|
className="bg-green-600 h-2 rounded-full transition-all duration-300"
|
|
style={{ width: `${category.accuracy}%` }}
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
{category.issues > 0 && (
|
|
<div className="flex items-center text-sm text-red-600">
|
|
<AlertCircle className="w-4 h-4 mr-1" />
|
|
<span>{category.issues} problema{category.issues > 1 ? 's' : ''} detectado{category.issues > 1 ? 's' : ''}</span>
|
|
</div>
|
|
)}
|
|
|
|
<p className="text-xs text-gray-600">{category.details}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
|
|
{/* Action Items */}
|
|
<Card className="p-6">
|
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Elementos de Acción</h3>
|
|
<div className="space-y-3">
|
|
{recommendations.map((rec, index) => (
|
|
<div key={index} className="flex items-center justify-between p-4 border rounded-lg">
|
|
<div className="flex items-start space-x-3 flex-1">
|
|
<Badge variant={getPriorityColor(rec.priority)}>
|
|
{rec.priority === 'high' ? 'Alta' : rec.priority === 'medium' ? 'Media' : 'Baja'}
|
|
</Badge>
|
|
<div>
|
|
<h4 className="text-sm font-medium text-gray-900 mb-1">{rec.title}</h4>
|
|
<p className="text-sm text-gray-600 mb-1">{rec.description}</p>
|
|
<div className="flex items-center space-x-4 text-xs text-gray-500">
|
|
<span>Tiempo estimado: {rec.estimatedTime}</span>
|
|
<span>•</span>
|
|
<span>Impacto: {rec.impact}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Button size="sm">
|
|
Completar
|
|
</Button>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default OnboardingAnalysisPage; |