'use client'; import { useState, useCallback } from 'react'; import { useRouter } from 'next/navigation'; import type { Machine, Criticality } from '@/lib/types'; interface MachineListProps { machines: Machine[]; tenantId: string; onEdit: (machine: Machine) => void; onDelete: (machine: Machine) => void; onBatchInspect?: (area: string, machineIds: string[]) => void; } const CRITICALITY_ORDER: Record = { critical: 0, major: 1, minor: 2, }; const getCriticalityScore = (c: Criticality | null) => { if (!c) return 3; return CRITICALITY_ORDER[c] ?? 3; }; export function MachineList({ machines, tenantId, onEdit, onDelete, onBatchInspect }: MachineListProps) { const router = useRouter(); const groupedMachines = machines.reduce((acc, machine) => { const area = machine.area || '미지정'; if (!acc[area]) { acc[area] = []; } acc[area].push(machine); return acc; }, {} as Record); const sortedAreas = Object.keys(groupedMachines).sort((a, b) => { const machinesA = groupedMachines[a]; const machinesB = groupedMachines[b]; const hasCriticalA = machinesA.some(m => m.criticality === 'critical'); const hasCriticalB = machinesB.some(m => m.criticality === 'critical'); if (hasCriticalA && !hasCriticalB) return -1; if (!hasCriticalA && hasCriticalB) return 1; return a.localeCompare(b); }); sortedAreas.forEach(area => { groupedMachines[area].sort((a, b) => { const scoreA = getCriticalityScore(a.criticality); const scoreB = getCriticalityScore(b.criticality); return scoreA - scoreB; }); }); const getBadgeClass = (criticality: Criticality | null) => { switch (criticality) { case 'critical': return 'machine-badge-critical'; case 'major': return 'machine-badge-major'; case 'minor': return 'machine-badge-minor'; default: return null; } }; const getBadgeText = (criticality: Criticality | null) => { switch (criticality) { case 'critical': return '핵심'; case 'major': return '주요'; case 'minor': return '보조'; default: return null; } }; const [collapsed, setCollapsed] = useState>(() => { const init: Record = {}; Object.keys(groupedMachines).forEach(area => { init[area] = groupedMachines[area].length > 30; }); return init; }); const toggleArea = useCallback((area: string) => { setCollapsed(prev => ({ ...prev, [area]: !prev[area] })); }, []); return (
{sortedAreas.map(area => (
toggleArea(area)} style={{ cursor: 'pointer' }}>

location_on {area} ({groupedMachines[area].length}대) expand_more

{onBatchInspect && ( )}
{!collapsed[area] &&
{groupedMachines[area].map((machine) => (
router.push(`/${tenantId}/machines/${machine.id}`)} >
precision_manufacturing
{machine.source === 'digital-twin' && ( cloud 동기화 )} {machine.criticality && ( {getBadgeText(machine.criticality)} )}

{machine.name}

{machine.equipment_code} {machine.model && ( {machine.model} )}
settings 부품 {machine.parts_count}개
))}
}
))} {sortedAreas.length === 0 && (
precision_manufacturing

등록된 설비가 없습니다.

)}
); }