feat: add DebugName wrappers to 56 components + redesign attunement cards + remove ScrollArea from AttunementsTab
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m31s

This commit is contained in:
2026-05-28 15:28:18 +02:00
parent 9671078fea
commit 13c185a216
59 changed files with 781 additions and 539 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
# Circular Dependencies # Circular Dependencies
Generated: 2026-05-28T11:15:20.183Z Generated: 2026-05-28T11:45:27.810Z
No circular dependencies found. ✅ No circular dependencies found. ✅
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_meta": { "_meta": {
"generated": "2026-05-28T11:15:18.333Z", "generated": "2026-05-28T11:45:26.075Z",
"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."
}, },
+3
View File
@@ -21,6 +21,7 @@ import { useGameLoop } from '@/lib/game/stores/gameHooks';
import { getUnifiedEffects } from '@/lib/game/effects'; import { getUnifiedEffects } from '@/lib/game/effects';
import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects'; import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects';
import { TimeDisplay } from '@/components/game'; import { TimeDisplay } from '@/components/game';
import { DebugName } from '@/components/game/debug/debug-context';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { TooltipProvider } from '@/components/ui/tooltip'; import { TooltipProvider } from '@/components/ui/tooltip';
@@ -197,6 +198,7 @@ export default function ManaLoopGame() {
} }
return ( return (
<DebugName name="HomePage">
<ErrorBoundary> <ErrorBoundary>
<TooltipProvider> <TooltipProvider>
<div className="game-root min-h-screen flex flex-col"> <div className="game-root min-h-screen flex flex-col">
@@ -235,5 +237,6 @@ export default function ManaLoopGame() {
</div> </div>
</TooltipProvider> </TooltipProvider>
</ErrorBoundary> </ErrorBoundary>
</DebugName>
); );
} }
+28 -25
View File
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { Sparkles, Swords, BookOpen, Target, FlaskConical, Cog, Hammer, Dumbbell } from 'lucide-react'; import { Sparkles, Swords, BookOpen, Target, FlaskConical, Cog, Hammer, Dumbbell } from 'lucide-react';
import { DebugName } from '@/components/game/debug/debug-context';
import type { GameAction } from '@/lib/game/types'; import type { GameAction } from '@/lib/game/types';
interface ActionButtonsProps { interface ActionButtonsProps {
@@ -119,33 +120,35 @@ export function ActionButtons({
}; };
return ( return (
<div className="space-y-2"> <DebugName name="ActionButtons">
<div className="bg-gray-800/50 rounded-lg p-3 border border-gray-700"> <div className="space-y-2">
<div className="flex items-center gap-2"> <div className="bg-gray-800/50 rounded-lg p-3 border border-gray-700">
<Icon className={`w-4 h-4 ${config.color}`} /> <div className="flex items-center gap-2">
<span className="text-sm font-medium text-gray-200">Current Activity</span> <Icon className={`w-4 h-4 ${config.color}`} />
</div> <span className="text-sm font-medium text-gray-200">Current Activity</span>
<div className={`text-lg font-semibold mt-1 ${config.color}`}>
{config.label}
</div>
{getActionDetails()}
{/* Show second design slot if active */}
{designProgress2 && (
<div className="mt-2 pt-2 border-t border-gray-700">
<div className="flex items-center gap-2">
<Target className="w-3 h-3 text-purple-400" />
<span className="text-xs text-gray-400">Second Design Slot</span>
</div>
<ProgressBar
progress={designProgress2.progress}
required={designProgress2.required}
label="Design progress"
/>
</div> </div>
)} <div className={`text-lg font-semibold mt-1 ${config.color}`}>
{config.label}
</div>
{getActionDetails()}
{/* Show second design slot if active */}
{designProgress2 && (
<div className="mt-2 pt-2 border-t border-gray-700">
<div className="flex items-center gap-2">
<Target className="w-3 h-3 text-purple-400" />
<span className="text-xs text-gray-400">Second Design Slot</span>
</div>
<ProgressBar
progress={designProgress2.progress}
required={designProgress2.required}
label="Design progress"
/>
</div>
)}
</div>
</div> </div>
</div> </DebugName>
); );
} }
+4 -1
View File
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { useCombatStore } from '@/lib/game/stores'; import { useCombatStore } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
import { ActivityLog } from './tabs/ActivityLog'; import { ActivityLog } from './tabs/ActivityLog';
/** /**
@@ -12,7 +13,9 @@ export function ActivityLogPanel() {
const activityLog = useCombatStore((s) => s.activityLog); const activityLog = useCombatStore((s) => s.activityLog);
return ( return (
<ActivityLog activityLog={activityLog} maxEntries={20} /> <DebugName name="ActivityLogPanel">
<ActivityLog activityLog={activityLog} maxEntries={20} />
</DebugName>
); );
} }
+61 -58
View File
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { DebugName } from '@/components/game/debug/debug-context';
import { useAttunementStore } from '@/lib/game/stores'; import { useAttunementStore } from '@/lib/game/stores';
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements'; import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
@@ -38,70 +39,72 @@ export function AttunementStatus() {
}; };
return ( return (
<div className="space-y-1"> <DebugName name="AttunementStatus">
<div className="flex items-center justify-between"> <div className="space-y-1">
<span className="text-[10px] uppercase tracking-wider text-[var(--text-muted)] font-bold">Attunements</span> <div className="flex items-center justify-between">
<span className="text-[10px] text-[var(--text-muted)]">{activeAttunements.length} active</span> <span className="text-[10px] uppercase tracking-wider text-[var(--text-muted)] font-bold">Attunements</span>
</div> <span className="text-[10px] text-[var(--text-muted)]">{activeAttunements.length} active</span>
<Separator className="bg-[var(--border-subtle)]" /> </div>
<div className="space-y-1.5"> <Separator className="bg-[var(--border-subtle)]" />
{activeAttunements.length === 0 ? ( <div className="space-y-1.5">
<div className="text-[10px] text-[var(--text-muted)] italic">No attunements active</div> {activeAttunements.length === 0 ? (
) : ( <div className="text-[10px] text-[var(--text-muted)] italic">No attunements active</div>
activeAttunements.map(([id, state]) => { ) : (
const def = ATTUNEMENTS_DEF[id]; activeAttunements.map(([id, state]) => {
if (!def) return null; const def = ATTUNEMENTS_DEF[id];
const nextXp = xpForNext(state.level); if (!def) return null;
const xpProgress = nextXp > 0 ? (state.experience / nextXp) * 100 : 0; const nextXp = xpForNext(state.level);
const xpProgress = nextXp > 0 ? (state.experience / nextXp) * 100 : 0;
return ( return (
<TooltipProvider key={id}> <TooltipProvider key={id}>
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<div className="flex items-center gap-2 p-1.5 rounded bg-[var(--bg-sunken)]/50 border border-[var(--border-subtle)]"> <div className="flex items-center gap-2 p-1.5 rounded bg-[var(--bg-sunken)]/50 border border-[var(--border-subtle)]">
<span className="text-sm">{def.icon}</span> <span className="text-sm">{def.icon}</span>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span className="text-[11px] font-medium text-[var(--text-primary)] truncate"> <span className="text-[11px] font-medium text-[var(--text-primary)] truncate">
{def.name} {def.name}
</span>
<span className="text-[10px] text-[var(--text-secondary)] font-mono">
Lv.{state.level}
</span>
</div>
<div className="text-[10px] text-[var(--text-muted)]">
<span className="capitalize">{SLOT_LABELS[def.slot] || def.slot}</span>
{nextXp > 0 && (
<span className="ml-1.5 font-mono">
{Math.floor(state.experience).toLocaleString()}/{nextXp.toLocaleString()} XP
</span> </span>
<span className="text-[10px] text-[var(--text-secondary)] font-mono">
Lv.{state.level}
</span>
</div>
<div className="text-[10px] text-[var(--text-muted)]">
<span className="capitalize">{SLOT_LABELS[def.slot] || def.slot}</span>
{nextXp > 0 && (
<span className="ml-1.5 font-mono">
{Math.floor(state.experience).toLocaleString()}/{nextXp.toLocaleString()} XP
</span>
)}
</div>
{nextXp > 0 && (
<div className="w-full h-0.5 bg-[var(--border-subtle)] rounded-full mt-0.5 overflow-hidden">
<div
className="h-full transition-all duration-500"
style={{
width: `${Math.min(100, xpProgress)}%`,
backgroundColor: def.color,
opacity: 0.7,
}}
/>
</div>
)} )}
</div> </div>
{nextXp > 0 && (
<div className="w-full h-0.5 bg-[var(--border-subtle)] rounded-full mt-0.5 overflow-hidden">
<div
className="h-full transition-all duration-500"
style={{
width: `${Math.min(100, xpProgress)}%`,
backgroundColor: def.color,
opacity: 0.7,
}}
/>
</div>
)}
</div> </div>
</div> </TooltipTrigger>
</TooltipTrigger> <TooltipContent side="right">
<TooltipContent side="right"> <p className="text-xs max-w-[220px]">{def.desc}</p>
<p className="text-xs max-w-[220px]">{def.desc}</p> </TooltipContent>
</TooltipContent> </Tooltip>
</Tooltip> </TooltipProvider>
</TooltipProvider> );
); })
}) )}
)} </div>
</div> </div>
</div> </DebugName>
); );
} }
+15 -12
View File
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { DebugName } from '@/components/game/debug/debug-context';
import { import {
Toast, Toast,
ToastClose, ToastClose,
@@ -61,8 +62,9 @@ export function GameToaster() {
const { toasts } = useToast(); const { toasts } = useToast();
return ( return (
<ToastProvider> <DebugName name="GameToast">
{toasts.map((toast) => { <ToastProvider>
{toasts.map((toast) => {
// Determine toast type from className or default to info // Determine toast type from className or default to info
const toastType: ToastType = const toastType: ToastType =
toast.variant === 'destructive' ? 'error' : toast.variant === 'destructive' ? 'error' :
@@ -103,16 +105,17 @@ export function GameToaster() {
- Desktop: bottom-right - Desktop: bottom-right
- Mobile: bottom-center, full-width - Mobile: bottom-center, full-width
*/} */}
<ToastViewport <ToastViewport
className={cn( className={cn(
'fixed z-[100] flex max-h-screen w-full flex-col-reverse p-4', 'fixed z-[100] flex max-h-screen w-full flex-col-reverse p-4',
// Desktop: bottom-right, fixed width // Desktop: bottom-right, fixed width
'sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col sm:max-w-[420px]', 'sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col sm:max-w-[420px]',
// Mobile: bottom-center, full-width // Mobile: bottom-center, full-width
'max-sm:bottom-0 max-sm:left-0 max-sm:flex-col max-sm:items-center' 'max-sm:bottom-0 max-sm:left-0 max-sm:flex-col max-sm:items-center'
)} )}
/> />
</ToastProvider> </ToastProvider>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Scroll } from 'lucide-react'; import { Scroll } from 'lucide-react';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { LOOT_DROPS } from '@/lib/game/data/loot-drops'; import { LOOT_DROPS } from '@/lib/game/data/loot-drops';
@@ -13,6 +14,7 @@ export function BlueprintsSection({ blueprints }: BlueprintsSectionProps) {
if (blueprints.length === 0) return null; if (blueprints.length === 0) return null;
return ( return (
<DebugName name="BlueprintsSection">
<div> <div>
<div className="text-xs text-[var(--text-muted)] mb-2 flex items-center gap-1"> <div className="text-xs text-[var(--text-muted)] mb-2 flex items-center gap-1">
<Scroll className="w-3 h-3" /> <Scroll className="w-3 h-3" />
@@ -42,5 +44,6 @@ export function BlueprintsSection({ blueprints }: BlueprintsSectionProps) {
Blueprints are permanent unlocks - use them to craft equipment Blueprints are permanent unlocks - use them to craft equipment
</div> </div>
</div> </div>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Package, Trash2 } from 'lucide-react'; import { Package, Trash2 } from 'lucide-react';
import type { EquipmentInstance } from '@/lib/game/types'; import type { EquipmentInstance } from '@/lib/game/types';
import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment'; import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
@@ -20,6 +21,7 @@ export function EquipmentItem({ instanceId, instance, onDelete }: EquipmentItemP
const rarityGlow = RARITY_GLOW_CSS_VAR[instance.rarity] || 'var(--rarity-common-glow)'; const rarityGlow = RARITY_GLOW_CSS_VAR[instance.rarity] || 'var(--rarity-common-glow)';
return ( return (
<DebugName name="EquipmentItem">
<div <div
className="p-2 rounded border bg-[var(--bg-sunken)] group" className="p-2 rounded border bg-[var(--bg-sunken)] group"
style={{ style={{
@@ -55,6 +57,7 @@ export function EquipmentItem({ instanceId, instance, onDelete }: EquipmentItemP
)} )}
</div> </div>
</div> </div>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Droplet } from 'lucide-react'; import { Droplet } from 'lucide-react';
import { ElementBadge } from '@/components/ui/element-badge'; import { ElementBadge } from '@/components/ui/element-badge';
import type { ElementState } from '@/lib/game/types'; import type { ElementState } from '@/lib/game/types';
@@ -15,6 +16,7 @@ export function EssenceItem({ elementId, state }: EssenceItemProps) {
if (!elem) return null; if (!elem) return null;
return ( return (
<DebugName name="EssenceItem">
<div <div
className="p-2 rounded border bg-[var(--bg-sunken)]" className="p-2 rounded border bg-[var(--bg-sunken)]"
style={{ style={{
@@ -29,6 +31,7 @@ export function EssenceItem({ elementId, state }: EssenceItemProps) {
{state.current} / {state.max} {state.current} / {state.max}
</div> </div>
</div> </div>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import type { LootInventory } from '@/lib/game/types'; import type { LootInventory } from '@/lib/game/types';
// For backward compatibility // For backward compatibility
type LootInventoryType = LootInventory; type LootInventoryType = LootInventory;
@@ -22,6 +23,7 @@ export function MaterialItem({ materialId, count, onDelete }: MaterialItemProps)
const rarityGlow = RARITY_GLOW_CSS_VAR[drop.rarity] || 'var(--rarity-common-glow)'; const rarityGlow = RARITY_GLOW_CSS_VAR[drop.rarity] || 'var(--rarity-common-glow)';
return ( return (
<DebugName name="MaterialItem">
<div <div
className="p-2 rounded border bg-[var(--bg-sunken)] group relative" className="p-2 rounded border bg-[var(--bg-sunken)] group relative"
style={{ style={{
@@ -54,6 +56,7 @@ export function MaterialItem({ materialId, count, onDelete }: MaterialItemProps)
)} )}
</div> </div>
</div> </div>
</DebugName>
); );
} }
+7 -4
View File
@@ -7,6 +7,7 @@ import { Zap, ChevronDown, ChevronUp } from 'lucide-react';
import { fmt, fmtDec } from '@/lib/game/stores'; import { fmt, fmtDec } from '@/lib/game/stores';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
import { useState } from 'react'; import { useState } from 'react';
import { DebugName } from '@/components/game/debug/debug-context';
interface ManaDisplayProps { interface ManaDisplayProps {
rawMana: number; rawMana: number;
@@ -39,8 +40,9 @@ export function ManaDisplay({
.sort((a, b) => b[1].current - a[1].current); .sort((a, b) => b[1].current - a[1].current);
return ( return (
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <DebugName name="ManaDisplay">
<CardContent className="pt-4 space-y-3"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardContent className="pt-4 space-y-3">
{/* Raw Mana - Main Display */} {/* Raw Mana - Main Display */}
<div> <div>
<div className="flex items-baseline gap-1"> <div className="flex items-baseline gap-1">
@@ -133,8 +135,9 @@ export function ManaDisplay({
)} )}
</div> </div>
)} )}
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
+17 -14
View File
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
import { formatHour } from '@/lib/game/utils/formatting'; import { formatHour } from '@/lib/game/utils/formatting';
interface TimeDisplayProps { interface TimeDisplayProps {
@@ -15,23 +16,25 @@ export function TimeDisplay({
insight, insight,
}: TimeDisplayProps) { }: TimeDisplayProps) {
return ( return (
<div className="flex items-center gap-4"> <DebugName name="TimeDisplay">
<div className="text-center"> <div className="flex items-center gap-4">
<div className="text-lg font-bold game-mono text-amber-400"> <div className="text-center">
Day {day} <div className="text-lg font-bold game-mono text-amber-400">
Day {day}
</div>
<div className="text-xs text-gray-400">
{formatHour(hour)}
</div>
</div> </div>
<div className="text-xs text-gray-400">
{formatHour(hour)} <div className="text-center">
<div className="text-lg font-bold game-mono text-purple-400">
{fmt(insight)}
</div>
<div className="text-xs text-gray-400">Insight</div>
</div> </div>
</div> </div>
</DebugName>
<div className="text-center">
<div className="text-lg font-bold game-mono text-purple-400">
{fmt(insight)}
</div>
<div className="text-xs text-gray-400">Insight</div>
</div>
</div>
); );
} }
+7 -4
View File
@@ -1,6 +1,7 @@
'use client'; 'use client';
import type { SkillUpgradeChoice } from '@/lib/game/types'; import type { SkillUpgradeChoice } from '@/lib/game/types';
import { DebugName } from '@/components/game/debug/debug-context';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
@@ -35,8 +36,9 @@ export function UpgradeDialog({
const currentSelections = pendingSelections.length > 0 ? pendingSelections : alreadySelected; const currentSelections = pendingSelections.length > 0 ? pendingSelections : alreadySelected;
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <DebugName name="UpgradeDialog">
<DialogContent className="bg-gray-900 border-gray-700 max-w-lg"> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="bg-gray-900 border-gray-700 max-w-lg">
<DialogHeader> <DialogHeader>
<DialogTitle className="text-amber-400"> <DialogTitle className="text-amber-400">
Choose Upgrade - {skillId} Choose Upgrade - {skillId}
@@ -107,8 +109,9 @@ export function UpgradeDialog({
{currentSelections.length < 2 ? `Select ${2 - currentSelections.length} more` : 'Confirm'} {currentSelections.length < 2 ? `Select ${2 - currentSelections.length} more` : 'Confirm'}
</Button> </Button>
</div> </div>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</DebugName>
); );
} }
@@ -11,6 +11,7 @@ import type { EquipmentSlot } from '@/lib/game/data/equipment';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
import { CheckCircle, Sparkles } from 'lucide-react'; import { CheckCircle, Sparkles } from 'lucide-react';
import { useCraftingStore, useManaStore } from '@/lib/game/stores'; import { useCraftingStore, useManaStore } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
export interface EnchantmentApplierProps { export interface EnchantmentApplierProps {
selectedEquipmentInstance: string | null; selectedEquipmentInstance: string | null;
@@ -51,23 +52,24 @@ export function EnchantmentApplier({
// Handle apply button click // Handle apply button click
const handleApply = () => { const handleApply = () => {
if (!selectedEquipmentInstance || !selectedDesign) return; if (!selectedEquipmentInstance || !selectedDesign) return;
const instance = equipmentInstances[selectedEquipmentInstance]; const instance = equipmentInstances[selectedEquipmentInstance];
const design = enchantmentDesigns.find(d => d.id === selectedDesign); const design = enchantmentDesigns.find(d => d.id === selectedDesign);
if (!instance || !design) return; if (!instance || !design) return;
// Check capacity // Check capacity
const availableCap = instance.totalCapacity - instance.usedCapacity; const availableCap = instance.totalCapacity - instance.usedCapacity;
if (availableCap < design.totalCapacityUsed) { if (availableCap < design.totalCapacityUsed) {
onCapacityExceeded?.(instance.name, instance.usedCapacity, instance.totalCapacity); onCapacityExceeded?.(instance.name, instance.usedCapacity, instance.totalCapacity);
return; return;
} }
startApplying(selectedEquipmentInstance, selectedDesign); startApplying(selectedEquipmentInstance, selectedDesign);
}; };
return ( return (
<DebugName name="EnchantmentApplier">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{/* Equipment & Design Selection */} {/* Equipment & Design Selection */}
<GameCard variant="default"> <GameCard variant="default">
@@ -217,7 +219,7 @@ export function EnchantmentApplier({
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<div className="text-lg font-semibold text-[var(--text-primary)]">{design.name}</div> <div className="text-lg font-semibold text-[var(--text-primary)]">{design.name}</div>
<div className="text-sm text-[var(--text-secondary)]"> {instance.name}</div> <div className="text-sm text-[var(--text-secondary)]">{instance.name}</div>
<div className="text-xs text-[var(--color-success)]"> <div className="text-xs text-[var(--color-success)]">
<CheckCircle size={12} className="inline mr-1" /> <CheckCircle size={12} className="inline mr-1" />
Ready for Enchantment Ready for Enchantment
@@ -271,6 +273,7 @@ export function EnchantmentApplier({
)} )}
</GameCard> </GameCard>
</div> </div>
</DebugName>
); );
} }
@@ -20,6 +20,7 @@ import {
removeEffectFromDesign, removeEffectFromDesign,
} from './EnchantmentDesigner/utils'; } from './EnchantmentDesigner/utils';
import { useCraftingStore } from '@/lib/game/stores'; import { useCraftingStore } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
export function EnchantmentDesigner({ export function EnchantmentDesigner({
selectedEquipmentType, selectedEquipmentType,
@@ -88,6 +89,7 @@ export function EnchantmentDesigner({
// Render stage // Render stage
return ( return (
<DebugName name="EnchantmentDesigner">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{/* Equipment Type Selection */} {/* Equipment Type Selection */}
<EquipmentTypeSelector <EquipmentTypeSelector
@@ -141,6 +143,7 @@ export function EnchantmentDesigner({
deleteDesign={deleteDesign} deleteDesign={deleteDesign}
/> />
</div> </div>
</DebugName>
); );
} }
@@ -3,6 +3,7 @@
import { ActionButton } from '@/components/ui/action-button'; import { ActionButton } from '@/components/ui/action-button';
import { StatRow } from '@/components/ui/stat-row'; import { StatRow } from '@/components/ui/stat-row';
import type { DesignFormProps } from './types'; import type { DesignFormProps } from './types';
import { DebugName } from '@/components/game/debug/debug-context';
export function DesignForm({ export function DesignForm({
designName, designName,
@@ -15,6 +16,7 @@ export function DesignForm({
handleCreateDesign, handleCreateDesign,
}: DesignFormProps) { }: DesignFormProps) {
return ( return (
<DebugName name="DesignForm">
<div className="space-y-2"> <div className="space-y-2">
<input <input
type="text" type="text"
@@ -45,6 +47,7 @@ export function DesignForm({
{isOverCapacity ? 'Over Capacity!' : `Start Design (${designTime.toFixed(1)}h)`} {isOverCapacity ? 'Over Capacity!' : `Start Design (${designTime.toFixed(1)}h)`}
</ActionButton> </ActionButton>
</div> </div>
</DebugName>
); );
} }
@@ -8,6 +8,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
import { AlertCircle, Wand2, Plus, Minus } from 'lucide-react'; import { AlertCircle, Wand2, Plus, Minus } from 'lucide-react';
import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from '@/lib/game/data/enchantment-effects'; import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from '@/lib/game/data/enchantment-effects';
import type { EffectSelectorProps } from './types'; import type { EffectSelectorProps } from './types';
import { DebugName } from '@/components/game/debug/debug-context';
export function EffectSelector({ export function EffectSelector({
selectedEquipmentType, selectedEquipmentType,
@@ -22,6 +23,7 @@ export function EffectSelector({
getIncompatibilityReason, getIncompatibilityReason,
}: EffectSelectorProps) { }: EffectSelectorProps) {
return ( return (
<DebugName name="EffectSelector">
<> <>
{enchantingLevel < 1 ? ( {enchantingLevel < 1 ? (
<div className="text-center text-[var(--text-muted)] py-8"> <div className="text-center text-[var(--text-muted)] py-8">
@@ -84,7 +86,7 @@ export function EffectSelector({
)} )}
<ActionButton <ActionButton
size="sm" size="sm"
variant="ghost" variant="ghost"
className="h-6 w-6 p-0" className="h-6 w-6 p-0"
onClick={() => addEffect(effect.id)} onClick={() => addEffect(effect.id)}
disabled={!selected && selectedEffects.length >= 5} disabled={!selected && selectedEffects.length >= 5}
@@ -143,6 +145,7 @@ export function EffectSelector({
</> </>
)} )}
</> </>
</DebugName>
); );
} }
@@ -6,6 +6,7 @@ import { ActionButton } from '@/components/ui/action-button';
import { Progress } from '@/components/ui/progress'; import { Progress } from '@/components/ui/progress';
import { ScrollArea } from '@/components/ui/scroll-area'; import { ScrollArea } from '@/components/ui/scroll-area';
import type { EquipmentTypeSelectorProps } from './types'; import type { EquipmentTypeSelectorProps } from './types';
import { DebugName } from '@/components/game/debug/debug-context';
export function EquipmentTypeSelector({ export function EquipmentTypeSelector({
ownedEquipmentTypes, ownedEquipmentTypes,
@@ -15,6 +16,7 @@ export function EquipmentTypeSelector({
cancelDesign, cancelDesign,
}: EquipmentTypeSelectorProps) { }: EquipmentTypeSelectorProps) {
return ( return (
<DebugName name="EquipmentTypeSelector">
<GameCard variant="default"> <GameCard variant="default">
<SectionHeader title="1. Select Equipment Type" /> <SectionHeader title="1. Select Equipment Type" />
{designProgress ? ( {designProgress ? (
@@ -61,6 +63,7 @@ export function EquipmentTypeSelector({
</ScrollArea> </ScrollArea>
)} )}
</GameCard> </GameCard>
</DebugName>
); );
} }
@@ -6,6 +6,7 @@ import { ActionButton } from '@/components/ui/action-button';
import { Trash2 } from 'lucide-react'; import { Trash2 } from 'lucide-react';
import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment'; import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
import type { SavedDesignsProps } from './types'; import type { SavedDesignsProps } from './types';
import { DebugName } from '@/components/game/debug/debug-context';
export function SavedDesigns({ export function SavedDesigns({
enchantmentDesigns, enchantmentDesigns,
@@ -14,6 +15,7 @@ export function SavedDesigns({
deleteDesign, deleteDesign,
}: SavedDesignsProps) { }: SavedDesignsProps) {
return ( return (
<DebugName name="SavedDesigns">
<GameCard variant="default" className="lg:col-span-2"> <GameCard variant="default" className="lg:col-span-2">
<SectionHeader title={`Saved Designs (${enchantmentDesigns.length})`} /> <SectionHeader title={`Saved Designs (${enchantmentDesigns.length})`} />
{enchantmentDesigns.length === 0 ? ( {enchantmentDesigns.length === 0 ? (
@@ -63,6 +65,7 @@ export function SavedDesigns({
</div> </div>
)} )}
</GameCard> </GameCard>
</DebugName>
); );
} }
@@ -14,6 +14,7 @@ import type { EquipmentSlot } from '@/lib/game/types';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
import { useCraftingStore, useManaStore } from '@/lib/game/stores'; import { useCraftingStore, useManaStore } from '@/lib/game/stores';
import { useGameToast } from '@/components/game/GameToast'; import { useGameToast } from '@/components/game/GameToast';
import { DebugName } from '@/components/game/debug/debug-context';
export interface EnchantmentPreparerProps { export interface EnchantmentPreparerProps {
selectedEquipmentInstance: string | null; selectedEquipmentInstance: string | null;
@@ -72,6 +73,7 @@ export function EnchantmentPreparer({
}; };
return ( return (
<DebugName name="EnchantmentPreparer">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{/* Equipment Selection */} {/* Equipment Selection */}
<GameCard variant="default"> <GameCard variant="default">
@@ -296,6 +298,7 @@ export function EnchantmentPreparer({
)} )}
</GameCard> </GameCard>
</div> </div>
</DebugName>
); );
} }
@@ -12,6 +12,7 @@ import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
import type { LootInventory } from '@/lib/game/types'; import type { LootInventory } from '@/lib/game/types';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
import { useCraftingStore, useCombatStore, useManaStore } from '@/lib/game/stores'; import { useCraftingStore, useCombatStore, useManaStore } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
// ─── Crafting Progress ─────────────────────────────────────────────────────── // ─── Crafting Progress ───────────────────────────────────────────────────────
@@ -222,6 +223,7 @@ export function EquipmentCrafter() {
const currentAction = useCombatStore((s) => s.currentAction); const currentAction = useCombatStore((s) => s.currentAction);
return ( return (
<DebugName name="EquipmentCrafter">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
<Card className="bg-gray-900/80 border-gray-700"> <Card className="bg-gray-900/80 border-gray-700">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
@@ -241,6 +243,7 @@ export function EquipmentCrafter() {
<MaterialsInventory materials={lootInventory.materials} deleteMaterial={deleteMaterial} /> <MaterialsInventory materials={lootInventory.materials} deleteMaterial={deleteMaterial} />
</div> </div>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Sparkles, Unlock } from 'lucide-react'; import { Sparkles, Unlock } from 'lucide-react';
@@ -30,6 +31,7 @@ export function AttunementDebug() {
}; };
return ( return (
<DebugName name="AttunementDebug">
<Card className="bg-gray-900/80 border-gray-700"> <Card className="bg-gray-900/80 border-gray-700">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-purple-400 text-sm flex items-center gap-2"> <CardTitle className="text-purple-400 text-sm flex items-center gap-2">
@@ -75,6 +77,7 @@ export function AttunementDebug() {
})} })}
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Star, Lock } from 'lucide-react'; import { Star, Lock } from 'lucide-react';
@@ -21,6 +22,7 @@ export function ElementDebug() {
}; };
return ( return (
<DebugName name="ElementDebug">
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2"> <Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-green-400 text-sm flex items-center gap-2"> <CardTitle className="text-green-400 text-sm flex items-center gap-2">
@@ -73,6 +75,7 @@ export function ElementDebug() {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
+3 -1
View File
@@ -9,7 +9,7 @@ import { Label } from '@/components/ui/label';
import { import {
RotateCcw, AlertTriangle, Zap, Clock, Settings, Eye, RotateCcw, AlertTriangle, Zap, Clock, Settings, Eye,
} from 'lucide-react'; } from 'lucide-react';
import { useDebug } from '@/components/game/debug/debug-context'; import { DebugName, useDebug } from '@/components/game/debug/debug-context';
import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores'; import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores';
import { computeMaxMana } from '@/lib/game/stores'; import { computeMaxMana } from '@/lib/game/stores';
@@ -282,6 +282,7 @@ export function GameStateDebug() {
}; };
return ( return (
<DebugName name="GameStateDebug">
<div className="space-y-4"> <div className="space-y-4">
<WarningBanner /> <WarningBanner />
<DisplayOptions /> <DisplayOptions />
@@ -298,6 +299,7 @@ export function GameStateDebug() {
/> />
</div> </div>
</div> </div>
</DebugName>
); );
} }
+3
View File
@@ -1,10 +1,12 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Bug } from 'lucide-react'; import { Bug } from 'lucide-react';
export function GolemDebug() { export function GolemDebug() {
return ( return (
<DebugName name="GolemDebug">
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2"> <Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-orange-400 text-sm flex items-center gap-2"> <CardTitle className="text-orange-400 text-sm flex items-center gap-2">
@@ -18,6 +20,7 @@ export function GolemDebug() {
</p> </p>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
+3
View File
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Bug } from 'lucide-react'; import { Bug } from 'lucide-react';
@@ -140,6 +141,7 @@ export function PactDebug() {
}; };
return ( return (
<DebugName name="PactDebug">
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2"> <Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-orange-400 text-sm flex items-center gap-2"> <CardTitle className="text-orange-400 text-sm flex items-center gap-2">
@@ -174,6 +176,7 @@ export function PactDebug() {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
+10 -5
View File
@@ -1,4 +1,5 @@
import type { ActivityLogEntry } from '@/lib/game/types'; import type { ActivityLogEntry } from '@/lib/game/types';
import { DebugName } from '@/components/game/debug/debug-context';
interface ActivityLogProps { interface ActivityLogProps {
activityLog: ActivityLogEntry[]; activityLog: ActivityLogEntry[];
@@ -10,14 +11,17 @@ export function ActivityLog({ activityLog, maxEntries = 20 }: ActivityLogProps)
if (entries.length === 0) { if (entries.length === 0) {
return ( return (
<div className="text-sm text-gray-500 italic p-2"> <DebugName name="ActivityLog">
No activity yet. <div className="text-sm text-gray-500 italic p-2">
</div> No activity yet.
</div>
</DebugName>
); );
} }
return ( return (
<div className="space-y-1 max-h-64 overflow-y-auto"> <DebugName name="ActivityLog">
<div className="space-y-1 max-h-64 overflow-y-auto">
{entries.map((entry) => ( {entries.map((entry) => (
<div <div
key={entry.id} key={entry.id}
@@ -29,6 +33,7 @@ export function ActivityLog({ activityLog, maxEntries = 20 }: ActivityLogProps)
{entry.message} {entry.message}
</div> </div>
))} ))}
</div> </div>
</DebugName>
); );
} }
+104 -30
View File
@@ -6,7 +6,6 @@ import type { AttunementDef, AttunementState } from '@/lib/game/types';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Progress } from '@/components/ui/progress'; import { Progress } from '@/components/ui/progress';
import { ScrollArea } from '@/components/ui/scroll-area';
import { DebugName } from '@/components/game/debug/debug-context'; import { DebugName } from '@/components/game/debug/debug-context';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
@@ -36,36 +35,83 @@ interface AttunementCardProps {
function AttunementCard({ def, state }: AttunementCardProps) { function AttunementCard({ def, state }: AttunementCardProps) {
const unlocked = !!state; const unlocked = !!state;
const isStarting = def.unlocked === true;
const xpProgress = state ? getXpProgress(state) : 0; const xpProgress = state ? getXpProgress(state) : 0;
const nextXp = state ? getXpForNextLevel(state.level) : 0; const nextXp = state ? getXpForNextLevel(state.level) : 0;
// Style tokens derived from def.color
const color = def.color;
return ( return (
<Card className={`bg-gray-900/60 ${unlocked ? 'border-gray-700' : 'border-gray-800 opacity-60'}`}> <Card
<CardContent className="p-4 space-y-3"> className={`relative overflow-hidden ${
unlocked
? 'bg-gray-900/60'
: 'bg-gray-950/80'
}`}
style={{
borderLeft: `3px solid ${unlocked ? color : `${color}33`}`,
borderColor: unlocked ? `${color}88` : `${color}22`,
opacity: unlocked ? 1 : 0.55,
}}
>
{/* Starting badge (top-right ribbon) */}
{isStarting && unlocked && (
<div
className="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full"
style={{ backgroundColor: `${color}22`, color }}
>
Starting
</div>
)}
{/* Locked overlay pattern */}
{!unlocked && (
<div className="absolute inset-0 pointer-events-none" style={{ background: `repeating-linear-gradient(45deg, transparent, transparent 12px, ${color}08 12px, ${color}08 24px)` }} />
)}
<CardContent className="p-4 space-y-3 relative">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2.5">
<span className="text-xl">{def.icon}</span> <span
className="text-xl p-1 rounded"
style={{ backgroundColor: `${color}18` }}
>
{def.icon}
</span>
<div> <div>
<h3 className="font-medium text-gray-100">{def.name}</h3> <h3
className="font-semibold"
style={{ color: unlocked ? color : `${color}99` }}
>
{def.name}
</h3>
<p className="text-xs text-gray-500"> <p className="text-xs text-gray-500">
{ATTUNEMENT_SLOT_NAMES[def.slot] ?? def.slot} {ATTUNEMENT_SLOT_NAMES[def.slot] ?? def.slot}
</p> </p>
</div> </div>
</div> </div>
{unlocked ? ( {unlocked ? (
<Badge className="bg-teal-900/50 text-teal-300 text-xs"> <Badge
className="text-xs font-bold"
style={{ backgroundColor: `${color}25`, color, border: `1px solid ${color}44` }}
>
Lv.{state.level} Lv.{state.level}
</Badge> </Badge>
) : ( ) : (
<Badge variant="outline" className="border-gray-700 text-gray-500 text-xs"> <Badge
Locked variant="outline"
className="text-xs"
style={{ borderColor: `${color}44`, color: `${color}88` }}
>
🔒 Locked
</Badge> </Badge>
)} )}
</div> </div>
{/* Description */} {/* Description */}
<p className="text-xs text-gray-400 leading-relaxed">{def.desc}</p> <p className={`text-xs leading-relaxed ${unlocked ? 'text-gray-400' : 'text-gray-600'}`}>{def.desc}</p>
{/* XP Progress (unlocked only) */} {/* XP Progress (unlocked only) */}
{unlocked && state && ( {unlocked && state && (
@@ -76,7 +122,12 @@ function AttunementCard({ def, state }: AttunementCardProps) {
{fmt(state.experience)} / {fmt(nextXp)} {fmt(state.experience)} / {fmt(nextXp)}
</span> </span>
</div> </div>
<Progress value={xpProgress} className="h-2" /> <div className="h-2 rounded-full overflow-hidden bg-gray-800">
<div
className="h-full rounded-full transition-all"
style={{ width: `${xpProgress}%`, backgroundColor: color }}
/>
</div>
{state.level >= MAX_ATTUNEMENT_LEVEL && ( {state.level >= MAX_ATTUNEMENT_LEVEL && (
<p className="text-xs text-amber-400 italic">Maximum level reached</p> <p className="text-xs text-amber-400 italic">Maximum level reached</p>
)} )}
@@ -85,13 +136,19 @@ function AttunementCard({ def, state }: AttunementCardProps) {
{/* Unlock condition (locked only) */} {/* Unlock condition (locked only) */}
{!unlocked && def.unlockCondition && ( {!unlocked && def.unlockCondition && (
<div className="text-xs text-gray-500 italic border-t border-gray-800 pt-2"> <div
className="text-xs italic pt-2"
style={{ color: `${color}77`, borderTop: `1px solid ${color}15` }}
>
🔒 {def.unlockCondition} 🔒 {def.unlockCondition}
</div> </div>
)} )}
{/* Details grid */} {/* Details grid */}
<div className="grid grid-cols-2 gap-2 text-xs border-t border-gray-800 pt-3"> <div
className="grid grid-cols-2 gap-2 text-xs pt-3"
style={{ borderTop: `1px solid ${unlocked ? `${color}22` : `${color}10`}` }}
>
<div> <div>
<span className="text-gray-500">Mana Type</span> <span className="text-gray-500">Mana Type</span>
<p className="text-gray-300 capitalize"> <p className="text-gray-300 capitalize">
@@ -110,21 +167,35 @@ function AttunementCard({ def, state }: AttunementCardProps) {
)} )}
<div> <div>
<span className="text-gray-500">Status</span> <span className="text-gray-500">Status</span>
<p className={state?.active ? 'text-green-400' : 'text-gray-500'}> <p style={{ color: state?.active ? '#4ade80' : unlocked ? `${color}aa` : '#6b7280' }}>
{state?.active ? 'Active' : unlocked ? 'Inactive' : 'Locked'} {state?.active ? 'Active' : unlocked ? 'Inactive' : 'Locked'}
</p> </p>
</div> </div>
{/* Invoker special: pact-based note */}
{def.primaryManaType === undefined && (
<div className="col-span-2">
<span className="text-gray-500">Special</span>
<p style={{ color: `${color}cc` }}>
Gains elemental mana from each guardian pact signed
</p>
</div>
)}
</div> </div>
{/* Capabilities */} {/* Capabilities */}
<div className="border-t border-gray-800 pt-3"> <div style={{ borderTop: `1px solid ${unlocked ? `${color}22` : `${color}10`}` }} className="pt-3">
<span className="text-xs text-gray-500 block mb-1.5">Capabilities</span> <span className="text-xs text-gray-500 block mb-1.5">Capabilities</span>
<div className="flex flex-wrap gap-1"> <div className="flex flex-wrap gap-1">
{def.capabilities.map((cap) => ( {def.capabilities.map((cap) => (
<Badge <Badge
key={cap} key={cap}
variant="outline" variant="outline"
className="border-gray-700 text-gray-400 text-[10px]" className="text-[10px]"
style={{
borderColor: `${color}44`,
color: unlocked ? `${color}cc` : `${color}66`,
backgroundColor: `${color}0a`,
}}
> >
{cap} {cap}
</Badge> </Badge>
@@ -140,7 +211,12 @@ function AttunementCard({ def, state }: AttunementCardProps) {
<Badge <Badge
key={cat} key={cat}
variant="outline" variant="outline"
className="border-gray-700 text-gray-400 text-[10px]" className="text-[10px]"
style={{
borderColor: `${color}33`,
color: unlocked ? `${color}aa` : `${color}55`,
backgroundColor: `${color}08`,
}}
> >
{cat} {cat}
</Badge> </Badge>
@@ -174,7 +250,7 @@ export function AttunementsTab() {
</p> </p>
</div> </div>
<div className="text-right"> <div className="text-right">
<div className="text-2xl font-bold text-teal-400"> <div className="text-2xl font-bold" style={{ color: '#1ABC9C' }}>
{unlockedCount} {unlockedCount}
<span className="text-sm text-gray-500 font-normal"> <span className="text-sm text-gray-500 font-normal">
/{allDefs.length} /{allDefs.length}
@@ -187,17 +263,15 @@ export function AttunementsTab() {
</Card> </Card>
{/* Attunement cards */} {/* Attunement cards */}
<ScrollArea className="h-[600px] pr-2"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> {allDefs.map((def) => (
{allDefs.map((def) => ( <AttunementCard
<AttunementCard key={def.id}
key={def.id} def={def}
def={def} state={attunements[def.id]}
state={attunements[def.id]} />
/> ))}
))} </div>
</div>
</ScrollArea>
</div> </div>
</DebugName> </DebugName>
); );
@@ -10,6 +10,7 @@ import {
} from '@/components/game/crafting'; } from '@/components/game/crafting';
import { useCraftingStore } from '@/lib/game/stores'; import { useCraftingStore } from '@/lib/game/stores';
import type { DesignEffect } from '@/lib/game/types'; import type { DesignEffect } from '@/lib/game/types';
import { DebugName } from '@/components/game/debug/debug-context';
type EnchanterPhase = 'design' | 'prepare' | 'apply'; type EnchanterPhase = 'design' | 'prepare' | 'apply';
@@ -45,6 +46,7 @@ export function EnchanterSubTab() {
}; };
return ( return (
<DebugName name="EnchanterSubTab">
<div className="space-y-4"> <div className="space-y-4">
{/* Phase selector */} {/* Phase selector */}
<div className="flex gap-2"> <div className="flex gap-2">
@@ -94,6 +96,7 @@ export function EnchanterSubTab() {
/> />
)} )}
</div> </div>
</DebugName>
); );
} }
@@ -19,6 +19,7 @@ import { MANA_TYPE_LABELS } from '@/lib/game/data/fabricator-recipe-types';
import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops'; import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
import { useCraftingStore, useManaStore } from '@/lib/game/stores'; import { useCraftingStore, useManaStore } from '@/lib/game/stores';
import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes'; import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes';
import { DebugName } from '@/components/game/debug/debug-context';
const BRANCH_RECIPE_IDS = new Set([ const BRANCH_RECIPE_IDS = new Set([
'oakStaff', 'arcanistStaff', 'battlestaff', 'arcanistCirclet', 'arcanistRobe', 'oakStaff', 'arcanistStaff', 'battlestaff', 'arcanistCirclet', 'arcanistRobe',
@@ -171,6 +172,7 @@ export function FabricatorSubTab() {
}; };
return ( return (
<DebugName name="FabricatorSubTab">
<div className="space-y-4"> <div className="space-y-4">
{/* Section toggle: Equipment vs Materials */} {/* Section toggle: Equipment vs Materials */}
<div className="flex gap-2"> <div className="flex gap-2">
@@ -375,6 +377,7 @@ export function FabricatorSubTab() {
</Card> </Card>
</div> </div>
</div> </div>
</DebugName>
); );
} }
@@ -7,6 +7,7 @@ import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
import { canCraftRecipe } from '@/lib/game/data/fabricator-recipes'; import { canCraftRecipe } from '@/lib/game/data/fabricator-recipes';
import { MANA_TYPE_LABELS } from '@/lib/game/data/fabricator-recipe-types'; import { MANA_TYPE_LABELS } from '@/lib/game/data/fabricator-recipe-types';
import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes'; import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes';
import { DebugName } from '@/components/game/debug/debug-context';
interface MaterialRecipeCardProps { interface MaterialRecipeCardProps {
recipe: FabricatorRecipe; recipe: FabricatorRecipe;
@@ -31,6 +32,7 @@ export function MaterialRecipeCard({
const resultRarity = resultDrop ? LOOT_RARITY_COLORS[resultDrop.rarity] : null; const resultRarity = resultDrop ? LOOT_RARITY_COLORS[resultDrop.rarity] : null;
return ( return (
<DebugName name="MaterialRecipeCard">
<div <div
className="p-3 rounded border bg-gray-800/50" className="p-3 rounded border bg-gray-800/50"
style={{ borderColor: resultRarity?.color ?? '#6B7280' }} style={{ borderColor: resultRarity?.color ?? '#6B7280' }}
@@ -98,5 +100,6 @@ export function MaterialRecipeCard({
{canCraft ? 'Craft' : 'Missing Resources'} {canCraft ? 'Craft' : 'Missing Resources'}
</Button> </Button>
</div> </div>
</DebugName>
); );
} }
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Trophy, CheckCircle, RotateCcw } from 'lucide-react'; import { Trophy, CheckCircle, RotateCcw } from 'lucide-react';
import { useCombatStore } from '@/lib/game/stores'; import { useCombatStore } from '@/lib/game/stores';
import { ACHIEVEMENTS } from '@/lib/game/data/achievements'; import { ACHIEVEMENTS } from '@/lib/game/data/achievements';
import { DebugName } from '@/components/game/debug/debug-context';
export function AchievementDebugSection() { export function AchievementDebugSection() {
const achievements = useCombatStore((s) => s.achievements); const achievements = useCombatStore((s) => s.achievements);
@@ -33,50 +34,52 @@ export function AchievementDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="AchievementDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-yellow-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<Trophy className="w-4 h-4" /> <CardTitle className="text-yellow-400 text-sm flex items-center gap-2">
Achievement Debug <Trophy className="w-4 h-4" />
</CardTitle> Achievement Debug
</CardHeader> </CardTitle>
<CardContent className="space-y-3"> </CardHeader>
<div className="text-xs text-gray-400"> <CardContent className="space-y-3">
Unlocked: {unlockedCount} / {totalCount} <div className="text-xs text-gray-400">
</div> Unlocked: {unlockedCount} / {totalCount}
</div>
<div className="flex gap-2 flex-wrap"> <div className="flex gap-2 flex-wrap">
<Button size="sm" variant="outline" onClick={handleUnlockAll}> <Button size="sm" variant="outline" onClick={handleUnlockAll}>
<CheckCircle className="w-3 h-3 mr-1" /> Unlock All <CheckCircle className="w-3 h-3 mr-1" /> Unlock All
</Button> </Button>
<Button size="sm" variant="destructive" onClick={handleResetAll}> <Button size="sm" variant="destructive" onClick={handleResetAll}>
<RotateCcw className="w-3 h-3 mr-1" /> Reset All <RotateCcw className="w-3 h-3 mr-1" /> Reset All
</Button> </Button>
</div> </div>
<div className="space-y-1 max-h-48 overflow-y-auto"> <div className="space-y-1 max-h-48 overflow-y-auto">
{Object.entries(ACHIEVEMENTS).map(([id, def]) => { {Object.entries(ACHIEVEMENTS).map(([id, def]) => {
const isUnlocked = achievements?.unlocked?.includes(id); const isUnlocked = achievements?.unlocked?.includes(id);
return ( return (
<div <div
key={id} key={id}
className={`flex items-center justify-between p-2 rounded text-xs ${ className={`flex items-center justify-between p-2 rounded text-xs ${
isUnlocked ? 'bg-green-900/20 border border-green-600/50' : 'bg-gray-800/50' isUnlocked ? 'bg-green-900/20 border border-green-600/50' : 'bg-gray-800/50'
}`} }`}
> >
<div> <div>
<span className="font-medium">{def.name}</span> <span className="font-medium">{def.name}</span>
<span className="text-gray-500 ml-2">({def.category})</span> <span className="text-gray-500 ml-2">({def.category})</span>
</div>
{isUnlocked && (
<CheckCircle className="w-3 h-3 text-green-400" />
)}
</div> </div>
{isUnlocked && ( );
<CheckCircle className="w-3 h-3 text-green-400" /> })}
)} </div>
</div> </CardContent>
); </Card>
})} </DebugName>
</div>
</CardContent>
</Card>
); );
} }
@@ -6,6 +6,7 @@ import { Sparkles, Unlock } from 'lucide-react';
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements'; import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
import { useAttunementStore } from '@/lib/game/stores'; import { useAttunementStore } from '@/lib/game/stores';
import { useManaStore } from '@/lib/game/stores'; import { useManaStore } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
export function AttunementDebugSection() { export function AttunementDebugSection() {
const attunements = useAttunementStore((s) => s.attunements); const attunements = useAttunementStore((s) => s.attunements);
@@ -34,54 +35,56 @@ export function AttunementDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="AttunementDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-purple-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<Sparkles className="w-4 h-4" /> <CardTitle className="text-purple-400 text-sm flex items-center gap-2">
Attunements <Sparkles className="w-4 h-4" />
</CardTitle> Attunements
</CardHeader> </CardTitle>
<CardContent className="space-y-3"> </CardHeader>
<Button size="sm" variant="outline" onClick={handleUnlockAll}> <CardContent className="space-y-3">
<Unlock className="w-3 h-3 mr-1" /> Unlock All <Button size="sm" variant="outline" onClick={handleUnlockAll}>
</Button> <Unlock className="w-3 h-3 mr-1" /> Unlock All
{Object.entries(ATTUNEMENTS_DEF).map(([id, def]) => { </Button>
const isActive = attunements?.[id]?.active; {Object.entries(ATTUNEMENTS_DEF).map(([id, def]) => {
const level = attunements?.[id]?.level || 1; const isActive = attunements?.[id]?.active;
const xp = attunements?.[id]?.experience || 0; const level = attunements?.[id]?.level || 1;
const xp = attunements?.[id]?.experience || 0;
return ( return (
<div key={id} className="flex items-center justify-between p-2 bg-gray-800/50 rounded"> <div key={id} className="flex items-center justify-between p-2 bg-gray-800/50 rounded">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span>{def.icon}</span> <span>{def.icon}</span>
<div> <div>
<div className="text-sm font-medium">{def.name}</div> <div className="text-sm font-medium">{def.name}</div>
{isActive && ( {isActive && (
<div className="text-xs text-gray-400">Lv.{level} {xp} XP</div> <div className="text-xs text-gray-400">Lv.{level} {xp} XP</div>
)} )}
</div>
</div>
<div className="flex gap-2">
<Button
size="sm"
variant="outline"
onClick={() => handleUnlockAttunement(id)}
>
<Unlock className="w-3 h-3 mr-1" /> Unlock
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleAddAttunementXP(id, 100)}
>
+100 XP
</Button>
</div> </div>
</div> </div>
<div className="flex gap-2"> );
<Button })}
size="sm" </CardContent>
variant="outline" </Card>
onClick={() => handleUnlockAttunement(id)} </DebugName>
>
<Unlock className="w-3 h-3 mr-1" /> Unlock
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleAddAttunementXP(id, 100)}
>
+100 XP
</Button>
</div>
</div>
);
})}
</CardContent>
</Card>
); );
} }
@@ -6,6 +6,7 @@ import { BookOpen, Plus, Pause, Play } from 'lucide-react';
import { useDisciplineStore } from '@/lib/game/stores/discipline-slice'; import { useDisciplineStore } from '@/lib/game/stores/discipline-slice';
import { ALL_DISCIPLINES } from '@/lib/game/data/disciplines'; import { ALL_DISCIPLINES } from '@/lib/game/data/disciplines';
import { useManaStore } from '@/lib/game/stores/manaStore'; import { useManaStore } from '@/lib/game/stores/manaStore';
import { DebugName } from '@/components/game/debug/debug-context';
export function DisciplineDebugSection() { export function DisciplineDebugSection() {
const disciplines = useDisciplineStore((s) => s.disciplines); const disciplines = useDisciplineStore((s) => s.disciplines);
@@ -55,81 +56,83 @@ export function DisciplineDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="DisciplineDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-indigo-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<BookOpen className="w-4 h-4" /> <CardTitle className="text-indigo-400 text-sm flex items-center gap-2">
Disciplines <BookOpen className="w-4 h-4" />
</CardTitle> Disciplines
</CardHeader> </CardTitle>
<CardContent className="space-y-3"> </CardHeader>
<div className="flex gap-2 flex-wrap mb-2"> <CardContent className="space-y-3">
<Button size="sm" variant="outline" onClick={handleActivateAll}> <div className="flex gap-2 flex-wrap mb-2">
<Play className="w-3 h-3 mr-1" /> Activate All <Button size="sm" variant="outline" onClick={handleActivateAll}>
</Button> <Play className="w-3 h-3 mr-1" /> Activate All
<Button size="sm" variant="outline" onClick={handleDeactivateAll}> </Button>
<Pause className="w-3 h-3 mr-1" /> Deactivate All <Button size="sm" variant="outline" onClick={handleDeactivateAll}>
</Button> <Pause className="w-3 h-3 mr-1" /> Deactivate All
</div> </Button>
<div className="text-xs text-gray-400"> </div>
Active: {activeIds.length} / {concurrentLimit} <div className="text-xs text-gray-400">
</div> Active: {activeIds.length} / {concurrentLimit}
<div className="space-y-2 max-h-64 overflow-y-auto"> </div>
{ALL_DISCIPLINES.map((def) => { <div className="space-y-2 max-h-64 overflow-y-auto">
const disc = disciplines[def.id]; {ALL_DISCIPLINES.map((def) => {
const isActive = activeIds.includes(def.id); const disc = disciplines[def.id];
const xp = disc?.xp || 0; const isActive = activeIds.includes(def.id);
const xp = disc?.xp || 0;
return ( return (
<div <div
key={def.id} key={def.id}
className="flex items-center justify-between p-2 bg-gray-800/50 rounded" className="flex items-center justify-between p-2 bg-gray-800/50 rounded"
> >
<div> <div>
<div className="text-sm font-medium">{def.name}</div> <div className="text-sm font-medium">{def.name}</div>
<div className="text-xs text-gray-400"> <div className="text-xs text-gray-400">
{isActive ? `XP: ${xp}` : 'Inactive'} {isActive ? `XP: ${xp}` : 'Inactive'}
</div>
</div>
<div className="flex gap-1">
<Button
size="sm"
variant="outline"
onClick={() => handleAddXP(def.id, 100)}
>
<Plus className="w-3 h-3 mr-1" /> +100
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleAddXP(def.id, 1000)}
>
+1K
</Button>
<Button
size="sm"
variant={isActive ? 'default' : 'outline'}
onClick={() => {
if (isActive) {
deactivate(def.id);
} else {
activate(def.id, { elements });
}
}}
>
{isActive ? (
<Pause className="w-3 h-3" />
) : (
<Play className="w-3 h-3" />
)}
</Button>
</div> </div>
</div> </div>
<div className="flex gap-1"> );
<Button })}
size="sm" </div>
variant="outline" </CardContent>
onClick={() => handleAddXP(def.id, 100)} </Card>
> </DebugName>
<Plus className="w-3 h-3 mr-1" /> +100
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleAddXP(def.id, 1000)}
>
+1K
</Button>
<Button
size="sm"
variant={isActive ? 'default' : 'outline'}
onClick={() => {
if (isActive) {
deactivate(def.id);
} else {
activate(def.id, { elements });
}
}}
>
{isActive ? (
<Pause className="w-3 h-3" />
) : (
<Play className="w-3 h-3" />
)}
</Button>
</div>
</div>
);
})}
</div>
</CardContent>
</Card>
); );
} }
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Star, Lock } from 'lucide-react'; import { Star, Lock } from 'lucide-react';
import { useManaStore } from '@/lib/game/stores'; import { useManaStore } from '@/lib/game/stores';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
import { DebugName } from '@/components/game/debug/debug-context';
export function ElementDebugSection() { export function ElementDebugSection() {
const elements = useManaStore((s) => s.elements); const elements = useManaStore((s) => s.elements);
@@ -29,63 +30,65 @@ export function ElementDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="ElementDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-green-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<Star className="w-4 h-4" /> <CardTitle className="text-green-400 text-sm flex items-center gap-2">
Elemental Mana <Star className="w-4 h-4" />
</CardTitle> Elemental Mana
</CardHeader> </CardTitle>
<CardContent> </CardHeader>
<div className="mb-3"> <CardContent>
<Button size="sm" variant="outline" onClick={handleUnlockAll}> <div className="mb-3">
<Lock className="w-3 h-3 mr-1" /> Unlock All Elements <Button size="sm" variant="outline" onClick={handleUnlockAll}>
</Button> <Lock className="w-3 h-3 mr-1" /> Unlock All Elements
</div> </Button>
<div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 gap-2"> </div>
{Object.entries(elements || {}).map(([id, elem]) => { <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 gap-2">
const def = ELEMENTS[id]; {Object.entries(elements || {}).map(([id, elem]) => {
return ( const def = ELEMENTS[id];
<div return (
key={id} <div
className={`p-2 rounded border text-center ${ key={id}
elem.unlocked ? 'border-gray-600 bg-gray-800/50' : 'border-gray-800 opacity-60' className={`p-2 rounded border text-center ${
}`} elem.unlocked ? 'border-gray-600 bg-gray-800/50' : 'border-gray-800 opacity-60'
style={{ }`}
borderColor: elem.unlocked ? def?.color : undefined style={{
}} borderColor: elem.unlocked ? def?.color : undefined
> }}
<div className="text-lg">{def?.sym}</div> >
<div className="text-xs text-gray-400">{def?.name}</div> <div className="text-lg">{def?.sym}</div>
<div className="text-xs text-gray-300 mt-1"> <div className="text-xs text-gray-400">{def?.name}</div>
{elem.current}/{elem.max} <div className="text-xs text-gray-300 mt-1">
{elem.current}/{elem.max}
</div>
{!elem.unlocked && (
<Button
size="sm"
variant="outline"
className="mt-2"
onClick={() => handleUnlockElement(id)}
>
<Lock className="w-3 h-3 mr-1" /> Unlock
</Button>
)}
{elem.unlocked && (
<Button
size="sm"
variant="outline"
className="mt-2"
onClick={() => handleAddElementalMana(id, 10)}
>
+10
</Button>
)}
</div> </div>
{!elem.unlocked && ( );
<Button })}
size="sm" </div>
variant="outline" </CardContent>
className="mt-2" </Card>
onClick={() => handleUnlockElement(id)} </DebugName>
>
<Lock className="w-3 h-3 mr-1" /> Unlock
</Button>
)}
{elem.unlocked && (
<Button
size="sm"
variant="outline"
className="mt-2"
onClick={() => handleAddElementalMana(id, 10)}
>
+10
</Button>
)}
</div>
);
})}
</div>
</CardContent>
</Card>
); );
} }
@@ -9,7 +9,7 @@ import { Label } from '@/components/ui/label';
import { import {
RotateCcw, AlertTriangle, Zap, Clock, Eye, RotateCcw, AlertTriangle, Zap, Clock, Eye,
} from 'lucide-react'; } from 'lucide-react';
import { useDebug } from '@/components/game/debug/debug-context'; import { DebugName, useDebug } from '@/components/game/debug/debug-context';
import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores'; import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores';
import { computeMaxMana } from '@/lib/game/stores'; import { computeMaxMana } from '@/lib/game/stores';
@@ -252,20 +252,22 @@ export function GameStateDebugSection() {
}; };
return ( return (
<div className="space-y-4"> <DebugName name="GameStateDebugSection">
<DisplayOptions /> <div className="space-y-4">
<DisplayOptions />
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<GameResetSection confirmReset={confirmReset} onReset={handleReset} /> <GameResetSection confirmReset={confirmReset} onReset={handleReset} />
<ManaDebugSection rawMana={rawMana} onAddMana={handleAddMana} onFillMana={handleFillMana} /> <ManaDebugSection rawMana={rawMana} onAddMana={handleAddMana} onFillMana={handleFillMana} />
<TimeControlSection day={day} hour={hour} paused={paused} onSetDay={handleSetDay} onTogglePause={togglePause} /> <TimeControlSection day={day} hour={hour} paused={paused} onSetDay={handleSetDay} onTogglePause={togglePause} />
<QuickActionsSection <QuickActionsSection
onUnlockBase={handleUnlockBase} onUnlockBase={handleUnlockBase}
onSkipToFloor={() => debugSetFloor?.(100)} onSkipToFloor={() => debugSetFloor?.(100)}
onResetFloorHP={() => resetFloorHP?.()} onResetFloorHP={() => resetFloorHP?.()}
/> />
</div>
</div> </div>
</div> </DebugName>
); );
} }
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Bug, Wand2 } from 'lucide-react'; import { Bug, Wand2 } from 'lucide-react';
import { useCombatStore } from '@/lib/game/stores'; import { useCombatStore } from '@/lib/game/stores';
import { GOLEMS_DEF } from '@/lib/game/data/golems'; import { GOLEMS_DEF } from '@/lib/game/data/golems';
import { DebugName } from '@/components/game/debug/debug-context';
export function GolemDebugSection() { export function GolemDebugSection() {
const golemancy = useCombatStore((s) => s.golemancy); const golemancy = useCombatStore((s) => s.golemancy);
@@ -29,52 +30,54 @@ export function GolemDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="GolemDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-orange-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<Bug className="w-4 h-4" /> <CardTitle className="text-orange-400 text-sm flex items-center gap-2">
Golem Debug <Bug className="w-4 h-4" />
</CardTitle> Golem Debug
</CardHeader> </CardTitle>
<CardContent className="space-y-3"> </CardHeader>
<div className="flex gap-2 flex-wrap"> <CardContent className="space-y-3">
<Button size="sm" variant="outline" onClick={handleEnableAll}> <div className="flex gap-2 flex-wrap">
<Wand2 className="w-3 h-3 mr-1" /> Enable All Golems <Button size="sm" variant="outline" onClick={handleEnableAll}>
</Button> <Wand2 className="w-3 h-3 mr-1" /> Enable All Golems
<Button size="sm" variant="outline" onClick={handleDisableAll}> </Button>
Disable All Golems <Button size="sm" variant="outline" onClick={handleDisableAll}>
</Button> Disable All Golems
</div> </Button>
<div className="text-xs text-gray-400"> </div>
Enabled: {enabledGolems.length} / {Object.keys(GOLEMS_DEF).length} <div className="text-xs text-gray-400">
</div> Enabled: {enabledGolems.length} / {Object.keys(GOLEMS_DEF).length}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 max-h-48 overflow-y-auto"> </div>
{Object.entries(GOLEMS_DEF).map(([id, def]) => { <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 max-h-48 overflow-y-auto">
const isEnabled = enabledGolems.includes(id); {Object.entries(GOLEMS_DEF).map(([id, def]) => {
return ( const isEnabled = enabledGolems.includes(id);
<div return (
key={id} <div
className={`p-2 rounded border flex items-center justify-between ${ key={id}
isEnabled ? 'border-orange-600/50 bg-orange-900/20' : 'border-gray-700' className={`p-2 rounded border flex items-center justify-between ${
}`} isEnabled ? 'border-orange-600/50 bg-orange-900/20' : 'border-gray-700'
> }`}
<div>
<div className="text-sm font-medium">{def.name}</div>
<div className="text-xs text-gray-400">{def.baseManaType}</div>
</div>
<Button
size="sm"
variant={isEnabled ? 'default' : 'outline'}
onClick={() => handleToggleGolem(id)}
> >
{isEnabled ? 'On' : 'Off'} <div>
</Button> <div className="text-sm font-medium">{def.name}</div>
</div> <div className="text-xs text-gray-400">{def.baseManaType}</div>
); </div>
})} <Button
</div> size="sm"
</CardContent> variant={isEnabled ? 'default' : 'outline'}
</Card> onClick={() => handleToggleGolem(id)}
>
{isEnabled ? 'On' : 'Off'}
</Button>
</div>
);
})}
</div>
</CardContent>
</Card>
</DebugName>
); );
} }
@@ -6,6 +6,7 @@ import { Bug } from 'lucide-react';
import { usePrestigeStore, useUIStore, useGameStore } from '@/lib/game/stores'; import { usePrestigeStore, useUIStore, useGameStore } from '@/lib/game/stores';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
import { getGuardianForFloor, getAllGuardianFloors } from '@/lib/game/data/guardian-encounters'; import { getGuardianForFloor, getAllGuardianFloors } from '@/lib/game/data/guardian-encounters';
import { DebugName } from '@/components/game/debug/debug-context';
// ─── Guardian Pact Row ─────────────────────────────────────────────────────── // ─── Guardian Pact Row ───────────────────────────────────────────────────────
@@ -124,43 +125,45 @@ export function PactDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="PactDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-orange-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<Bug className="w-4 h-4" /> <CardTitle className="text-orange-400 text-sm flex items-center gap-2">
Pact Debug <Bug className="w-4 h-4" />
</CardTitle> Pact Debug
</CardHeader> </CardTitle>
<CardContent> </CardHeader>
<div className="space-y-3"> <CardContent>
<div className="flex gap-2 flex-wrap"> <div className="space-y-3">
<Button size="sm" variant="outline" onClick={signAllPacts}> <div className="flex gap-2 flex-wrap">
Sign All Pacts <Button size="sm" variant="outline" onClick={signAllPacts}>
</Button> Sign All Pacts
<Button size="sm" variant="destructive" onClick={clearAllPacts}> </Button>
Clear All Pacts ({signedPacts.length}) <Button size="sm" variant="destructive" onClick={clearAllPacts}>
</Button> Clear All Pacts ({signedPacts.length})
</div> </Button>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
{guardianFloors.map((floor) => ( {guardianFloors.map((floor) => (
<GuardianPactRow <GuardianPactRow
key={floor} key={floor}
floor={floor} floor={floor}
isSigned={signedPacts.includes(floor)} isSigned={signedPacts.includes(floor)}
onForceSign={() => forcePact(floor)} onForceSign={() => forcePact(floor)}
onRemove={() => removePactHandler(floor)} onRemove={() => removePactHandler(floor)}
/> />
))} ))}
</div> </div>
<div className="text-xs text-gray-400 pt-2 border-t border-gray-700"> <div className="text-xs text-gray-400 pt-2 border-t border-gray-700">
Signed Pacts: {signedPacts.length} | Signed Pacts: {signedPacts.length} |
Max Pacts: {1 + (prestigeUpgrades?.pactCapacity || 0)} Max Pacts: {1 + (prestigeUpgrades?.pactCapacity || 0)}
</div>
</div> </div>
</div> </CardContent>
</CardContent> </Card>
</Card> </DebugName>
); );
} }
@@ -6,6 +6,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Castle, ArrowUp, Eye } from 'lucide-react'; import { Castle, ArrowUp, Eye } from 'lucide-react';
import { useCombatStore } from '@/lib/game/stores'; import { useCombatStore } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
export function SpireDebugSection() { export function SpireDebugSection() {
const [floorInput, setFloorInput] = useState('50'); const [floorInput, setFloorInput] = useState('50');
@@ -39,67 +40,69 @@ export function SpireDebugSection() {
}; };
return ( return (
<Card className="bg-gray-900/80 border-gray-700"> <DebugName name="SpireDebugSection">
<CardHeader className="pb-2"> <Card className="bg-gray-900/80 border-gray-700">
<CardTitle className="text-teal-400 text-sm flex items-center gap-2"> <CardHeader className="pb-2">
<Castle className="w-4 h-4" /> <CardTitle className="text-teal-400 text-sm flex items-center gap-2">
Spire Debug <Castle className="w-4 h-4" />
</CardTitle> Spire Debug
</CardHeader> </CardTitle>
<CardContent className="space-y-3"> </CardHeader>
<div className="text-xs text-gray-400"> <CardContent className="space-y-3">
Current Floor: {currentFloor} | Max Reached: {maxFloorReached} | Spire Mode: {spireMode ? 'ON' : 'OFF'} <div className="text-xs text-gray-400">
</div> Current Floor: {currentFloor} | Max Reached: {maxFloorReached} | Spire Mode: {spireMode ? 'ON' : 'OFF'}
<div className="flex gap-2 items-end">
<div className="flex-1">
<label className="text-xs text-gray-400 mb-1 block">Floor (1-100)</label>
<Input
type="number"
min={1}
max={100}
value={floorInput}
onChange={(e) => setFloorInput(e.target.value)}
className="h-8"
/>
</div> </div>
<Button size="sm" variant="outline" onClick={handleJumpToFloor}>
<ArrowUp className="w-3 h-3 mr-1" /> Jump
</Button>
</div>
<div className="flex gap-2 flex-wrap"> <div className="flex gap-2 items-end">
<Button size="sm" variant="outline" onClick={handleClearFloor}> <div className="flex-1">
Reset Floor HP <label className="text-xs text-gray-400 mb-1 block">Floor (1-100)</label>
</Button> <Input
<Button type="number"
size="sm" min={1}
variant={spireMode ? 'default' : 'outline'} max={100}
onClick={handleToggleSpireMode} value={floorInput}
> onChange={(e) => setFloorInput(e.target.value)}
<Eye className="w-3 h-3 mr-1" /> className="h-8"
{spireMode ? 'Exit Spire Mode' : 'Enter Spire Mode'} />
</Button> </div>
</div> <Button size="sm" variant="outline" onClick={handleJumpToFloor}>
<ArrowUp className="w-3 h-3 mr-1" /> Jump
<div className="flex gap-2 flex-wrap">
{[10, 25, 50, 75, 100].map((f) => (
<Button
key={f}
size="sm"
variant="outline"
onClick={() => {
setFloorInput(String(f));
debugSetFloor(f);
setMaxFloorReached(f);
}}
>
Floor {f}
</Button> </Button>
))} </div>
</div>
</CardContent> <div className="flex gap-2 flex-wrap">
</Card> <Button size="sm" variant="outline" onClick={handleClearFloor}>
Reset Floor HP
</Button>
<Button
size="sm"
variant={spireMode ? 'default' : 'outline'}
onClick={handleToggleSpireMode}
>
<Eye className="w-3 h-3 mr-1" />
{spireMode ? 'Exit Spire Mode' : 'Enter Spire Mode'}
</Button>
</div>
<div className="flex gap-2 flex-wrap">
{[10, 25, 50, 75, 100].map((f) => (
<Button
key={f}
size="sm"
variant="outline"
onClick={() => {
setFloorInput(String(f));
debugSetFloor(f);
setMaxFloorReached(f);
}}
>
Floor {f}
</Button>
))}
</div>
</CardContent>
</Card>
</DebugName>
); );
} }
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { DebugName } from '@/components/game/debug/debug-context';
import { computeEquipmentEffects } from '@/lib/game/effects'; import { computeEquipmentEffects } from '@/lib/game/effects';
import type { EquipmentInstance } from '@/lib/game/types'; import type { EquipmentInstance } from '@/lib/game/types';
@@ -43,6 +44,7 @@ export function EquipmentEffectsSummary({ equipmentInstances, equippedInstances
} }
return ( return (
<DebugName name="EquipmentEffectsSummary">
<div className="p-3 rounded border border-[var(--border-default)] bg-[var(--bg-sunken)] space-y-2"> <div className="p-3 rounded border border-[var(--border-default)] bg-[var(--bg-sunken)] space-y-2">
<h3 className="text-sm font-semibold text-[var(--text-primary)]">Equipment Effects</h3> <h3 className="text-sm font-semibold text-[var(--text-primary)]">Equipment Effects</h3>
@@ -89,5 +91,6 @@ export function EquipmentEffectsSummary({ equipmentInstances, equippedInstances
</div> </div>
)} )}
</div> </div>
</DebugName>
); );
} }
@@ -5,6 +5,7 @@ import type { EquipmentInstance, EquipmentSlot } from '@/lib/game/types';
import { EQUIPMENT_TYPES, SLOT_NAMES } from '@/lib/game/data/equipment'; import { EQUIPMENT_TYPES, SLOT_NAMES } from '@/lib/game/data/equipment';
import { RARITY_CSS_VAR } from '@/components/game/LootInventory/types'; import { RARITY_CSS_VAR } from '@/components/game/LootInventory/types';
import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons'; import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
import { DebugName } from '@/components/game/debug/debug-context';
import { ActionButton } from '@/components/ui/action-button'; import { ActionButton } from '@/components/ui/action-button';
interface EquipmentSlotGridProps { interface EquipmentSlotGridProps {
@@ -17,6 +18,7 @@ const SLOTS: EquipmentSlot[] = ['mainHand', 'offHand', 'head', 'body', 'hands',
export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUnequip }: EquipmentSlotGridProps) { export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUnequip }: EquipmentSlotGridProps) {
return ( return (
<DebugName name="EquipmentSlotGrid">
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3"> <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
{SLOTS.map((slot) => { {SLOTS.map((slot) => {
const instanceId = equippedInstances[slot]; const instanceId = equippedInstances[slot];
@@ -75,5 +77,6 @@ export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUne
); );
})} })}
</div> </div>
</DebugName>
); );
} }
@@ -7,6 +7,7 @@ import { EQUIPMENT_TYPES, getValidSlotsForEquipmentType } from '@/lib/game/data/
import { RARITY_CSS_VAR, RARITY_GLOW_CSS_VAR } from '@/components/game/LootInventory/types'; import { RARITY_CSS_VAR, RARITY_GLOW_CSS_VAR } from '@/components/game/LootInventory/types';
import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons'; import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
import { ActionButton } from '@/components/ui/action-button'; import { ActionButton } from '@/components/ui/action-button';
import { DebugName } from '@/components/game/debug/debug-context';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -38,6 +39,7 @@ export function InventoryList({ inventoryItems, equippedInstances, onEquip, onDe
} }
return ( return (
<DebugName name="InventoryList">
<div className="space-y-2"> <div className="space-y-2">
{inventoryItems.map(([instanceId, instance]) => { {inventoryItems.map(([instanceId, instance]) => {
const type = EQUIPMENT_TYPES[instance.typeId]; const type = EQUIPMENT_TYPES[instance.typeId];
@@ -131,5 +133,6 @@ export function InventoryList({ inventoryItems, equippedInstances, onEquip, onDe
); );
})} })}
</div> </div>
</DebugName>
); );
} }
+5 -2
View File
@@ -6,6 +6,7 @@ import { ELEMENTS, SPELLS_DEF } from '@/lib/game/constants';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { DebugName } from '@/components/game/debug/debug-context';
// Format spell cost for display // Format spell cost for display
function formatSpellCost(cost: { type: 'raw' | 'element'; element?: string; amount: number }): string { function formatSpellCost(cost: { type: 'raw' | 'element'; element?: string; amount: number }): string {
@@ -34,7 +35,8 @@ export function SpellsTab() {
const spellTiers = [0, 1, 2, 3, 4]; const spellTiers = [0, 1, 2, 3, 4];
return ( return (
<div className="space-y-6"> <DebugName name="SpellsTab">
<div className="space-y-6">
{spellTiers.map(tier => { {spellTiers.map(tier => {
const spellsInTier = Object.entries(SPELLS_DEF).filter(([, def]) => def.tier === tier); const spellsInTier = Object.entries(SPELLS_DEF).filter(([, def]) => def.tier === tier);
if (spellsInTier.length === 0) return null; if (spellsInTier.length === 0) return null;
@@ -121,7 +123,8 @@ export function SpellsTab() {
</div> </div>
); );
})} })}
</div> </div>
</DebugName>
); );
} }
@@ -7,6 +7,7 @@ import { Progress } from '@/components/ui/progress';
import { getSpireRoomTypeDisplay } from '@/lib/game/utils/spire-utils'; import { getSpireRoomTypeDisplay } from '@/lib/game/utils/spire-utils';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
interface RoomDisplayProps { interface RoomDisplayProps {
floorState: FloorState; floorState: FloorState;
@@ -179,6 +180,7 @@ export function RoomDisplay({ floorState }: RoomDisplayProps) {
const isGuardian = floorState.roomType === 'guardian'; const isGuardian = floorState.roomType === 'guardian';
return ( return (
<DebugName name="RoomDisplay">
<Card className={`bg-gray-900/80 ${isGuardian ? 'border-red-800/40' : 'border-gray-700'}`}> <Card className={`bg-gray-900/80 ${isGuardian ? 'border-red-800/40' : 'border-gray-700'}`}>
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-sm flex items-center gap-2" style={{ color: roomDisplay.color }}> <CardTitle className="text-sm flex items-center gap-2" style={{ color: roomDisplay.color }}>
@@ -196,5 +198,6 @@ export function RoomDisplay({ floorState }: RoomDisplayProps) {
)} )}
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -3,6 +3,7 @@
import type { ActivityLogEntry } from '@/lib/game/types'; import type { ActivityLogEntry } from '@/lib/game/types';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ScrollArea } from '@/components/ui/scroll-area'; import { ScrollArea } from '@/components/ui/scroll-area';
import { DebugName } from '@/components/game/debug/debug-context';
interface SpireActivityLogProps { interface SpireActivityLogProps {
activityLog: ActivityLogEntry[]; activityLog: ActivityLogEntry[];
@@ -13,6 +14,7 @@ export function SpireActivityLog({ activityLog, maxEntries = 30 }: SpireActivity
const entries = activityLog.slice(0, maxEntries); const entries = activityLog.slice(0, maxEntries);
return ( return (
<DebugName name="SpireActivityLog">
<Card className="bg-gray-900/80 border-gray-700"> <Card className="bg-gray-900/80 border-gray-700">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-sm text-gray-400">📜 Activity Log</CardTitle> <CardTitle className="text-sm text-gray-400">📜 Activity Log</CardTitle>
@@ -39,5 +41,6 @@ export function SpireActivityLog({ activityLog, maxEntries = 30 }: SpireActivity
</ScrollArea> </ScrollArea>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -5,6 +5,7 @@ import { SPELLS_DEF, ELEMENTS } from '@/lib/game/constants';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress'; import { Progress } from '@/components/ui/progress';
import { GOLEMS_DEF } from '@/lib/game/data/golems'; import { GOLEMS_DEF } from '@/lib/game/data/golems';
import { DebugName } from '@/components/game/debug/debug-context';
interface SpireCombatControlsProps { interface SpireCombatControlsProps {
castProgress: number; castProgress: number;
@@ -31,6 +32,7 @@ export function SpireCombatControls({ castProgress }: SpireCombatControlsProps)
const summonedGolems = golemancy.summonedGolems || []; const summonedGolems = golemancy.summonedGolems || [];
return ( return (
<DebugName name="SpireCombatControls">
<div className="space-y-4"> <div className="space-y-4">
{/* Active Spell Panel */} {/* Active Spell Panel */}
<Card className="bg-gray-900/80 border-gray-700"> <Card className="bg-gray-900/80 border-gray-700">
@@ -127,5 +129,6 @@ export function SpireCombatControls({ castProgress }: SpireCombatControlsProps)
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
</DebugName>
); );
} }
@@ -13,6 +13,7 @@ import { RoomDisplay } from './RoomDisplay';
import { SpireCombatControls } from './SpireCombatControls'; import { SpireCombatControls } from './SpireCombatControls';
import { SpireActivityLog } from './SpireActivityLog'; import { SpireActivityLog } from './SpireActivityLog';
import { SpireManaDisplay } from './SpireManaDisplay'; import { SpireManaDisplay } from './SpireManaDisplay';
import { DebugName } from '@/components/game/debug/debug-context';
// ─── Derived Stats Hook ────────────────────────────────────────────────────── // ─── Derived Stats Hook ──────────────────────────────────────────────────────
@@ -164,6 +165,7 @@ export function SpireCombatPage() {
}; };
return ( return (
<DebugName name="SpireCombatPage">
<div className="min-h-screen bg-gray-950 flex flex-col"> <div className="min-h-screen bg-gray-950 flex flex-col">
<header className="sticky top-0 z-50 bg-gray-900/95 border-b border-gray-800 px-4 py-2"> <header className="sticky top-0 z-50 bg-gray-900/95 border-b border-gray-800 px-4 py-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
@@ -206,5 +208,6 @@ export function SpireCombatPage() {
<SpireActivityLog activityLog={activityLog} maxEntries={20} /> <SpireActivityLog activityLog={activityLog} maxEntries={20} />
</main> </main>
</div> </div>
</DebugName>
); );
} }
@@ -6,6 +6,7 @@ import { Card, CardContent } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress'; import { Progress } from '@/components/ui/progress';
import { Mountain, ArrowUp, ArrowDown, LogOut } from 'lucide-react'; import { Mountain, ArrowUp, ArrowDown, LogOut } from 'lucide-react';
import { getGuardianForFloor, isGuardianFloor } from '@/lib/game/data/guardian-encounters'; import { getGuardianForFloor, isGuardianFloor } from '@/lib/game/data/guardian-encounters';
import { DebugName } from '@/components/game/debug/debug-context';
interface SpireHeaderProps { interface SpireHeaderProps {
currentFloor: number; currentFloor: number;
@@ -39,6 +40,7 @@ export function SpireHeader({
const roomProgress = totalRooms > 0 ? ((roomsCleared) / totalRooms) * 100 : 0; const roomProgress = totalRooms > 0 ? ((roomsCleared) / totalRooms) * 100 : 0;
return ( return (
<DebugName name="SpireHeader">
<Card className="bg-gray-900/80 border-gray-700"> <Card className="bg-gray-900/80 border-gray-700">
<CardContent className="py-3 space-y-3"> <CardContent className="py-3 space-y-3">
{/* Top row: Floor info + controls */} {/* Top row: Floor info + controls */}
@@ -123,5 +125,6 @@ export function SpireHeader({
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -4,6 +4,7 @@ import { useManaStore, fmt, fmtDec } from '@/lib/game/stores';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress'; import { Progress } from '@/components/ui/progress';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
import { DebugName } from '@/components/game/debug/debug-context';
interface SpireManaDisplayProps { interface SpireManaDisplayProps {
maxMana: number; maxMana: number;
@@ -22,6 +23,7 @@ export function SpireManaDisplay({ maxMana, effectiveRegen }: SpireManaDisplayPr
const manaPercent = maxMana > 0 ? (rawMana / maxMana) * 100 : 0; const manaPercent = maxMana > 0 ? (rawMana / maxMana) * 100 : 0;
return ( return (
<DebugName name="SpireManaDisplay">
<Card className="bg-gray-900/80 border-gray-700"> <Card className="bg-gray-900/80 border-gray-700">
<CardContent className="py-3 space-y-2"> <CardContent className="py-3 space-y-2">
{/* Raw Mana */} {/* Raw Mana */}
@@ -68,5 +70,6 @@ export function SpireManaDisplay({ maxMana, effectiveRegen }: SpireManaDisplayPr
)} )}
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
+5 -2
View File
@@ -10,6 +10,7 @@ import { StudyStatsSection } from './StatsTab/StudyStatsSection';
import { ElementStatsSection } from './StatsTab/ElementStatsSection'; import { ElementStatsSection } from './StatsTab/ElementStatsSection';
import { LoopStatsSection } from './StatsTab/LoopStatsSection'; import { LoopStatsSection } from './StatsTab/LoopStatsSection';
import { DisciplineStatsSection } from './StatsTab/DisciplineStatsSection'; import { DisciplineStatsSection } from './StatsTab/DisciplineStatsSection';
import { DebugName } from '@/components/game/debug/debug-context';
export function StatsTab() { export function StatsTab() {
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
@@ -23,7 +24,8 @@ export function StatsTab() {
const elemMax = 10 + (prestigeUpgrades.elementalAttune || 0) * 25; const elemMax = 10 + (prestigeUpgrades.elementalAttune || 0) * 25;
return ( return (
<div className="space-y-4"> <DebugName name="StatsTab">
<div className="space-y-4">
<ManaStatsSection <ManaStatsSection
stats={{ stats={{
...manaStats, ...manaStats,
@@ -51,7 +53,8 @@ export function StatsTab() {
elemMax={elemMax} elemMax={elemMax}
/> />
<LoopStatsSection /> <LoopStatsSection />
</div> </div>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DebugName } from '@/components/game/debug/debug-context';
import { Swords } from 'lucide-react'; import { Swords } from 'lucide-react';
import { fmt, fmtDec } from '@/lib/game/stores'; import { fmt, fmtDec } from '@/lib/game/stores';
import type { SpellDef } from '@/lib/game/types'; import type { SpellDef } from '@/lib/game/types';
@@ -12,6 +13,7 @@ interface CombatStatsSectionProps {
export function CombatStatsSection({ activeSpellDef, pactMultiplier }: CombatStatsSectionProps) { export function CombatStatsSection({ activeSpellDef, pactMultiplier }: CombatStatsSectionProps) {
return ( return (
<DebugName name="CombatStatsSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-fire)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--mana-fire)] game-panel-title text-xs flex items-center gap-2">
@@ -44,5 +46,6 @@ export function CombatStatsSection({ activeSpellDef, pactMultiplier }: CombatSta
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { DebugName } from '@/components/game/debug/debug-context';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Brain } from 'lucide-react'; import { Brain } from 'lucide-react';
import { useDisciplineStore } from '@/lib/game/stores/discipline-slice'; import { useDisciplineStore } from '@/lib/game/stores/discipline-slice';
@@ -27,6 +28,7 @@ export function DisciplineStatsSection({ disciplineEffects }: DisciplineStatsSec
if (disciplineEntries.length === 0) return null; if (disciplineEntries.length === 0) return null;
return ( return (
<DebugName name="DisciplineStatsSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2">
@@ -68,5 +70,6 @@ export function DisciplineStatsSection({ disciplineEffects }: DisciplineStatsSec
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DebugName } from '@/components/game/debug/debug-context';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { FlaskConical } from 'lucide-react'; import { FlaskConical } from 'lucide-react';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
@@ -16,6 +17,7 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
const elements = useManaStore((s) => s.elements); const elements = useManaStore((s) => s.elements);
return ( return (
<DebugName name="ElementStatsSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--color-success)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--color-success)] game-panel-title text-xs flex items-center gap-2">
@@ -59,5 +61,6 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DebugName } from '@/components/game/debug/debug-context';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { RotateCcw } from 'lucide-react'; import { RotateCcw } from 'lucide-react';
import { fmt } from '@/lib/game/stores'; import { fmt } from '@/lib/game/stores';
@@ -18,6 +19,7 @@ export function LoopStatsSection() {
const spellsLearned = Object.values(spells || {}).filter((s: SpellState) => s.learned).length; const spellsLearned = Object.values(spells || {}).filter((s: SpellState) => s.learned).length;
return ( return (
<DebugName name="LoopStatsSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2">
@@ -57,5 +59,6 @@ export function LoopStatsSection() {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { fmt, fmtDec } from '@/lib/game/stores'; import { fmt, fmtDec } from '@/lib/game/stores';
import { DebugName } from '@/components/game/debug/debug-context';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Droplet } from 'lucide-react'; import { Droplet } from 'lucide-react';
import type { ComputedEffects } from '@/lib/game/effects/upgrade-effects.types'; import type { ComputedEffects } from '@/lib/game/effects/upgrade-effects.types';
@@ -51,6 +52,7 @@ export function ManaStatsSection({ stats, elemMax }: ManaStatsSectionProps) {
} = stats; } = stats;
return ( return (
<DebugName name="ManaStatsSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-water)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--mana-water)] game-panel-title text-xs flex items-center gap-2">
@@ -206,5 +208,6 @@ export function ManaStatsSection({ stats, elemMax }: ManaStatsSectionProps) {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DebugName } from '@/components/game/debug/debug-context';
import { Trophy } from 'lucide-react'; import { Trophy } from 'lucide-react';
import { fmtDec } from '@/lib/game/stores'; import { fmtDec } from '@/lib/game/stores';
import { ELEMENTS } from '@/lib/game/constants'; import { ELEMENTS } from '@/lib/game/constants';
@@ -19,6 +20,7 @@ export function PactStatusSection({ pactMultiplier, pactInsightMultiplier }: Pac
const pactInterferenceMitigation = prestigeUpgrades?.pactInterferenceMitigation || 0; const pactInterferenceMitigation = prestigeUpgrades?.pactInterferenceMitigation || 0;
return ( return (
<DebugName name="PactStatusSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2">
@@ -74,5 +76,6 @@ export function PactStatusSection({ pactMultiplier, pactInsightMultiplier }: Pac
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DebugName } from '@/components/game/debug/debug-context';
import { BookOpen } from 'lucide-react'; import { BookOpen } from 'lucide-react';
import { fmtDec } from '@/lib/game/stores'; import { fmtDec } from '@/lib/game/stores';
@@ -11,6 +12,7 @@ interface StudyStatsSectionProps {
export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsSectionProps) { export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsSectionProps) {
return ( return (
<DebugName name="StudyStatsSection">
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]"> <Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2"> <CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2">
@@ -41,5 +43,6 @@ export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsS
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
} }
@@ -7,6 +7,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Shield, Swords, Clock, Sparkles, Check, Lock, ChevronRight } from 'lucide-react'; import { Shield, Swords, Clock, Sparkles, Check, Lock, ChevronRight } from 'lucide-react';
import clsx from 'clsx'; import clsx from 'clsx';
import { DebugName } from '@/components/game/debug/debug-context';
// ─── Types ─────────────────────────────────────────────────────────────────── // ─── Types ───────────────────────────────────────────────────────────────────
@@ -81,14 +82,15 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
: elemDisplays[0]?.name ?? guardian.element; : elemDisplays[0]?.name ?? guardian.element;
return ( return (
<Card <DebugName name="GuardianPactsComponents">
className={clsx( <Card
'border transition-colors', className={clsx(
status === 'signed' && 'border-green-600/40', 'border transition-colors',
status === 'defeated' && 'border-amber-600/40', status === 'signed' && 'border-green-600/40',
status === 'undefeated' && 'border-gray-700/60', status === 'defeated' && 'border-amber-600/40',
)} status === 'undefeated' && 'border-gray-700/60',
> )}
>
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<div className="min-w-0"> <div className="min-w-0">
@@ -141,7 +143,8 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
/> />
)} )}
</CardContent> </CardContent>
</Card> </Card>
</DebugName>
); );
}); });