Files
WebUITest-RealProjecT/FrontEnd/components/ProcessedDataPanel.tsx
arDTDev 6219c4c60e feat: Implement vision menu, processed data panel, and UI improvements
- Add VisionMenu component with Camera (QRCode) and Barcode (Keyence) submenus
- Remove old CameraPanel component and replace with dropdown menu structure
- Add ProcessedDataPanel to display processed data in bottom dock (5 rows visible)
- Create SystemStatusPanel component with horizontal button layout (START/STOP/RESET)
- Create EventLogPanel component for better code organization
- Add device initialization feature with 7-axis progress tracking
- Add GetProcessedData and GetInitializeStatus backend methods
- Update Header menu layout to vertical (icon on top, text below) for more space
- Update HomePage layout with bottom-docked ProcessedDataPanel
- Refactor HomePage to use new modular components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 22:18:55 +09:00

134 lines
7.0 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { Database, RefreshCw } from 'lucide-react';
import { comms } from '../communication';
import { ProcessedDataRow } from '../types';
import { PanelHeader } from './common/PanelHeader';
import { CyberPanel } from './common/CyberPanel';
export const ProcessedDataPanel: React.FC = () => {
const [data, setData] = useState<ProcessedDataRow[]>([]);
const [loading, setLoading] = useState(false);
const loadData = async () => {
setLoading(true);
try {
const dataJson = await comms.getProcessedData();
const parsedData = JSON.parse(dataJson) as ProcessedDataRow[];
// Display only the first 5 rows
setData(parsedData.slice(0, 5));
} catch (error) {
console.error('[ProcessedDataPanel] Failed to load data:', error);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadData();
// Refresh every 5 seconds
const interval = setInterval(loadData, 5000);
return () => clearInterval(interval);
}, []);
const getRowBackgroundColor = (row: ProcessedDataRow) => {
if (row.REMARK.startsWith('(BYPASS')) {
return 'bg-sky-300/20';
}
return row.LOC === 'L' ? 'bg-slate-700/20' : 'bg-slate-800/10';
};
const getRowTextColor = (row: ProcessedDataRow) => {
if (row.REMARK.startsWith('(BYPASS')) {
return 'text-white';
}
if (!row.PRNATTACH) {
return 'text-red-500';
}
if (!row.PRNVALID) {
return 'text-emerald-900';
}
return 'text-slate-200';
};
return (
<CyberPanel className="flex flex-col h-full">
<PanelHeader
icon={Database}
title="PROCESSED DATA"
className="mb-3"
>
<button
onClick={loadData}
disabled={loading}
className="p-1.5 hover:bg-white/10 rounded transition-colors disabled:opacity-50"
title="Refresh"
>
<RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />
</button>
</PanelHeader>
<div className="flex-1 overflow-auto">
<table className="w-full text-xs border-collapse">
<thead className="sticky top-0 bg-slate-900/90 backdrop-blur-sm z-10">
<tr className="border-b border-neon-blue/30">
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">R</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">MODEL</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">START</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">BATCH</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">SID</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">RID</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">VENDER</th>
<th className="px-2 py-1.5 text-right font-tech text-neon-blue">QTY</th>
<th className="px-2 py-1.5 text-right font-tech text-neon-blue">(MAX)</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">MFG</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">V.LOT</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">PARTNO</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">CPN</th>
<th className="px-2 py-1.5 text-left font-tech text-neon-blue">Remark</th>
<th className="px-2 py-1.5 text-center font-tech text-neon-blue">Attach</th>
<th className="px-2 py-1.5 text-center font-tech text-neon-blue">Valid</th>
</tr>
</thead>
<tbody>
{data.length === 0 ? (
<tr>
<td colSpan={16} className="px-2 py-8 text-center text-slate-500 font-mono text-xs">
{loading ? 'Loading...' : 'No data available'}
</td>
</tr>
) : (
data.map((row, index) => (
<tr
key={index}
className={`border-b border-white/5 ${getRowBackgroundColor(row)} ${getRowTextColor(row)} hover:bg-white/5 transition-colors`}
>
<td className="px-2 py-1.5 font-mono text-center">{row.target}</td>
<td className="px-2 py-1.5 font-mono">{row.JTYPE}</td>
<td className="px-2 py-1.5 font-mono">{row.STIME}</td>
<td className="px-2 py-1.5 font-mono">{row.BATCH}</td>
<td className="px-2 py-1.5 font-mono font-bold">{row.SID}</td>
<td className="px-2 py-1.5 font-mono font-bold">{row.RID}</td>
<td className="px-2 py-1.5 font-mono text-center">{row.VNAME}</td>
<td className="px-2 py-1.5 font-mono text-right">{row.QTY.toLocaleString()}</td>
<td className="px-2 py-1.5 font-mono text-right">{row.qtymax.toLocaleString()}</td>
<td className="px-2 py-1.5 font-mono text-center">{row.MFGDATE}</td>
<td className="px-2 py-1.5 font-mono">{row.VLOT}</td>
<td className="px-2 py-1.5 font-mono">{row.PARTNO}</td>
<td className="px-2 py-1.5 font-mono">{row.MCN}</td>
<td className="px-2 py-1.5 font-mono">{row.REMARK}</td>
<td className="px-2 py-1.5 text-center">
<span className={`inline-block w-3 h-3 rounded-full ${row.PRNATTACH ? 'bg-neon-green' : 'bg-red-500'}`} />
</td>
<td className="px-2 py-1.5 text-center">
<span className={`inline-block w-3 h-3 rounded-full ${row.PRNVALID ? 'bg-neon-green' : 'bg-red-500'}`} />
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</CyberPanel>
);
};