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:
156
FrontEnd/components/VisionMenu.tsx
Normal file
156
FrontEnd/components/VisionMenu.tsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Camera, ChevronRight, X } from 'lucide-react';
|
||||
|
||||
interface VisionMenuProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
const [activeSubmenu, setActiveSubmenu] = useState<string | null>(null);
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
if (isOpen) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [isOpen, onClose]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleQRCodeCamera = () => {
|
||||
console.log('[VisionMenu] Camera (QRCode) clicked');
|
||||
// TODO: Implement QR Code camera functionality
|
||||
};
|
||||
|
||||
const handleKeyenceBarcode = () => {
|
||||
console.log('[VisionMenu] Barcode (Keyence) clicked');
|
||||
// TODO: Implement Keyence barcode functionality
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={menuRef}
|
||||
className="absolute top-20 left-1/2 -translate-x-1/2 z-50 bg-black/95 backdrop-blur-md border border-neon-blue/50 rounded-lg shadow-glow-blue min-w-[300px]"
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between p-4 border-b border-white/10">
|
||||
<div className="flex items-center gap-3">
|
||||
<Camera className="w-5 h-5 text-neon-blue" />
|
||||
<h3 className="font-tech font-bold text-lg text-white">VISION</h3>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-slate-400 hover:text-white transition-colors"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Menu Items */}
|
||||
<div className="p-2">
|
||||
{/* Camera (QRCode) */}
|
||||
<div className="relative">
|
||||
<button
|
||||
onMouseEnter={() => setActiveSubmenu('qrcode')}
|
||||
onClick={handleQRCodeCamera}
|
||||
className="w-full flex items-center justify-between px-4 py-3 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors font-tech"
|
||||
>
|
||||
<span>Camera (QRCode)</span>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
{/* QRCode Submenu */}
|
||||
{activeSubmenu === 'qrcode' && (
|
||||
<div
|
||||
className="absolute left-full top-0 ml-1 bg-black/95 backdrop-blur-md border border-neon-blue/50 rounded-lg shadow-glow-blue min-w-[200px] p-2"
|
||||
onMouseLeave={() => setActiveSubmenu(null)}
|
||||
>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Connect')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
<div className="h-px bg-white/10 my-1" />
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Get Image')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Get Image
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Live View')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Live View
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Read Test')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Read Test
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Barcode (Keyence) */}
|
||||
<div className="relative">
|
||||
<button
|
||||
onMouseEnter={() => setActiveSubmenu('keyence')}
|
||||
onClick={handleKeyenceBarcode}
|
||||
className="w-full flex items-center justify-between px-4 py-3 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors font-tech"
|
||||
>
|
||||
<span>Barcode (Keyence)</span>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
{/* Keyence Submenu */}
|
||||
{activeSubmenu === 'keyence' && (
|
||||
<div
|
||||
className="absolute left-full top-0 ml-1 bg-black/95 backdrop-blur-md border border-neon-blue/50 rounded-lg shadow-glow-blue min-w-[200px] p-2"
|
||||
onMouseLeave={() => setActiveSubmenu(null)}
|
||||
>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Get Image')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Get Image
|
||||
</button>
|
||||
<div className="h-px bg-white/10 my-1" />
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Trigger On')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Trigger On
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Trigger Off')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Trigger Off
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Save Image')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Save Image
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user