fix: persist CraftingTab sub-tab selection across tab navigation
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m28s

- Add activeCraftingSubTab state + setActiveCraftingSubTab action to
  craftingStore (persisted to localStorage via zustand persist middleware)
- Add CraftingAttunement type to craftingStore.types and re-export from
  stores/index.ts barrel
- Update CraftingTab.tsx to read/write active sub-tab from store instead
  of local useState, so selection survives component remount
- Add default 'fabricator' value in craft-initial-state.ts
This commit is contained in:
2026-06-09 19:08:49 +02:00
parent 28d39a61ba
commit 8bca8f85d5
7 changed files with 15 additions and 7 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# Circular Dependencies # Circular Dependencies
Generated: 2026-06-09T13:31:30.036Z Generated: 2026-06-09T16:48:20.172Z
Found: 2 circular chain(s) — these MUST be fixed before modifying involved files. Found: 2 circular chain(s) — these MUST be fixed before modifying involved files.
1. 1) stores/golem-combat-actions.ts > stores/golem-combat-helpers.ts 1. 1) stores/golem-combat-actions.ts > stores/golem-combat-helpers.ts
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_meta": { "_meta": {
"generated": "2026-06-09T13:31:28.048Z", "generated": "2026-06-09T16:48:18.218Z",
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.", "description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry." "usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
}, },
+4 -4
View File
@@ -1,14 +1,13 @@
'use client'; 'use client';
import { useState } from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import { Hammer, Sparkles } from 'lucide-react'; import { Hammer, Sparkles } from 'lucide-react';
import { DebugName } from '@/components/game/debug/debug-context'; import { DebugName } from '@/components/game/debug/debug-context';
import { useCraftingStore } from '@/lib/game/stores/craftingStore';
import type { CraftingAttunement } from '@/lib/game/stores/craftingStore.types';
import { FabricatorSubTab } from './CraftingTab/FabricatorSubTab'; import { FabricatorSubTab } from './CraftingTab/FabricatorSubTab';
import { EnchanterSubTab } from './CraftingTab/EnchanterSubTab'; import { EnchanterSubTab } from './CraftingTab/EnchanterSubTab';
type CraftingAttunement = 'fabricator' | 'enchanter';
interface CraftingSubTab { interface CraftingSubTab {
key: CraftingAttunement; key: CraftingAttunement;
label: string; label: string;
@@ -21,7 +20,8 @@ const CRAFTING_SUB_TABS: CraftingSubTab[] = [
]; ];
export function CraftingTab() { export function CraftingTab() {
const [activeSubTab, setActiveSubTab] = useState<CraftingAttunement>('fabricator'); const activeSubTab = useCraftingStore((s) => s.activeCraftingSubTab);
const setActiveSubTab = useCraftingStore((s) => s.setActiveCraftingSubTab);
return ( return (
<DebugName name="CraftingTab"> <DebugName name="CraftingTab">
@@ -34,6 +34,7 @@ export function createDefaultCraftingState(): CraftingState {
selectedEquipmentInstance: null, selectedEquipmentInstance: null,
}, },
lastError: null, lastError: null,
activeCraftingSubTab: 'fabricator',
}; };
} }
+3
View File
@@ -285,6 +285,8 @@ export const useCraftingStore = create<CraftingStore>()(
clearLastError: () => set({ lastError: null }), clearLastError: () => set({ lastError: null }),
setActiveCraftingSubTab: (tab) => set({ activeCraftingSubTab: tab }),
unlockEffects: (effectIds: string[]) => { unlockEffects: (effectIds: string[]) => {
set((state) => { set((state) => {
const existing = new Set(state.unlockedEffects); const existing = new Set(state.unlockedEffects);
@@ -343,6 +345,7 @@ export const useCraftingStore = create<CraftingStore>()(
lootInventory: state.lootInventory, lootInventory: state.lootInventory,
enchantmentSelection: state.enchantmentSelection, enchantmentSelection: state.enchantmentSelection,
lastError: state.lastError, lastError: state.lastError,
activeCraftingSubTab: state.activeCraftingSubTab,
}), }),
} }
) )
@@ -16,6 +16,8 @@ export interface CraftingError {
timestamp: number; timestamp: number;
} }
export type CraftingAttunement = 'fabricator' | 'enchanter';
export interface CraftingState { export interface CraftingState {
designProgress: DesignProgress | null; designProgress: DesignProgress | null;
designProgress2: DesignProgress | null; designProgress2: DesignProgress | null;
@@ -39,6 +41,7 @@ export interface CraftingState {
selectedEquipmentInstance: string | null; selectedEquipmentInstance: string | null;
}; };
lastError: CraftingError | null; lastError: CraftingError | null;
activeCraftingSubTab: CraftingAttunement;
} }
export interface CraftingActions { export interface CraftingActions {
@@ -47,6 +50,7 @@ export interface CraftingActions {
setPreparationProgress: (progress: PreparationProgress | null) => void; setPreparationProgress: (progress: PreparationProgress | null) => void;
setApplicationProgress: (progress: ApplicationProgress | null) => void; setApplicationProgress: (progress: ApplicationProgress | null) => void;
setEquipmentCraftingProgress: (progress: EquipmentCraftingProgress | null) => void; setEquipmentCraftingProgress: (progress: EquipmentCraftingProgress | null) => void;
setActiveCraftingSubTab: (tab: CraftingAttunement) => void;
startDesigningEnchantment: (name: string, equipmentTypeId: string, effects: DesignEffect[]) => boolean; startDesigningEnchantment: (name: string, equipmentTypeId: string, effects: DesignEffect[]) => boolean;
cancelDesign: (slot?: 1 | 2) => void; cancelDesign: (slot?: 1 | 2) => void;
saveDesign: (design: EnchantmentDesign) => void; saveDesign: (design: EnchantmentDesign) => void;
+1 -1
View File
@@ -15,7 +15,7 @@ export { useCombatStore, makeInitialSpells } from './combatStore';
export type { CombatState, CombatActions, CombatStore } from './combat-state.types'; export type { CombatState, CombatActions, CombatStore } from './combat-state.types';
export { useCraftingStore } from './craftingStore'; export { useCraftingStore } from './craftingStore';
export type { CraftingState, CraftingActions } from './craftingStore.types'; export type { CraftingState, CraftingActions, CraftingStore, CraftingAttunement } from './craftingStore.types';
export { useAttunementStore } from './attunementStore'; export { useAttunementStore } from './attunementStore';
export type { AttunementStoreState } from './attunementStore'; export type { AttunementStoreState } from './attunementStore';