fix: Spire tab maxFloorReached undefined error
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 2m43s

This commit is contained in:
2026-05-08 13:24:37 +02:00
parent c6d3e0d7bc
commit e4fb66df9f
8 changed files with 295 additions and 21 deletions
+45 -19
View File
@@ -3,21 +3,47 @@
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { ChevronUp, ChevronDown, Mountain, Shield, Skull, Heart, Wind, ShieldCheck } from 'lucide-react';
import { ChevronUp, ChevronDown, Mountain, Skull } from 'lucide-react';
import { ELEMENTS } from '@/lib/game/constants';
import type { FloorControlsProps } from '@/lib/game/types';
const ROOM_TYPE_CONFIG: Record<string, { label: string; icon: string; color: string }> = {
combat: { label: 'Combat', icon: '⚔️', color: '#EF4444' },
swarm: { label: 'Swarm', icon: '🐝', color: '#F59E0B' },
speed: { label: 'Speed', icon: '💨', color: '#3B82F6' },
guardian: { label: 'Guardian', icon: '🛡️', color: '#EF4444' },
puzzle: { label: 'Puzzle', icon: '🧩', color: '#8B5CF6' },
};
interface FloorControlsProps {
// Store values passed as individual props
currentFloor: number;
floorHP: number;
floorMaxHP: number;
maxFloorReached: number;
equipmentSpellStates: any[];
// Other props
climbDirection: 'up' | 'down' | null;
isGuardianFloor: boolean;
currentRoom: any;
currentGuardian: any;
isFloorCleared: boolean;
floorElemDef: any;
roomType: string;
roomConfig: { label: string; icon: string; color: string };
activeEquipmentSpells: any[];
floorElem: string;
totalDPS: number;
calcDamage: (state: { skills: Record<string, number>; signedPacts: number[] }, spellId: string, floorElem?: string) => number;
SPELLS_DEF: Record<string, any>;
canCastSpell: (spellId: string) => boolean;
storeCurrentAction: string;
handleClimb: (direction: 'up' | 'down') => void;
formatSpellCost: (cost: any) => string;
getSpellCostColor: (cost: any) => string;
// Skills and pacts needed for calcDamage
skills: Record<string, number>;
signedPacts: number[];
}
export function FloorControls({
store,
currentFloor,
floorHP,
floorMaxHP,
maxFloorReached,
equipmentSpellStates,
climbDirection,
isGuardianFloor,
currentRoom,
@@ -27,10 +53,8 @@ export function FloorControls({
roomType,
roomConfig,
activeEquipmentSpells,
upgradeEffects,
floorElem,
totalDPS,
getEnemyName,
calcDamage,
SPELLS_DEF,
canCastSpell,
@@ -38,6 +62,8 @@ export function FloorControls({
handleClimb,
formatSpellCost,
getSpellCostColor,
skills,
signedPacts,
}: FloorControlsProps) {
return (
<Card className="bg-gray-900/80 border-gray-700">
@@ -50,7 +76,7 @@ export function FloorControls({
variant="outline"
size="sm"
onClick={() => handleClimb('up')}
disabled={storeCurrentAction === 'climb' || isFloorCleared || store.maxFloorReached >= 100}
disabled={storeCurrentAction === 'climb' || isFloorCleared || maxFloorReached >= 100}
className="border-gray-600 hover:bg-gray-800"
>
<ChevronUp className="w-4 h-4 mr-1" />
@@ -60,7 +86,7 @@ export function FloorControls({
variant="outline"
size="sm"
onClick={() => handleClimb('down')}
disabled={storeCurrentAction === 'climb' || store.currentFloor <= 1}
disabled={storeCurrentAction === 'climb' || currentFloor <= 1}
className="border-gray-600 hover:bg-gray-800"
>
<ChevronDown className="w-4 h-4 mr-1" />
@@ -97,14 +123,14 @@ export function FloorControls({
<div
className="h-full rounded-full transition-all duration-300"
style={{
width: `${Math.max(0, (store.floorHP / store.floorMaxHP) * 100)}%`,
width: `${Math.max(0, (floorHP / floorMaxHP) * 100)}%`,
background: `linear-gradient(90deg, ${floorElemDef?.color}99, ${floorElemDef?.color})`,
boxShadow: `0 0 8px ${floorElemDef?.glow}`,
}}
/>
</div>
<div className="flex justify-between text-xs text-gray-400">
<span>{fmt(store.floorHP)} / {fmt(store.floorMaxHP)} HP</span>
<span>{fmt(floorHP)} / {fmt(floorMaxHP)} HP</span>
<span className="text-amber-400">
DPS: {activeEquipmentSpells.length > 0 ? fmtDec(totalDPS) : '—'}
</span>
@@ -117,7 +143,7 @@ export function FloorControls({
{activeEquipmentSpells.map(({ spellId, equipmentId }) => {
const spellDef = SPELLS_DEF[spellId];
if (!spellDef) return null;
const spellState = store.equipmentSpellStates?.find(
const spellState = equipmentSpellStates?.find(
s => s.spellId === spellId && s.sourceEquipment === equipmentId
);
const progress = spellState?.castProgress || 0;
@@ -134,7 +160,7 @@ export function FloorControls({
</span>
</div>
<div className="text-xs text-gray-400 mb-1">
{fmt(calcDamage(store, spellId))} dmg {' '}
{fmt(calcDamage({ skills, signedPacts }, spellId, floorElem))} dmg {' '}
<span style={{ color: getSpellCostColor(spellDef.cost) }}>
{formatSpellCost(spellDef.cost)}
</span>
+7 -2
View File
@@ -292,6 +292,13 @@ export function SpireTab({ simpleMode = false }: SpireTabProps) {
{/* Floor Controls */}
{simpleMode && (
<FloorControls
currentFloor={currentFloor}
floorHP={floorHP}
floorMaxHP={floorMaxHP}
maxFloorReached={maxFloorReached}
equipmentSpellStates={equipmentSpellStates}
skills={skills}
signedPacts={signedPacts}
storeCurrentAction={currentAction}
climbDirection={climbDirection}
isGuardianFloor={isGuardianFloor}
@@ -302,10 +309,8 @@ export function SpireTab({ simpleMode = false }: SpireTabProps) {
roomType={roomType}
roomConfig={roomConfig}
activeEquipmentSpells={activeEquipmentSpells}
upgradeEffects={upgradeEffects}
floorElem={floorElem}
totalDPS={totalDPS}
getEnemyName={getEnemyName}
calcDamage={calcDamage}
SPELLS_DEF={SPELLS_DEF}
canCastSpell={canCastSpell}