- Implement WebView2-based HMI frontend with React + TypeScript + Vite - Add C# .NET backend with WebSocket communication layer - Separate UI components into modular structure: * RecipePanel: Recipe selection and management * IOPanel: I/O monitoring and control (32 inputs/outputs) * MotionPanel: Servo control for X/Y/Z axes * CameraPanel: Vision system feed with HUD overlay * SettingsModal: System configuration management - Create reusable UI components (CyberPanel, TechButton, PanelHeader) - Implement dual-mode communication (WebView2 native + WebSocket fallback) - Add 3D visualization with Three.js/React Three Fiber - Fix JSON parsing bug in configuration save handler - Include comprehensive .gitignore for .NET and Node.js projects 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
import React from 'react';
|
|
import { FileText, CheckCircle2, Layers } from 'lucide-react';
|
|
import { Recipe } from '../types';
|
|
import { PanelHeader } from './common/PanelHeader';
|
|
import { TechButton } from './common/TechButton';
|
|
|
|
interface RecipePanelProps {
|
|
recipes: Recipe[];
|
|
currentRecipe: Recipe;
|
|
onSelectRecipe: (r: Recipe) => void;
|
|
}
|
|
|
|
export const RecipePanel: React.FC<RecipePanelProps> = ({ recipes, currentRecipe, onSelectRecipe }) => (
|
|
<div className="h-full flex flex-col">
|
|
<PanelHeader title="Recipe Select" icon={FileText} />
|
|
<div className="space-y-2 flex-1 overflow-y-auto custom-scrollbar pr-2">
|
|
{recipes.map(r => (
|
|
<div
|
|
key={r.id}
|
|
onClick={() => onSelectRecipe(r)}
|
|
className={`
|
|
p-3 cursor-pointer flex justify-between items-center transition-all border-l-4
|
|
${currentRecipe.id === r.id
|
|
? 'bg-white/10 border-neon-blue text-white shadow-[inset_0_0_20px_rgba(0,243,255,0.1)]'
|
|
: 'bg-black/20 border-transparent text-slate-500 hover:bg-white/5 hover:text-slate-300'}
|
|
`}
|
|
>
|
|
<div>
|
|
<div className="font-tech font-bold text-sm tracking-wide">{r.name}</div>
|
|
<div className="text-[10px] font-mono opacity-60">{r.lastModified}</div>
|
|
</div>
|
|
{currentRecipe.id === r.id && <CheckCircle2 className="w-4 h-4 text-neon-blue" />}
|
|
</div>
|
|
))}
|
|
</div>
|
|
<TechButton className="w-full mt-4 flex items-center justify-center gap-2">
|
|
<Layers className="w-4 h-4" /> New Recipe
|
|
</TechButton>
|
|
</div>
|
|
);
|