From 1c2d8da08de6a1c6ffe276d0abfab294822a4c74 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 18 May 2026 20:40:19 +0200 Subject: [PATCH] wired-tools(store): hoist managed-holder give picker chain (selectedManagedVariableEntry, selectedManagedHolderVariableId, managedGiveVariableItemId, managedGiveValue) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the Variable-Manage panel's four-step picker cascade into the Zustand store. Closes the WiredCreatorTools "fragmented picker state" roadmap item — every remaining useState in the panel is now either a store-backed UI flag or a transient component-only value (keepSelected, globalClock, roomEnteredAt, monitor error/log details). All writers were already direct assignments (no updater shape), so the setters are plain typed setters. Sentinels remain `null` / `0` / `0` / `'0'`; the cascade reset effects at WiredCreatorToolsView.tsx:2265-2307 keep the chain self-consistent. Panel close/reopen now preserves the managed picker state, matching the lifecycle guarantee already provided for selection, monitor snapshot, variable highlight, and inline editor. Tests: 4 new cases (entry select/clear, chain write, post-action reset to sentinels, panel-lifecycle persistence). Suite: 203/203. --- .../wired-tools/WiredCreatorToolsView.tsx | 12 ++-- .../wiredCreatorToolsUiStore.test.ts | 67 ++++++++++++++++++- .../wired-tools/wiredCreatorToolsUiStore.ts | 32 ++++++++- 3 files changed, 104 insertions(+), 7 deletions(-) diff --git a/src/components/wired-tools/WiredCreatorToolsView.tsx b/src/components/wired-tools/WiredCreatorToolsView.tsx index 85984a8..2bd5cf8 100644 --- a/src/components/wired-tools/WiredCreatorToolsView.tsx +++ b/src/components/wired-tools/WiredCreatorToolsView.tsx @@ -70,16 +70,20 @@ export const WiredCreatorToolsView: FC<{}> = () => const setVariableManageSort = useWiredCreatorToolsUiStore(s => s.setVariableManageSort); const variableManagePage = useWiredCreatorToolsUiStore(s => s.variableManagePage); const setVariableManagePage = useWiredCreatorToolsUiStore(s => s.setVariableManagePage); - const [ selectedManagedVariableEntry, setSelectedManagedVariableEntry ] = useState(null); - const [ selectedManagedHolderVariableId, setSelectedManagedHolderVariableId ] = useState(0); + const selectedManagedVariableEntry = useWiredCreatorToolsUiStore(s => s.selectedManagedVariableEntry); + const setSelectedManagedVariableEntry = useWiredCreatorToolsUiStore(s => s.setSelectedManagedVariableEntry); + const selectedManagedHolderVariableId = useWiredCreatorToolsUiStore(s => s.selectedManagedHolderVariableId); + const setSelectedManagedHolderVariableId = useWiredCreatorToolsUiStore(s => s.setSelectedManagedHolderVariableId); const editingManagedHolderVariableId = useWiredCreatorToolsUiStore(s => s.editingManagedHolderVariableId); const setEditingManagedHolderVariableId = useWiredCreatorToolsUiStore(s => s.setEditingManagedHolderVariableId); const editingManagedHolderValue = useWiredCreatorToolsUiStore(s => s.editingManagedHolderValue); const setEditingManagedHolderValue = useWiredCreatorToolsUiStore(s => s.setEditingManagedHolderValue); const isManagedGiveOpen = useWiredCreatorToolsUiStore(s => s.isManagedGiveOpen); const setIsManagedGiveOpen = useWiredCreatorToolsUiStore(s => s.setIsManagedGiveOpen); - const [ managedGiveVariableItemId, setManagedGiveVariableItemId ] = useState(0); - const [ managedGiveValue, setManagedGiveValue ] = useState('0'); + const managedGiveVariableItemId = useWiredCreatorToolsUiStore(s => s.managedGiveVariableItemId); + const setManagedGiveVariableItemId = useWiredCreatorToolsUiStore(s => s.setManagedGiveVariableItemId); + const managedGiveValue = useWiredCreatorToolsUiStore(s => s.managedGiveValue); + const setManagedGiveValue = useWiredCreatorToolsUiStore(s => s.setManagedGiveValue); const isVariableHighlightActive = useWiredCreatorToolsUiStore(s => s.isVariableHighlightActive); const setIsVariableHighlightActive = useWiredCreatorToolsUiStore(s => s.setIsVariableHighlightActive); const variableHighlightOverlays = useWiredCreatorToolsUiStore(s => s.variableHighlightOverlays); diff --git a/src/components/wired-tools/wiredCreatorToolsUiStore.test.ts b/src/components/wired-tools/wiredCreatorToolsUiStore.test.ts index 22f7f39..49a6e04 100644 --- a/src/components/wired-tools/wiredCreatorToolsUiStore.test.ts +++ b/src/components/wired-tools/wiredCreatorToolsUiStore.test.ts @@ -32,7 +32,11 @@ const INITIAL = { selectedInspectionVariableKeys: { furni: '', user: '', global: '' }, selectedVariableKeys: { furni: '', user: '', global: '', context: '' }, inspectionGiveVariableItemId: 0, - inspectionGiveValue: '0' + inspectionGiveValue: '0', + selectedManagedVariableEntry: null, + selectedManagedHolderVariableId: 0, + managedGiveVariableItemId: 0, + managedGiveValue: '0' }; describe('useWiredCreatorToolsUiStore', () => @@ -76,6 +80,10 @@ describe('useWiredCreatorToolsUiStore', () => expect(state.selectedVariableKeys).toEqual({ furni: '', user: '', global: '', context: '' }); expect(state.inspectionGiveVariableItemId).toBe(0); expect(state.inspectionGiveValue).toBe('0'); + expect(state.selectedManagedVariableEntry).toBeNull(); + expect(state.selectedManagedHolderVariableId).toBe(0); + expect(state.managedGiveVariableItemId).toBe(0); + expect(state.managedGiveValue).toBe('0'); }); describe('setIsVisible', () => @@ -486,4 +494,61 @@ describe('useWiredCreatorToolsUiStore', () => expect(useWiredCreatorToolsUiStore.getState().inspectionGiveValue).toBe('0'); }); }); + + describe('managed holder give pickers', () => + { + const entry = { entityId: 7, entityName: 'fountain', categoryLabel: 'Furni', value: '12' } as never; + + it('setSelectedManagedVariableEntry writes the picked entry; null clears (reset path)', () => + { + useWiredCreatorToolsUiStore.getState().setSelectedManagedVariableEntry(entry); + expect(useWiredCreatorToolsUiStore.getState().selectedManagedVariableEntry).toEqual(entry); + + useWiredCreatorToolsUiStore.getState().setSelectedManagedVariableEntry(null); + expect(useWiredCreatorToolsUiStore.getState().selectedManagedVariableEntry).toBeNull(); + }); + + it('the holder + give picker chain writes through cleanly', () => + { + useWiredCreatorToolsUiStore.getState().setSelectedManagedHolderVariableId(11); + useWiredCreatorToolsUiStore.getState().setManagedGiveVariableItemId(33); + useWiredCreatorToolsUiStore.getState().setManagedGiveValue('75'); + + const state = useWiredCreatorToolsUiStore.getState(); + expect(state.selectedManagedHolderVariableId).toBe(11); + expect(state.managedGiveVariableItemId).toBe(33); + expect(state.managedGiveValue).toBe('75'); + }); + + it('post-give-action reset returns the give-side back to its 0 / "0" sentinels', () => + { + useWiredCreatorToolsUiStore.getState().setSelectedManagedHolderVariableId(11); + useWiredCreatorToolsUiStore.getState().setManagedGiveVariableItemId(33); + useWiredCreatorToolsUiStore.getState().setManagedGiveValue('75'); + + // Matches the post-action path at WiredCreatorToolsView.tsx:2400-2402: + // setSelectedManagedHolderVariableId(newId); + // setManagedGiveValue('0'); + useWiredCreatorToolsUiStore.getState().setSelectedManagedHolderVariableId(99); + useWiredCreatorToolsUiStore.getState().setManagedGiveValue('0'); + + expect(useWiredCreatorToolsUiStore.getState().selectedManagedHolderVariableId).toBe(99); + expect(useWiredCreatorToolsUiStore.getState().managedGiveValue).toBe('0'); + }); + + it('the managed picker chain persists across the panel close/reopen lifecycle', () => + { + useWiredCreatorToolsUiStore.getState().setSelectedManagedVariableEntry(entry); + useWiredCreatorToolsUiStore.getState().setSelectedManagedHolderVariableId(11); + useWiredCreatorToolsUiStore.getState().setManagedGiveVariableItemId(33); + + useWiredCreatorToolsUiStore.getState().setIsVisible(false); + useWiredCreatorToolsUiStore.getState().setIsVisible(true); + + const state = useWiredCreatorToolsUiStore.getState(); + expect(state.selectedManagedVariableEntry).toEqual(entry); + expect(state.selectedManagedHolderVariableId).toBe(11); + expect(state.managedGiveVariableItemId).toBe(33); + }); + }); }); diff --git a/src/components/wired-tools/wiredCreatorToolsUiStore.ts b/src/components/wired-tools/wiredCreatorToolsUiStore.ts index 0a5c18d..71c0c2c 100644 --- a/src/components/wired-tools/wiredCreatorToolsUiStore.ts +++ b/src/components/wired-tools/wiredCreatorToolsUiStore.ts @@ -1,6 +1,6 @@ import { createNitroStore } from '../../state/createNitroStore'; import { createEmptyMonitorSnapshot } from './WiredCreatorTools.helpers'; -import { InspectionElementType, InspectionFurniLiveState, InspectionFurniSelection, InspectionUserLiveState, InspectionUserSelection, MonitorSnapshot, VariableHighlightOverlay, VariablesElementType, WiredToolsTab } from './WiredCreatorTools.types'; +import { InspectionElementType, InspectionFurniLiveState, InspectionFurniSelection, InspectionUserLiveState, InspectionUserSelection, MonitorSnapshot, VariableHighlightOverlay, VariableManageEntry, VariablesElementType, WiredToolsTab } from './WiredCreatorTools.types'; type MonitorSeverityFilter = 'ALL' | 'ERROR' | 'WARNING'; type Updater = T | ((prev: T) => T); @@ -100,6 +100,19 @@ interface WiredCreatorToolsUiState inspectionGiveVariableItemId: number; inspectionGiveValue: string; + /** + * Variable-Manage panel — "managed holder" picker chain. Selecting + * an entry seeds the holder row, which seeds the give-variable + * picker. Sentinels: `null` entry / `0` holder-id / `0` give-id / + * `'0'` give-value. The cascade reset effects at + * WiredCreatorToolsView.tsx:2265-2307 keep these in sync as the + * upstream selection or available definitions change. + */ + selectedManagedVariableEntry: VariableManageEntry | null; + selectedManagedHolderVariableId: number; + managedGiveVariableItemId: number; + managedGiveValue: string; + setIsVisible: (next: Updater) => void; setActiveTab: (next: WiredToolsTab) => void; setInspectionType: (next: InspectionElementType) => void; @@ -140,6 +153,11 @@ interface WiredCreatorToolsUiState setInspectionGiveVariableItemId: (next: number) => void; setInspectionGiveValue: (next: string) => void; + + setSelectedManagedVariableEntry: (next: VariableManageEntry | null) => void; + setSelectedManagedHolderVariableId: (next: number) => void; + setManagedGiveVariableItemId: (next: number) => void; + setManagedGiveValue: (next: string) => void; } export const useWiredCreatorToolsUiStore = createNitroStore()((set) => ({ @@ -183,6 +201,11 @@ export const useWiredCreatorToolsUiStore = createNitroStore set(state => ({ isVisible: apply(state.isVisible, next) })), setActiveTab: (next) => set({ activeTab: next }), setInspectionType: (next) => set({ inspectionType: next }), @@ -222,5 +245,10 @@ export const useWiredCreatorToolsUiStore = createNitroStore set(state => ({ selectedVariableKeys: apply(state.selectedVariableKeys, next) })), setInspectionGiveVariableItemId: (next) => set({ inspectionGiveVariableItemId: next }), - setInspectionGiveValue: (next) => set({ inspectionGiveValue: next }) + setInspectionGiveValue: (next) => set({ inspectionGiveValue: next }), + + setSelectedManagedVariableEntry: (next) => set({ selectedManagedVariableEntry: next }), + setSelectedManagedHolderVariableId: (next) => set({ selectedManagedHolderVariableId: next }), + setManagedGiveVariableItemId: (next) => set({ managedGiveVariableItemId: next }), + setManagedGiveValue: (next) => set({ managedGiveValue: next }) }));