diff --git a/docs/project-structure.txt b/docs/project-structure.txt index e1a3b11..3cfb998 100644 --- a/docs/project-structure.txt +++ b/docs/project-structure.txt @@ -397,6 +397,7 @@ Mana-Loop/ │ │ │ │ ├── regen.test.ts │ │ │ │ ├── skill.test.ts │ │ │ │ ├── spell-cost.test.ts +│ │ │ │ ├── spire-exit-action.test.ts │ │ │ │ └── spire-tab-refresh.test.ts │ │ │ ├── attunementStore.ts │ │ │ ├── combat-actions.ts diff --git a/src/components/game/tabs/CraftingTab.tsx b/src/components/game/tabs/CraftingTab.tsx index 617cc50..9ddf03a 100755 --- a/src/components/game/tabs/CraftingTab.tsx +++ b/src/components/game/tabs/CraftingTab.tsx @@ -16,6 +16,7 @@ import { import { useCombatStore, useCraftingStore } from '@/lib/game/stores'; import { DebugName } from '@/lib/game/debug-context'; import { useGameToast } from '@/components/game/GameToast'; +import type { DesignEffect } from '@/lib/game/types'; export function CraftingTab() { const showToast = useGameToast(); @@ -30,6 +31,13 @@ export function CraftingTab() { const [activeTab, setActiveTab] = useState<'fabricate' | 'enchant'>('fabricate'); const [enchantStage, setEnchantStage] = useState<'design' | 'prepare' | 'apply'>('design'); + // Enchant state + const [selectedEquipmentType, setSelectedEquipmentType] = useState(null); + const [selectedEffects, setSelectedEffects] = useState([]); + const [designName, setDesignName] = useState(''); + const [selectedDesign, setSelectedDesign] = useState(null); + const [selectedEquipmentInstance, setSelectedEquipmentInstance] = useState(null); + // Safe toFixed helper const safeToFixed = (value: number | undefined, decimals: number = 0): string => { if (value === undefined || isNaN(value)) return '0'; @@ -121,28 +129,28 @@ export function CraftingTab() { {/* Enchant Stage Content */} {enchantStage === 'design' && ( {}} - selectedEffects={[]} - setSelectedEffects={() => {}} - designName={''} - setDesignName={() => {}} - selectedDesign={null} - setSelectedDesign={() => {}} + selectedEquipmentType={selectedEquipmentType} + setSelectedEquipmentType={setSelectedEquipmentType} + selectedEffects={selectedEffects} + setSelectedEffects={setSelectedEffects} + designName={designName} + setDesignName={setDesignName} + selectedDesign={selectedDesign} + setSelectedDesign={setSelectedDesign} /> )} {enchantStage === 'prepare' && ( {}} + selectedEquipmentInstance={selectedEquipmentInstance} + setSelectedEquipmentInstance={setSelectedEquipmentInstance} /> )} {enchantStage === 'apply' && ( {}} - selectedDesign={null} - setSelectedDesign={() => {}} + selectedEquipmentInstance={selectedEquipmentInstance} + setSelectedEquipmentInstance={setSelectedEquipmentInstance} + selectedDesign={selectedDesign} + setSelectedDesign={setSelectedDesign} onEnchantmentApplied={handleEnchantmentApplied} onCapacityExceeded={handleCapacityExceeded} /> diff --git a/src/lib/game/stores/__tests__/spire-exit-action.test.ts b/src/lib/game/stores/__tests__/spire-exit-action.test.ts new file mode 100644 index 0000000..f427ee8 --- /dev/null +++ b/src/lib/game/stores/__tests__/spire-exit-action.test.ts @@ -0,0 +1,64 @@ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { useCombatStore } from '../combatStore'; +import { useUIStore } from '../uiStore'; + +describe('Spire Exit Action — Bug 1 Fix', () => { + beforeEach(() => { + // Reset combat store to a known state + useCombatStore.setState({ + currentFloor: 5, + floorHP: 100, + floorMaxHP: 100, + maxFloorReached: 5, + activeSpell: 'manaBolt', + currentAction: 'climb' as const, + castProgress: 0, + spireMode: true, + climbDirection: 'down' as const, + isDescending: true, + }); + }); + + afterEach(() => { + useCombatStore.setState({ + currentFloor: 1, + floorHP: 100, + floorMaxHP: 100, + maxFloorReached: 1, + activeSpell: 'manaBolt', + currentAction: 'meditate', + castProgress: 0, + spireMode: false, + climbDirection: null, + isDescending: false, + }); + useUIStore.setState({ logs: [] }); + }); + + it('should reset currentAction to "meditate" when exitSpireMode is called', () => { + // Pre-condition: action is "climb" while in spire + expect(useCombatStore.getState().currentAction).toBe('climb'); + expect(useCombatStore.getState().spireMode).toBe(true); + + // Exit spire mode + useCombatStore.getState().exitSpireMode(); + + // Post-condition: currentAction must be "meditate" + expect(useCombatStore.getState().currentAction).toBe('meditate'); + }); + + it('should set spireMode to false when exitSpireMode is called', () => { + useCombatStore.getState().exitSpireMode(); + expect(useCombatStore.getState().spireMode).toBe(false); + }); + + it('should clear climbDirection when exitSpireMode is called', () => { + useCombatStore.getState().exitSpireMode(); + expect(useCombatStore.getState().climbDirection).toBeNull(); + }); + + it('should clear isDescending when exitSpireMode is called', () => { + useCombatStore.getState().exitSpireMode(); + expect(useCombatStore.getState().isDescending).toBe(false); + }); +}); \ No newline at end of file diff --git a/src/lib/game/stores/combatStore.ts b/src/lib/game/stores/combatStore.ts index 822b020..a695e15 100755 --- a/src/lib/game/stores/combatStore.ts +++ b/src/lib/game/stores/combatStore.ts @@ -253,7 +253,7 @@ export const useCombatStore = create()( }, exitSpireMode: () => { - set({ spireMode: false, climbDirection: null, isDescending: false }); + set({ spireMode: false, currentAction: 'meditate', climbDirection: null, isDescending: false }); }, startClimbUp: () => set({ climbDirection: 'up', currentAction: 'climb' }),