fix: update SpellsTab to use modular stores, fixing tab crash
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m42s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m42s
This commit is contained in:
@@ -1,34 +1,44 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { useCombatStore, useManaStore, useSkillStore } from '@/lib/game/stores';
|
||||||
import { GameCard, ElementBadge } from '@/components/ui';
|
import { GameCard, ElementBadge } from '@/components/ui';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { ELEMENTS, SPELLS_DEF } from '@/lib/game/constants';
|
import { ELEMENTS, SPELLS_DEF } from '@/lib/game/constants';
|
||||||
import { ENCHANTMENT_EFFECTS } from '@/lib/game/data/enchantment-effects';
|
import { ENCHANTMENT_EFFECTS } from '@/lib/game/data/enchantment-effects';
|
||||||
import { canAffordSpellCost } from '@/lib/game/store';
|
import { canAffordSpellCost } from '@/lib/game/stores';
|
||||||
import { formatSpellCost, getSpellCostColor } from '@/lib/game/formatting';
|
import { formatSpellCost, getSpellCostColor } from '@/lib/game/formatting';
|
||||||
|
|
||||||
interface SpellsTabProps {
|
export function SpellsTab() {
|
||||||
store: {
|
// Use modular stores directly
|
||||||
spells: Record<string, { learned: boolean; level: number; studyProgress: number }>;
|
const spells = useCombatStore((s) => s.spells);
|
||||||
equippedInstances: Record<string, string | null>;
|
const activeSpell = useCombatStore((s) => s.activeSpell);
|
||||||
equipmentInstances: Record<string, { instanceId: string; name: string; enchantments: { effectId: string; stacks: number }[] }>;
|
const setSpell = useCombatStore((s) => s.setSpell);
|
||||||
activeSpell: string;
|
|
||||||
rawMana: number;
|
const equippedInstances = useCombatStore((s) => s.equippedInstances);
|
||||||
elements: Record<string, { current: number; max: number; unlocked: boolean }>;
|
const equipmentInstances = useCombatStore((s) => s.equipmentInstances);
|
||||||
signedPacts: number[];
|
|
||||||
unlockedEffects: string[];
|
const rawMana = useManaStore((s) => s.rawMana);
|
||||||
setSpell: (spellId: string) => void;
|
const elements = useManaStore((s) => s.elements);
|
||||||
};
|
|
||||||
}
|
const signedPacts = useSkillStore((s) => s.signedPacts);
|
||||||
|
const unlockedEffects = useSkillStore((s) => s.unlockedEffects);
|
||||||
|
|
||||||
export function SpellsTab({ store }: SpellsTabProps) {
|
|
||||||
// Get spells from equipment
|
// Get spells from equipment
|
||||||
const equipmentSpellIds: string[] = [];
|
const equipmentSpellIds: string[] = [];
|
||||||
const spellSources: Record<string, string[]> = {};
|
const spellSources: Record<string, string[]> = {};
|
||||||
|
|
||||||
for (const instanceId of Object.values(store.equippedInstances)) {
|
// Guard against undefined stores during initialization
|
||||||
|
if (!equippedInstances || !equipmentInstances) {
|
||||||
|
return (
|
||||||
|
<div className="p-4 text-center text-[var(--text-muted)]">
|
||||||
|
Loading spell data...
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const instanceId of Object.values(equippedInstances)) {
|
||||||
if (!instanceId) continue;
|
if (!instanceId) continue;
|
||||||
const instance = store.equipmentInstances[instanceId];
|
const instance = equipmentInstances[instanceId];
|
||||||
if (!instance) continue;
|
if (!instance) continue;
|
||||||
|
|
||||||
for (const ench of instance.enchantments) {
|
for (const ench of instance.enchantments) {
|
||||||
@@ -49,10 +59,10 @@ export function SpellsTab({ store }: SpellsTabProps) {
|
|||||||
const canCastSpell = (spellId: string): boolean => {
|
const canCastSpell = (spellId: string): boolean => {
|
||||||
const spell = SPELLS_DEF[spellId];
|
const spell = SPELLS_DEF[spellId];
|
||||||
if (!spell || !spell.cost) return false;
|
if (!spell || !spell.cost) return false;
|
||||||
return canAffordSpellCost(spell.cost, store.rawMana, store.elements);
|
return canAffordSpellCost(spell.cost, rawMana, elements);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasPactSpells = store.signedPacts.length > 0;
|
const hasPactSpells = signedPacts && signedPacts.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
@@ -72,7 +82,7 @@ export function SpellsTab({ store }: SpellsTabProps) {
|
|||||||
const def = SPELLS_DEF[id];
|
const def = SPELLS_DEF[id];
|
||||||
if (!def) return null;
|
if (!def) return null;
|
||||||
|
|
||||||
const isActive = store.activeSpell === id;
|
const isActive = activeSpell === id;
|
||||||
const canCast = canCastSpell(id);
|
const canCast = canCastSpell(id);
|
||||||
const elemDef = def.elem === 'raw' ? null : ELEMENTS[def.elem];
|
const elemDef = def.elem === 'raw' ? null : ELEMENTS[def.elem];
|
||||||
const sources = spellSources[id] || [];
|
const sources = spellSources[id] || [];
|
||||||
@@ -116,7 +126,7 @@ export function SpellsTab({ store }: SpellsTabProps) {
|
|||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
className="px-3 py-1 text-xs border border-[var(--border-default)] rounded hover:border-[var(--border-focus)] transition-colors"
|
className="px-3 py-1 text-xs border border-[var(--border-default)] rounded hover:border-[var(--border-focus)] transition-colors"
|
||||||
onClick={() => store.setSpell(id)}
|
onClick={() => setSpell(id)}
|
||||||
>
|
>
|
||||||
Set Active
|
Set Active
|
||||||
</button>
|
</button>
|
||||||
@@ -169,7 +179,7 @@ export function SpellsTab({ store }: SpellsTabProps) {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{Object.entries(SPELLS_DEF).map(([id, def]) => {
|
{Object.entries(SPELLS_DEF).map(([id, def]) => {
|
||||||
const elemDef = def.elem === 'raw' ? null : ELEMENTS[def.elem];
|
const elemDef = def.elem === 'raw' ? null : ELEMENTS[def.elem];
|
||||||
const isUnlocked = store.unlockedEffects?.includes(`spell_${id}`);
|
const isUnlocked = unlockedEffects?.includes(`spell_${id}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GameCard
|
<GameCard
|
||||||
|
|||||||
Reference in New Issue
Block a user