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>
This commit is contained in:
2025-11-25 22:18:55 +09:00
parent e46886cabc
commit 6219c4c60e
14 changed files with 1273 additions and 555 deletions

View File

@@ -1,6 +1,7 @@
import React from 'react';
import React, { useState } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { Activity, Settings, Move, Camera, Layers, Cpu, Target } from 'lucide-react';
import { VisionMenu } from '../VisionMenu';
interface HeaderProps {
currentTime: Date;
@@ -12,12 +13,15 @@ interface HeaderProps {
export const Header: React.FC<HeaderProps> = ({ currentTime, onTabChange, activeTab }) => {
const navigate = useNavigate();
const location = useLocation();
const [showVisionMenu, setShowVisionMenu] = useState(false);
const isWebView = typeof window !== 'undefined' && !!window.chrome?.webview;
const isIOPage = location.pathname === '/io-monitor';
return (
<header className="absolute top-0 left-0 right-0 h-20 px-6 flex items-center justify-between z-40 bg-gradient-to-b from-black/80 to-transparent pointer-events-none">
<>
<VisionMenu isOpen={showVisionMenu} onClose={() => setShowVisionMenu(false)} />
<header className="absolute top-0 left-0 right-0 h-20 px-6 flex items-center justify-between z-40 bg-gradient-to-b from-black/80 to-transparent pointer-events-none">
<div
className="flex items-center gap-4 pointer-events-auto cursor-pointer group"
onClick={() => {
@@ -47,7 +51,7 @@ export const Header: React.FC<HeaderProps> = ({ currentTime, onTabChange, active
{/* IO Tab Switcher (only on IO page) */}
<div className="bg-black/40 backdrop-blur-md p-1 rounded-full border border-white/10 flex gap-1">
<div className="bg-black/40 backdrop-blur-md p-1 rounded-2xl border border-white/10 flex gap-1">
{[
{ id: 'recipe', icon: Layers, label: 'RECIPE', path: '/' },
{ id: 'io', icon: Activity, label: 'I/O MONITOR', path: '/io-monitor' },
@@ -67,21 +71,27 @@ export const Header: React.FC<HeaderProps> = ({ currentTime, onTabChange, active
if (item.id === 'io') {
navigate('/io-monitor');
onTabChange(null);
setShowVisionMenu(false);
} else if (item.id === 'camera') {
setShowVisionMenu(!showVisionMenu);
onTabChange(null);
} else {
if (location.pathname !== '/') {
navigate('/');
}
setShowVisionMenu(false);
onTabChange(activeTab === item.id ? null : item.id as any);
}
}}
className={`
flex items-center gap-2 px-6 py-2 rounded-full font-tech font-bold text-sm transition-all border border-transparent
flex flex-col items-center justify-center gap-1 px-3 py-2 rounded-xl font-tech font-bold text-[10px] transition-all border border-transparent min-w-[70px]
${isActive
? 'bg-neon-blue/10 text-neon-blue border-neon-blue shadow-glow-blue'
: 'text-slate-400 hover:text-white hover:bg-white/5'}
`}
>
<item.icon className="w-4 h-4" /> {item.label}
<item.icon className="w-5 h-5" />
<span className="leading-tight">{item.label}</span>
</button>
);
})}
@@ -97,5 +107,6 @@ export const Header: React.FC<HeaderProps> = ({ currentTime, onTabChange, active
</div>
</div>
</header>
</>
);
};