Add improved production UI 3
This commit is contained in:
252
frontend/src/pages/app/analytics/ProductionAnalyticsPage.tsx
Normal file
252
frontend/src/pages/app/analytics/ProductionAnalyticsPage.tsx
Normal file
@@ -0,0 +1,252 @@
|
||||
import React, { useState } from 'react';
|
||||
import { TrendingUp, DollarSign, Activity, AlertTriangle, Settings } from 'lucide-react';
|
||||
import { Card, StatsGrid, Button } from '../../../components/ui';
|
||||
import { PageHeader } from '../../../components/layout';
|
||||
import { QualityDashboard, EquipmentManager } from '../../../components/domain/production';
|
||||
|
||||
// Production Cost Monitor Component (placeholder)
|
||||
const ProductionCostMonitor: React.FC = () => {
|
||||
return (
|
||||
<Card className="p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-[var(--text-primary)]">Monitor de Costos de Producción</h3>
|
||||
<DollarSign className="w-5 h-5 text-[var(--color-primary)]" />
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="p-4 bg-[var(--surface-secondary)] rounded-lg">
|
||||
<p className="text-sm text-[var(--text-secondary)]">Costo por unidad</p>
|
||||
<p className="text-2xl font-bold text-[var(--text-primary)]">€2.45</p>
|
||||
<p className="text-xs text-green-600">-8% vs mes anterior</p>
|
||||
</div>
|
||||
<div className="p-4 bg-[var(--surface-secondary)] rounded-lg">
|
||||
<p className="text-sm text-[var(--text-secondary)]">Eficiencia de costos</p>
|
||||
<p className="text-2xl font-bold text-[var(--text-primary)]">92%</p>
|
||||
<p className="text-xs text-green-600">+3% vs objetivo</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-64 bg-[var(--surface-secondary)] rounded-lg flex items-center justify-center">
|
||||
<p className="text-[var(--text-secondary)]">Gráfico de tendencias de costos</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
// AI Insights Component (placeholder)
|
||||
const AIInsights: React.FC = () => {
|
||||
return (
|
||||
<Card className="p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-[var(--text-primary)]">Insights de IA</h3>
|
||||
<Activity className="w-5 h-5 text-[var(--color-primary)]" />
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div className="p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
||||
<div className="flex items-start gap-3">
|
||||
<TrendingUp className="w-5 h-5 text-blue-600 mt-0.5" />
|
||||
<div>
|
||||
<h4 className="font-medium text-blue-900">Optimización de Producción</h4>
|
||||
<p className="text-sm text-blue-700">Se detectó que producir croissants los martes reduce costos en 15%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4 bg-amber-50 border border-amber-200 rounded-lg">
|
||||
<div className="flex items-start gap-3">
|
||||
<AlertTriangle className="w-5 h-5 text-amber-600 mt-0.5" />
|
||||
<div>
|
||||
<h4 className="font-medium text-amber-900">Predicción de Demanda</h4>
|
||||
<p className="text-sm text-amber-700">Aumento del 25% en demanda de pan integral previsto para el fin de semana</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
// Equipment Status Component (placeholder)
|
||||
const EquipmentStatus: React.FC = () => {
|
||||
return (
|
||||
<Card className="p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-[var(--text-primary)]">Estado de Equipos</h3>
|
||||
<Settings className="w-5 h-5 text-[var(--color-primary)]" />
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between p-3 bg-green-50 border border-green-200 rounded-lg">
|
||||
<div>
|
||||
<p className="font-medium text-green-900">Horno Principal</p>
|
||||
<p className="text-sm text-green-700">Funcionando óptimamente</p>
|
||||
</div>
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full"></div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||||
<div>
|
||||
<p className="font-medium text-yellow-900">Mezcladora #2</p>
|
||||
<p className="text-sm text-yellow-700">Mantenimiento requerido en 3 días</p>
|
||||
</div>
|
||||
<div className="w-3 h-3 bg-yellow-500 rounded-full"></div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between p-3 bg-green-50 border border-green-200 rounded-lg">
|
||||
<div>
|
||||
<p className="font-medium text-green-900">Refrigerador</p>
|
||||
<p className="text-sm text-green-700">Temperatura estable</p>
|
||||
</div>
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
const ProductionAnalyticsPage: React.FC = () => {
|
||||
const [activeTab, setActiveTab] = useState('overview');
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<PageHeader
|
||||
title="Análisis de Producción"
|
||||
description="Análisis avanzado y insights para profesionales y empresas"
|
||||
/>
|
||||
|
||||
{/* Key Metrics */}
|
||||
<StatsGrid
|
||||
stats={[
|
||||
{
|
||||
title: 'Eficiencia General',
|
||||
value: '94%',
|
||||
variant: 'success' as const,
|
||||
icon: TrendingUp,
|
||||
},
|
||||
{
|
||||
title: 'Costo Promedio',
|
||||
value: '€2.45',
|
||||
variant: 'info' as const,
|
||||
icon: DollarSign,
|
||||
},
|
||||
{
|
||||
title: 'Equipos Activos',
|
||||
value: '8/9',
|
||||
variant: 'warning' as const,
|
||||
icon: Settings,
|
||||
},
|
||||
{
|
||||
title: 'Calidad Promedio',
|
||||
value: '9.2/10',
|
||||
variant: 'success' as const,
|
||||
icon: Activity,
|
||||
}
|
||||
]}
|
||||
columns={4}
|
||||
/>
|
||||
|
||||
{/* Tabs Navigation */}
|
||||
<div className="border-b border-[var(--border-primary)]">
|
||||
<nav className="-mb-px flex space-x-8">
|
||||
<button
|
||||
onClick={() => setActiveTab('overview')}
|
||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${
|
||||
activeTab === 'overview'
|
||||
? 'border-orange-500 text-[var(--color-primary)]'
|
||||
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
Resumen
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('costs')}
|
||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${
|
||||
activeTab === 'costs'
|
||||
? 'border-orange-500 text-[var(--color-primary)]'
|
||||
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
Costos
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('ai-insights')}
|
||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${
|
||||
activeTab === 'ai-insights'
|
||||
? 'border-orange-500 text-[var(--color-primary)]'
|
||||
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
IA Insights
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('equipment')}
|
||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${
|
||||
activeTab === 'equipment'
|
||||
? 'border-orange-500 text-[var(--color-primary)]'
|
||||
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
Equipos
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('quality')}
|
||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${
|
||||
activeTab === 'quality'
|
||||
? 'border-orange-500 text-[var(--color-primary)]'
|
||||
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
Calidad
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{/* Tab Content */}
|
||||
{activeTab === 'overview' && (
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<ProductionCostMonitor />
|
||||
<AIInsights />
|
||||
<EquipmentStatus />
|
||||
<Card className="p-6">
|
||||
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-4">Resumen de Calidad</h3>
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-[var(--text-secondary)]">Productos aprobados</span>
|
||||
<span className="font-medium">96%</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-[var(--text-secondary)]">Rechazos por calidad</span>
|
||||
<span className="font-medium">2%</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-[var(--text-secondary)]">Reprocesos</span>
|
||||
<span className="font-medium">2%</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'costs' && (
|
||||
<div className="grid gap-6">
|
||||
<ProductionCostMonitor />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'ai-insights' && (
|
||||
<div className="grid gap-6">
|
||||
<AIInsights />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'equipment' && (
|
||||
<div className="grid gap-6">
|
||||
<EquipmentStatus />
|
||||
<EquipmentManager />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'quality' && (
|
||||
<QualityDashboard />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductionAnalyticsPage;
|
||||
Reference in New Issue
Block a user