fix(spire): reset currentAction to meditate on spire exit; fix(crafting): wire enchanting state hooks to EnchantmentDesigner/Preparer/Applier
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m53s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m53s
This commit is contained in:
@@ -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<string | null>(null);
|
||||
const [selectedEffects, setSelectedEffects] = useState<DesignEffect[]>([]);
|
||||
const [designName, setDesignName] = useState('');
|
||||
const [selectedDesign, setSelectedDesign] = useState<string | null>(null);
|
||||
const [selectedEquipmentInstance, setSelectedEquipmentInstance] = useState<string | null>(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' && (
|
||||
<EnchantmentDesigner
|
||||
selectedEquipmentType={null}
|
||||
setSelectedEquipmentType={() => {}}
|
||||
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' && (
|
||||
<EnchantmentPreparer
|
||||
selectedEquipmentInstance={null}
|
||||
setSelectedEquipmentInstance={() => {}}
|
||||
selectedEquipmentInstance={selectedEquipmentInstance}
|
||||
setSelectedEquipmentInstance={setSelectedEquipmentInstance}
|
||||
/>
|
||||
)}
|
||||
{enchantStage === 'apply' && (
|
||||
<EnchantmentApplier
|
||||
selectedEquipmentInstance={null}
|
||||
setSelectedEquipmentInstance={() => {}}
|
||||
selectedDesign={null}
|
||||
setSelectedDesign={() => {}}
|
||||
selectedEquipmentInstance={selectedEquipmentInstance}
|
||||
setSelectedEquipmentInstance={setSelectedEquipmentInstance}
|
||||
selectedDesign={selectedDesign}
|
||||
setSelectedDesign={setSelectedDesign}
|
||||
onEnchantmentApplied={handleEnchantmentApplied}
|
||||
onCapacityExceeded={handleCapacityExceeded}
|
||||
/>
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -253,7 +253,7 @@ export const useCombatStore = create<CombatState>()(
|
||||
},
|
||||
|
||||
exitSpireMode: () => {
|
||||
set({ spireMode: false, climbDirection: null, isDescending: false });
|
||||
set({ spireMode: false, currentAction: 'meditate', climbDirection: null, isDescending: false });
|
||||
},
|
||||
|
||||
startClimbUp: () => set({ climbDirection: 'up', currentAction: 'climb' }),
|
||||
|
||||
Reference in New Issue
Block a user