diff --git a/web/client/src/components/SettingsPanel.jsx b/web/client/src/components/SettingsPanel.jsx new file mode 100644 index 0000000..abf780f --- /dev/null +++ b/web/client/src/components/SettingsPanel.jsx @@ -0,0 +1,145 @@ +import React, { useState, useCallback } from 'react'; +import { useInventoryStore } from '../store/inventoryStore'; +import './SettingsPanel.css'; + +function SettingsPanel({ isOpen, onClose }) { + const droppers = useInventoryStore((state) => state.inventory.droppers) || []; + const dropperNicknames = useInventoryStore((state) => state.dropperNicknames) || {}; + const setDropperNickname = useInventoryStore((state) => state.setDropperNickname); + + const [editingDropper, setEditingDropper] = useState(null); + const [editValue, setEditValue] = useState(''); + const [saving, setSaving] = useState(false); + + const startEditing = useCallback((dropperName) => { + setEditingDropper(dropperName); + setEditValue(dropperNicknames[dropperName] || ''); + }, [dropperNicknames]); + + const saveNickname = useCallback(async () => { + if (!editingDropper) return; + setSaving(true); + await setDropperNickname(editingDropper, editValue); + setSaving(false); + setEditingDropper(null); + setEditValue(''); + }, [editingDropper, editValue, setDropperNickname]); + + const removeNickname = useCallback(async (dropperName) => { + setSaving(true); + await setDropperNickname(dropperName, ''); + setSaving(false); + }, [setDropperNickname]); + + const handleKeyDown = useCallback((e) => { + if (e.key === 'Enter') saveNickname(); + if (e.key === 'Escape') { + setEditingDropper(null); + setEditValue(''); + } + }, [saveNickname]); + + if (!isOpen) return null; + + return ( +
+
e.stopPropagation()}> +
+

⚙️ Settings

+ +
+ +
+
+

🏷️ Dropper Nicknames

+

+ Give your dispensers friendly names so they're easier to identify. +

+ + {droppers.length === 0 ? ( +
+ No droppers detected. Connect the bridge to discover droppers. +
+ ) : ( +
+ {droppers.map((d) => { + const nickname = dropperNicknames[d.name]; + const isEditing = editingDropper === d.name; + const shortName = d.name.replace(/^minecraft:/, ''); + + return ( +
+
+ + {shortName} + {d.isDefault && default} + {d.clientId && client {d.clientId}} + + {nickname && !isEditing && ( + "{nickname}" + )} +
+
+ {isEditing ? ( + <> + setEditValue(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="Enter nickname..." + maxLength={32} + autoFocus + disabled={saving} + /> + + + + ) : ( + <> + + {nickname && ( + + )} + + )} +
+
+ ); + })} +
+ )} +
+
+
+
+ ); +} + +export default SettingsPanel;