'use client'; import { useAttunementStore } from '@/lib/game/stores'; import { ATTUNEMENTS_DEF, ATTUNEMENT_SLOT_NAMES, getAttunementXPForLevel, MAX_ATTUNEMENT_LEVEL } from '@/lib/game/data/attunements'; import type { AttunementDef, AttunementState } from '@/lib/game/types'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Progress } from '@/components/ui/progress'; import { ScrollArea } from '@/components/ui/scroll-area'; import { DebugName } from '@/components/game/debug/debug-context'; import { fmt } from '@/lib/game/stores'; // ─── Helpers ───────────────────────────────────────────────────────────────── function getXpForNextLevel(level: number): number { if (level >= MAX_ATTUNEMENT_LEVEL) return 0; return getAttunementXPForLevel(level + 1); } function getXpProgress(state: AttunementState): number { const nextXp = getXpForNextLevel(state.level); if (nextXp <= 0) return 100; return Math.min(100, Math.round((state.experience / nextXp) * 100)); } function isAttunementUnlocked(id: string, attunements: Record): boolean { return id in attunements; } // ─── Attunement Card ───────────────────────────────────────────────────────── interface AttunementCardProps { def: AttunementDef; state?: AttunementState; } function AttunementCard({ def, state }: AttunementCardProps) { const unlocked = !!state; const xpProgress = state ? getXpProgress(state) : 0; const nextXp = state ? getXpForNextLevel(state.level) : 0; return ( {/* Header */}
{def.icon}

{def.name}

{ATTUNEMENT_SLOT_NAMES[def.slot] ?? def.slot}

{unlocked ? ( Lv.{state.level} ) : ( Locked )}
{/* Description */}

{def.desc}

{/* XP Progress (unlocked only) */} {unlocked && state && (
XP Progress {fmt(state.experience)} / {fmt(nextXp)}
{state.level >= MAX_ATTUNEMENT_LEVEL && (

Maximum level reached

)}
)} {/* Unlock condition (locked only) */} {!unlocked && def.unlockCondition && (
🔒 {def.unlockCondition}
)} {/* Details grid */}
Mana Type

{def.primaryManaType ?? 'None (pact-based)'}

Raw Regen

+{def.rawManaRegen}/hr

{def.conversionRate > 0 && (
Conversion

{def.conversionRate}/hr

)}
Status

{state?.active ? 'Active' : unlocked ? 'Inactive' : 'Locked'}

{/* Capabilities */}
Capabilities
{def.capabilities.map((cap) => ( {cap} ))}
{/* Skill Categories */}
Skill Categories
{def.skillCategories.map((cat) => ( {cat} ))}
); } // ─── Main Component ────────────────────────────────────────────────────────── export function AttunementsTab() { const attunements = useAttunementStore((s) => s.attunements); const allDefs = Object.values(ATTUNEMENTS_DEF); const unlockedCount = allDefs.filter((d) => isAttunementUnlocked(d.id, attunements)).length; return (
{/* Summary header */}

Attunements

Class-like abilities tied to body locations

{unlockedCount} /{allDefs.length}

Unlocked

{/* Attunement cards */}
{allDefs.map((def) => ( ))}
); } AttunementsTab.displayName = 'AttunementsTab';