import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Layers, Plus, Trash2, Copy, Save, ArrowLeft, FileText, Calendar, Check } from 'lucide-react'; import { Recipe } from '../types'; import { comms } from '../communication'; import { TechButton } from '../components/common/TechButton'; interface RecipeData { idx?: number; Title?: string; Motion?: string; BCD_1D?: boolean; BCD_QR?: boolean; BCD_DM?: boolean; vOption?: number; vWMSInfo?: number; vSIDInfo?: number; vJobInfo?: number; vSIDConv?: number; Def_VName?: string; Def_MFG?: string; IgnoreOtherBarcode?: boolean; DisableCamera?: boolean; DisablePrinter?: boolean; CheckSIDExsit?: boolean; bOwnZPL?: boolean; IgnorePartNo?: boolean; IgnoreBatch?: boolean; BSave?: number; AutoOutConveyor?: number; [key: string]: any; } export const RecipePage: React.FC = () => { const navigate = useNavigate(); const [recipes, setRecipes] = useState([]); const [selectedTitle, setSelectedTitle] = useState(null); const [editedRecipe, setEditedRecipe] = useState(null); const [isLoading, setIsLoading] = useState(true); const [hasChanges, setHasChanges] = useState(false); useEffect(() => { loadRecipes(); }, []); const loadRecipes = async () => { try { const recipeStr = await comms.getRecipeList(); const recipeData = JSON.parse(recipeStr); setRecipes(recipeData); if (recipeData.length > 0 && !selectedTitle) { await handleSelect(recipeData[0]); } } catch (e) { console.error("Failed to load recipes", e); } setIsLoading(false); }; const handleSelect = async (r: Recipe) => { if (hasChanges) { const confirmed = window.confirm("You have unsaved changes. Do you want to discard them?"); if (!confirmed) return; } setSelectedTitle(r.name); try { const recipeStr = await comms.getRecipe(r.name); const recipeData = JSON.parse(recipeStr); setEditedRecipe(recipeData); setHasChanges(false); } catch (e) { console.error("Failed to load recipe details", e); alert("Failed to load recipe details"); } }; const handleFieldChange = (field: string, value: any) => { if (!editedRecipe) return; setEditedRecipe({ ...editedRecipe, [field]: value }); setHasChanges(true); }; const handleSave = async () => { if (!editedRecipe || !selectedTitle) return; try { const result = await comms.saveRecipe(selectedTitle, JSON.stringify(editedRecipe)); if (result.success) { setHasChanges(false); alert("Recipe saved successfully!"); await loadRecipes(); } else { alert(`Failed to save recipe: ${result.message}`); } } catch (error: any) { alert(`Error saving recipe: ${error.message || 'Unknown error'}`); console.error('Recipe save error:', error); } }; const handleCopy = async () => { if (!selectedTitle) return; const selectedRecipe = recipes.find(r => r.name === selectedTitle); if (!selectedRecipe) return; const newName = prompt(`Copy "${selectedRecipe.name}" as:`, `${selectedRecipe.name}_Copy`); if (!newName || newName.trim() === '') return; try { const result = await comms.copyRecipe(selectedTitle, newName.trim()); if (result.success && result.newRecipe) { await loadRecipes(); await handleSelect(result.newRecipe); console.log("Recipe copied successfully:", result.newRecipe); } else { alert(`Failed to copy recipe: ${result.message}`); } } catch (error: any) { alert(`Error copying recipe: ${error.message || 'Unknown error'}`); console.error('Recipe copy error:', error); } }; const handleDelete = async () => { if (!selectedTitle) return; const selectedRecipe = recipes.find(r => r.name === selectedTitle); if (!selectedRecipe) return; const confirmed = window.confirm(`Are you sure you want to delete "${selectedRecipe.name}"?`); if (!confirmed) return; try { const result = await comms.deleteRecipe(selectedTitle); if (result.success) { await loadRecipes(); // Select first recipe or clear selection const newRecipeList = recipes.filter(r => r.name !== selectedTitle); if (newRecipeList.length > 0) { await handleSelect(newRecipeList[0]); } else { setSelectedTitle(null); setEditedRecipe(null); } console.log("Recipe deleted successfully"); } else { alert(`Failed to delete recipe: ${result.message}`); } } catch (error: any) { alert(`Error deleting recipe: ${error.message || 'Unknown error'}`); console.error('Recipe delete error:', error); } }; return (
{/* Header */}

RECIPE MANAGEMENT

TOTAL: {recipes.length}
{/* Left: Recipe List */}
RECIPE LIST
{recipes.map(r => (
handleSelect(r)} className={` p-3 rounded border cursor-pointer transition-all group ${selectedTitle === r.name ? 'bg-neon-blue/20 border-neon-blue text-white shadow-glow-blue' : 'bg-white/5 border-white/5 text-slate-400 hover:bg-white/10 hover:border-white/20'} `} >
{r.name}
{r.lastModified}
))}
{/* List Actions */}
{/* Right: Editor */}
RECIPE EDITOR {editedRecipe && {editedRecipe.Title || selectedTitle}}
{editedRecipe ? (
{/* Basic Settings */}

Basic Settings

handleFieldChange('Motion', e.target.value)} className="w-full bg-black/40 border border-white/10 rounded px-4 py-2 text-white focus:border-neon-blue focus:outline-none transition-colors font-mono text-sm" />
handleFieldChange('AutoOutConveyor', parseInt(e.target.value) || 0)} className="w-full bg-black/40 border border-white/10 rounded px-4 py-2 text-white focus:border-neon-blue focus:outline-none transition-colors font-mono text-sm" />
handleFieldChange('Def_VName', e.target.value)} className="w-full bg-black/40 border border-white/10 rounded px-4 py-2 text-white focus:border-neon-blue focus:outline-none transition-colors font-mono text-sm" />
handleFieldChange('Def_MFG', e.target.value)} className="w-full bg-black/40 border border-white/10 rounded px-4 py-2 text-white focus:border-neon-blue focus:outline-none transition-colors font-mono text-sm" />
{/* Barcode Settings */}

Barcode Settings

{/* Feature Flags */}

Feature Flags

{[ { key: 'IgnoreOtherBarcode', label: 'Ignore Other Barcode' }, { key: 'DisableCamera', label: 'Disable Camera' }, { key: 'DisablePrinter', label: 'Disable Printer' }, { key: 'CheckSIDExsit', label: 'Check SID Exist' }, { key: 'bOwnZPL', label: 'Own ZPL' }, { key: 'IgnorePartNo', label: 'Ignore Part No' }, { key: 'IgnoreBatch', label: 'Ignore Batch' }, ].map(({ key, label }) => ( ))}
) : (

Select a recipe to edit

)}
{/* Editor Actions */}
{hasChanges && ( ● UNSAVED CHANGES )}
SAVE CHANGES
); };