import React, { useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Card, CardHeader, CardBody } from '../../ui/Card'; import { Button } from '../../ui/Button'; import { Input } from '../../ui/Input'; import { Badge } from '../../ui/Badge'; import { Modal } from '../../ui/Modal'; import { Tabs, TabsList, TabsTrigger, TabsContent } from '../../ui/Tabs'; import { StatsGrid } from '../../ui/Stats'; import { Settings, AlertTriangle, CheckCircle, Wrench, Calendar, Clock, Thermometer, Activity, Zap, TrendingUp, Search, Plus, Filter, Download, BarChart3, Bell, MapPin, User } from 'lucide-react'; import { useCurrentTenant } from '../../../stores/tenant.store'; export interface Equipment { id: string; name: string; type: 'oven' | 'mixer' | 'proofer' | 'freezer' | 'packaging' | 'other'; model: string; serialNumber: string; location: string; status: 'operational' | 'maintenance' | 'down' | 'warning'; installDate: string; lastMaintenance: string; nextMaintenance: string; maintenanceInterval: number; // days temperature?: number; targetTemperature?: number; efficiency: number; uptime: number; energyUsage: number; utilizationToday: number; alerts: Array<{ id: string; type: 'warning' | 'critical' | 'info'; message: string; timestamp: string; acknowledged: boolean; }>; maintenanceHistory: Array<{ id: string; date: string; type: 'preventive' | 'corrective' | 'emergency'; description: string; technician: string; cost: number; downtime: number; // hours partsUsed: string[]; }>; specifications: { power: number; // kW capacity: number; dimensions: { width: number; height: number; depth: number; }; weight: number; }; } export interface EquipmentManagerProps { className?: string; equipment?: Equipment[]; onCreateEquipment?: () => void; onEditEquipment?: (equipmentId: string) => void; onScheduleMaintenance?: (equipmentId: string) => void; onAcknowledgeAlert?: (equipmentId: string, alertId: string) => void; onViewMaintenanceHistory?: (equipmentId: string) => void; } const MOCK_EQUIPMENT: Equipment[] = [ { id: '1', name: 'Horno Principal #1', type: 'oven', model: 'Miwe Condo CO 4.1212', serialNumber: 'MCO-2021-001', location: 'Área de Horneado - Zona A', status: 'operational', installDate: '2021-03-15', lastMaintenance: '2024-01-15', nextMaintenance: '2024-04-15', maintenanceInterval: 90, temperature: 220, targetTemperature: 220, efficiency: 92, uptime: 98.5, energyUsage: 45.2, utilizationToday: 87, alerts: [], maintenanceHistory: [ { id: '1', date: '2024-01-15', type: 'preventive', description: 'Limpieza general y calibración de termostatos', technician: 'Juan Pérez', cost: 150, downtime: 2, partsUsed: ['Filtros de aire', 'Sellos de puerta'] } ], specifications: { power: 45, capacity: 24, dimensions: { width: 200, height: 180, depth: 120 }, weight: 850 } }, { id: '2', name: 'Batidora Industrial #2', type: 'mixer', model: 'Hobart HL800', serialNumber: 'HHL-2020-002', location: 'Área de Preparación - Zona B', status: 'warning', installDate: '2020-08-10', lastMaintenance: '2024-01-20', nextMaintenance: '2024-02-20', maintenanceInterval: 30, efficiency: 88, uptime: 94.2, energyUsage: 12.8, utilizationToday: 76, alerts: [ { id: '1', type: 'warning', message: 'Vibración inusual detectada en el motor', timestamp: '2024-01-23T10:30:00Z', acknowledged: false }, { id: '2', type: 'info', message: 'Mantenimiento programado en 5 días', timestamp: '2024-01-23T08:00:00Z', acknowledged: true } ], maintenanceHistory: [ { id: '1', date: '2024-01-20', type: 'corrective', description: 'Reemplazo de correas de transmisión', technician: 'María González', cost: 85, downtime: 4, partsUsed: ['Correa tipo V', 'Rodamientos'] } ], specifications: { power: 15, capacity: 80, dimensions: { width: 120, height: 150, depth: 80 }, weight: 320 } }, { id: '3', name: 'Cámara de Fermentación #1', type: 'proofer', model: 'Bongard EUROPA 16.18', serialNumber: 'BEU-2022-001', location: 'Área de Fermentación', status: 'maintenance', installDate: '2022-06-20', lastMaintenance: '2024-01-23', nextMaintenance: '2024-01-24', maintenanceInterval: 60, temperature: 32, targetTemperature: 35, efficiency: 0, uptime: 85.1, energyUsage: 0, utilizationToday: 0, alerts: [ { id: '1', type: 'info', message: 'En mantenimiento programado', timestamp: '2024-01-23T06:00:00Z', acknowledged: true } ], maintenanceHistory: [ { id: '1', date: '2024-01-23', type: 'preventive', description: 'Mantenimiento programado - sistema de humidificación', technician: 'Carlos Rodríguez', cost: 200, downtime: 8, partsUsed: ['Sensor de humedad', 'Válvulas'] } ], specifications: { power: 8, capacity: 16, dimensions: { width: 180, height: 200, depth: 100 }, weight: 450 } } ]; const EquipmentManager: React.FC = ({ className, equipment = MOCK_EQUIPMENT, onCreateEquipment, onEditEquipment, onScheduleMaintenance, onAcknowledgeAlert, onViewMaintenanceHistory }) => { const { t } = useTranslation(); const [activeTab, setActiveTab] = useState('overview'); const [searchQuery, setSearchQuery] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [selectedEquipment, setSelectedEquipment] = useState(null); const [showEquipmentModal, setShowEquipmentModal] = useState(false); const filteredEquipment = useMemo(() => { return equipment.filter(eq => { const matchesSearch = !searchQuery || eq.name.toLowerCase().includes(searchQuery.toLowerCase()) || eq.location.toLowerCase().includes(searchQuery.toLowerCase()) || eq.type.toLowerCase().includes(searchQuery.toLowerCase()); const matchesStatus = statusFilter === 'all' || eq.status === statusFilter; return matchesSearch && matchesStatus; }); }, [equipment, searchQuery, statusFilter]); const equipmentStats = useMemo(() => { const total = equipment.length; const operational = equipment.filter(e => e.status === 'operational').length; const warning = equipment.filter(e => e.status === 'warning').length; const maintenance = equipment.filter(e => e.status === 'maintenance').length; const down = equipment.filter(e => e.status === 'down').length; const avgEfficiency = equipment.reduce((sum, e) => sum + e.efficiency, 0) / total; const avgUptime = equipment.reduce((sum, e) => sum + e.uptime, 0) / total; const totalAlerts = equipment.reduce((sum, e) => sum + e.alerts.filter(a => !a.acknowledged).length, 0); return { total, operational, warning, maintenance, down, avgEfficiency, avgUptime, totalAlerts }; }, [equipment]); const getStatusConfig = (status: Equipment['status']) => { const configs = { operational: { color: 'success' as const, icon: CheckCircle, label: t('equipment.status.operational', 'Operational') }, warning: { color: 'warning' as const, icon: AlertTriangle, label: t('equipment.status.warning', 'Warning') }, maintenance: { color: 'info' as const, icon: Wrench, label: t('equipment.status.maintenance', 'Maintenance') }, down: { color: 'error' as const, icon: AlertTriangle, label: t('equipment.status.down', 'Down') } }; return configs[status]; }; const getTypeIcon = (type: Equipment['type']) => { const icons = { oven: Thermometer, mixer: Activity, proofer: Settings, freezer: Zap, packaging: Settings, other: Settings }; return icons[type]; }; const formatDateTime = (dateString: string) => { return new Date(dateString).toLocaleDateString('es-ES', { day: '2-digit', month: '2-digit', year: 'numeric' }); }; const stats = [ { title: t('equipment.stats.total', 'Total Equipment'), value: equipmentStats.total, icon: Settings, variant: 'default' as const }, { title: t('equipment.stats.operational', 'Operational'), value: equipmentStats.operational, icon: CheckCircle, variant: 'success' as const, subtitle: `${((equipmentStats.operational / equipmentStats.total) * 100).toFixed(1)}%` }, { title: t('equipment.stats.avg_efficiency', 'Avg Efficiency'), value: `${equipmentStats.avgEfficiency.toFixed(1)}%`, icon: TrendingUp, variant: equipmentStats.avgEfficiency >= 90 ? 'success' as const : 'warning' as const }, { title: t('equipment.stats.alerts', 'Active Alerts'), value: equipmentStats.totalAlerts, icon: Bell, variant: equipmentStats.totalAlerts === 0 ? 'success' as const : 'error' as const } ]; return (

{t('equipment.manager.title', 'Equipment Management')}

{t('equipment.manager.subtitle', 'Monitor and manage production equipment')}

{/* Stats */} {/* Filters */}
setSearchQuery(e.target.value)} className="pl-10" />
{/* Equipment List */} {t('equipment.tabs.overview', 'Overview')} {t('equipment.tabs.maintenance', 'Maintenance')} {t('equipment.tabs.alerts', 'Alerts')}
{filteredEquipment.map((eq) => { const statusConfig = getStatusConfig(eq.status); const TypeIcon = getTypeIcon(eq.type); const StatusIcon = statusConfig.icon; return (
{ setSelectedEquipment(eq); setShowEquipmentModal(true); }} >

{eq.name}

{statusConfig.label}
{t('equipment.efficiency', 'Efficiency')}: {eq.efficiency}%
{t('equipment.uptime', 'Uptime')}: {eq.uptime.toFixed(1)}%
{t('equipment.location', 'Location')}: {eq.location}
{eq.temperature && (
{t('equipment.temperature', 'Temperature')}: {eq.temperature}°C
)}
{eq.alerts.filter(a => !a.acknowledged).length > 0 && (
{eq.alerts.filter(a => !a.acknowledged).length} {t('equipment.unread_alerts', 'unread alerts')}
)}
); })}
{equipment.map((eq) => (

{eq.name}

{new Date(eq.nextMaintenance) <= new Date() ? t('equipment.maintenance.overdue', 'Overdue') : t('equipment.maintenance.scheduled', 'Scheduled')}
{t('equipment.maintenance.last', 'Last')}:
{formatDateTime(eq.lastMaintenance)}
{t('equipment.maintenance.next', 'Next')}:
{formatDateTime(eq.nextMaintenance)}
{t('equipment.maintenance.interval', 'Interval')}:
{eq.maintenanceInterval} {t('common.days', 'days')}
{t('equipment.maintenance.history', 'History')}:
{eq.maintenanceHistory.length} {t('equipment.maintenance.records', 'records')}
))}
{equipment.flatMap(eq => eq.alerts.map(alert => (

{eq.name}

{alert.acknowledged ? t('equipment.alerts.acknowledged', 'Acknowledged') : t('equipment.alerts.new', 'New')}
{new Date(alert.timestamp).toLocaleString('es-ES')}

{alert.message}

{!alert.acknowledged && ( )}
)) )}
{/* Equipment Details Modal */} {selectedEquipment && ( { setShowEquipmentModal(false); setSelectedEquipment(null); }} title={selectedEquipment.name} size="lg" >
{/* Basic Info */}

{selectedEquipment.model}

{selectedEquipment.serialNumber}

{selectedEquipment.location}

{formatDateTime(selectedEquipment.installDate)}

{/* Current Status */}
{selectedEquipment.efficiency}%
{t('equipment.efficiency', 'Efficiency')}
{selectedEquipment.uptime.toFixed(1)}%
{t('equipment.uptime', 'Uptime')}
{selectedEquipment.energyUsage} kW
{t('equipment.energy_usage', 'Energy Usage')}
{/* Actions */}
)}
); }; export default EquipmentManager;