'use client'; import { useState, useMemo } from 'react'; import { useCombatStore } from '@/lib/game/stores'; import { ACHIEVEMENTS, ACHIEVEMENT_CATEGORY_COLORS, getAchievementsByCategory, isAchievementRevealed, } from '@/lib/game/data/achievements'; import type { AchievementDef } 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 { SectionHeader } from '@/components/ui/section-header'; import { DebugName } from '@/components/game/debug/debug-context'; import { fmt } from '@/lib/game/stores'; // ─── Helpers ───────────────────────────────────────────────────────────────── const CATEGORY_LABELS: Record = { combat: '⚔️ Combat', progression: '📈 Progression', crafting: '🔨 Crafting', magic: '✨ Magic', special: '🌟 Special', }; function getProgressForAchievement( achievement: AchievementDef, progress: Record, ): number { return progress[achievement.id] ?? 0; } function getProgressPercent(achievement: AchievementDef, current: number): number { if (achievement.requirement.value <= 0) return 100; return Math.min(100, Math.round((current / achievement.requirement.value) * 100)); } function formatReward(reward: AchievementDef['reward']): string { const parts: string[] = []; if (reward.insight) parts.push(`${reward.insight} insight`); if (reward.manaBonus) parts.push(`+${reward.manaBonus} mana`); if (reward.damageBonus) parts.push(`+${(reward.damageBonus * 100).toFixed(0)}% dmg`); if (reward.regenBonus) parts.push(`+${reward.regenBonus} regen`); if (reward.title) parts.push(`title: "${reward.title}"`); if (reward.unlockEffect) parts.push(`unlock: ${reward.unlockEffect}`); return parts.join(', '); } // ─── Category Section ──────────────────────────────────────────────────────── interface CategorySectionProps { category: string; achievements: AchievementDef[]; unlocked: string[]; progress: Record; collapsed: boolean; onToggleCollapse: () => void; } function CategorySection({ category, achievements, unlocked, progress, collapsed, onToggleCollapse, }: CategorySectionProps) { const color = ACHIEVEMENT_CATEGORY_COLORS[category] ?? '#9CA3AF'; const label = CATEGORY_LABELS[category] ?? category; const unlockedCount = achievements.filter((a) => unlocked.includes(a.id)).length; return ( {collapsed ? 'Expand ▼' : 'Collapse ▲'} } /> {!collapsed && ( {achievements.map((achievement) => { const isUnlocked = unlocked.includes(achievement.id); const currentProgress = getProgressForAchievement(achievement, progress); const percent = getProgressPercent(achievement, currentProgress); const revealed = isAchievementRevealed(achievement, currentProgress); if (!revealed) { return (
??? Hidden achievement — keep progressing to reveal
); } return (
{achievement.name} {isUnlocked && ( ✓ Unlocked )}
{fmt(currentProgress)} / {fmt(achievement.requirement.value)}

{achievement.desc}

{percent}%
Reward:{' '} {formatReward(achievement.reward)}
); })}
)}
); } // ─── Main Component ────────────────────────────────────────────────────────── export function AchievementsTab() { const achievements = useCombatStore((s) => s.achievements); const [collapsedCategories, setCollapsedCategories] = useState>({}); const byCategory = useMemo(() => getAchievementsByCategory(), []); const categories = useMemo( () => Object.keys(byCategory).sort(), [byCategory], ); const totalAchievements = Object.keys(ACHIEVEMENTS).length; const unlockedCount = achievements.unlocked.length; const toggleCollapse = (category: string) => { setCollapsedCategories((prev) => ({ ...prev, [category]: !prev[category], })); }; return (
{/* Summary header */}

Achievements

Track your progress and unlock rewards

{unlockedCount} /{totalAchievements}
{/* Category sections */}
{categories.map((category) => ( toggleCollapse(category)} /> ))}
); } AchievementsTab.displayName = 'AchievementsTab';