import React, { useState, useCallback } from 'react'; import { useTurtleStore } from '../store/turtleStore'; import './ControlPanel.css'; function TurtleCard({ turtle, isSelected, onSelect }) { const activeState = turtle.state || turtle.mode || 'idle'; const fuel = turtle.fuel === 'unlimited' ? '∞' : (turtle.fuel || '?'); const inventoryCount = Array.isArray(turtle.inventory) ? turtle.inventory.length : (turtle.inventory ? Object.keys(turtle.inventory).length : 0); const displayName = turtle.label || `Turtle ${turtle.turtleID}`; const modeColors = { mining: '#55ff55', exploring: '#55ffff', returning: '#ffaa00', goHome: '#ffaa00', idle: '#aaaaaa', manual: '#ff55ff', refueling: '#ff5555', farming: '#55ff55', dumpInventory: '#aa00aa', dumping: '#aa00aa', moving: '#55ffff', scan: '#5555ff', extraction: '#ffaa00', building: '#00aaaa', autocraft: '#ff55ff', unknown: '#555555' }; return (

{displayName}

{activeState}
Position: {turtle.position ? `${turtle.position.x}, ${turtle.position.y}, ${turtle.position.z}` : 'No GPS' }
Fuel: {fuel}
Inventory: {inventoryCount} items
{turtle.position && turtle.homePosition && (
Home Distance: {Math.abs(turtle.position.x - turtle.homePosition.x) + Math.abs(turtle.position.y - turtle.homePosition.y) + Math.abs(turtle.position.z - turtle.homePosition.z)} blocks
)}
); } function TurtleDetails({ turtle }) { const setTurtleState = useTurtleStore((state) => state.setTurtleState); const renameTurtle = useTurtleStore((state) => state.renameTurtle); const equipLeft = useTurtleStore((state) => state.equipLeft); const equipRight = useTurtleStore((state) => state.equipRight); const sortInventory = useTurtleStore((state) => state.sortInventory); const selectSlot = useTurtleStore((state) => state.selectSlot); const dropItems = useTurtleStore((state) => state.dropItems); const suckItems = useTurtleStore((state) => state.suckItems); const connectToInventory = useTurtleStore((state) => state.connectToInventory); const updateTurtleConfig = useTurtleStore((state) => state.updateTurtleConfig); const exploreTurtle = useTurtleStore((state) => state.exploreTurtle); const gpsLocateTurtle = useTurtleStore((state) => state.gpsLocateTurtle); const moveForward = useTurtleStore((state) => state.moveForward); const moveBack = useTurtleStore((state) => state.moveBack); const moveUp = useTurtleStore((state) => state.moveUp); const moveDown = useTurtleStore((state) => state.moveDown); const turnLeft = useTurtleStore((state) => state.turnLeft); const turnRight = useTurtleStore((state) => state.turnRight); const digBlock = useTurtleStore((state) => state.digBlock); const digBlockUp = useTurtleStore((state) => state.digBlockUp); const digBlockDown = useTurtleStore((state) => state.digBlockDown); const placeBlock = useTurtleStore((state) => state.placeBlock); const [renameValue, setRenameValue] = useState(''); const [showConfig, setShowConfig] = useState(false); const [configValues, setConfigValues] = useState({ maxDistance: 200, autoRefuel: true }); if (!turtle) { return (

Select a turtle to view details and control it

); } const handleStateChange = (stateName, data = {}) => { setTurtleState(turtle.turtleID, stateName, data); }; const handleRename = async () => { if (renameValue.trim()) { await renameTurtle(turtle.turtleID, renameValue.trim()); setRenameValue(''); } }; const handleSlotClick = async (slotIndex) => { await selectSlot(turtle.turtleID, slotIndex + 1); }; const handleConfigSave = async () => { await updateTurtleConfig(turtle.turtleID, configValues); setShowConfig(false); }; const activeState = turtle.state || turtle.mode || 'idle'; const displayName = turtle.label || `Turtle ${turtle.turtleID}`; return (

{displayName} #{turtle.turtleID}

{/* Rename + Config bar */}
setRenameValue(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleRename()} placeholder="Rename turtle..." className="rename-input" style={{ flex: 1, minWidth: '120px', padding: '4px 8px', border: '2px solid #333', background: '#1a1a1a', color: '#e0e0e0' }} />
{/* Config Modal */} {showConfig && (

βš™οΈ Configuration

)}

Status

State: {activeState}
{turtle.stateDescription && (
Activity: {turtle.stateDescription}
)}
Fuel: {turtle.fuel === 'unlimited' ? 'Unlimited' : turtle.fuel}
Position: {turtle.position ? `X: ${turtle.position.x}, Y: ${turtle.position.y}, Z: ${turtle.position.z}` : 'No GPS' }
Home: {turtle.homePosition ? `X: ${turtle.homePosition.x}, Y: ${turtle.homePosition.y}, Z: ${turtle.homePosition.z}` : 'Not set' }
{turtle.error && (
Error: {turtle.error}
)} {turtle.warning && (
Warning: {turtle.warning}
)}
{/* Peripherals section */} {turtle.peripherals && Object.keys(turtle.peripherals).length > 0 && (

Peripherals

{Object.entries(turtle.peripherals).map(([side, info]) => (
{side}: {typeof info === 'string' ? info : (info?.types?.join(', ') || 'unknown')}
))}
)}

State Machine

Movement

Actions

{/* Equipment & Inventory Actions */}

Equipment & Inventory

{turtle.inventory && turtle.inventory.length > 0 && (

Inventory ({turtle.inventoryCount || turtle.inventory.length}/16) β€” Slot: {turtle.selectedSlot || 1}

{Array.from({ length: 16 }, (_, slotIndex) => { const item = turtle.inventory[slotIndex]; const isSelected = (turtle.selectedSlot || 1) === (slotIndex + 1); return (
handleSlotClick(slotIndex)} style={isSelected ? { outline: '2px solid #55ffff', outlineOffset: '-2px' } : {}} > {item ? ( <>
{item.name.includes('diamond') ? 'πŸ’Ž' : item.name.includes('gold') ? 'οΏ½' : item.name.includes('iron') ? 'βšͺ' : item.name.includes('coal') ? '⚫' : item.name.includes('emerald') ? '🟒' : item.name.includes('redstone') ? 'πŸ”΄' : item.name.includes('lapis') ? 'πŸ”΅' : item.name.includes('stone') ? 'πŸ—Ώ' : item.name.includes('dirt') ? '🟀' : item.name.includes('wood') || item.name.includes('log') ? 'πŸͺ΅' : item.name.includes('cobble') ? 'πŸͺ¨' : 'οΏ½πŸ“¦'} {item.count}
{item.name.replace('minecraft:', '').replace(/_/g, ' ').split(' ').slice(0, 2).join(' ')}
) : ( {slotIndex + 1} )}
); })}
)}
); } export default function ControlPanel() { const turtles = useTurtleStore((state) => state.getTurtleArray()); const selectedTurtleId = useTurtleStore((state) => state.selectedTurtleId); const selectTurtle = useTurtleStore((state) => state.selectTurtle); const selectedTurtle = useTurtleStore((state) => state.getSelectedTurtle()); const connected = useTurtleStore((state) => state.connected); return (

🐒 Turtle Control Center

{connected ? 'Connected' : 'Disconnected'}

Turtles ({turtles.length})

{turtles.length === 0 ? (

No turtles connected

Waiting for turtles to come online...

) : (
{turtles.map((turtle) => ( selectTurtle(turtle.turtleID)} /> ))}
)}
); }