Files
Mana-Loop/src/components/game/StatsTab/ManaStatsSection.tsx
T
n8n-gitea 3e5b634815
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 42s
feat: partial UI redesign - TabBar, ManaDisplay, StatsTab sub-sections
Design token migration:
- TabBar: replaced hardcoded colors/shadows with --bg-panel, --border-subtle,
  --font-display tokens. Removed rounded-full pills, added Cinzel font tracking.
- ManaDisplay: replaced bg-gray-900/text-blue-400 with --mana-raw, --bg-panel,
  element-specific --mana-* tokens. Updated progress bar styling.
- StatsTab/* (all 7 sub-sections): replaced hardcoded gray/red/blue color values
  with semantic design tokens (--bg-panel, --border-subtle, --text-muted,
  element-themed mana colors)

NOTE: This is a partial implementation. TASK-011 paused to address
foundational issues (missing types, duplicate stat functions) first.
See issue #14 for full context.
2026-05-14 12:03:09 +02:00

243 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { fmt, fmtDec } from '@/lib/game/stores';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Droplet } from 'lucide-react';
import type { SkillUpgradeChoice } from '@/lib/game/types';
import { useSkillStore, usePrestigeStore } from '@/lib/game/stores';
interface ManaStatsSectionProps {
maxMana: number;
baseRegen: number;
effectiveRegen: number;
clickMana: number;
meditationMultiplier: number;
upgradeEffects: any;
elemMax: number;
selectedUpgrades: { skillId: string; upgrade: SkillUpgradeChoice }[];
}
export function ManaStatsSection({
maxMana,
baseRegen,
effectiveRegen,
clickMana,
meditationMultiplier,
upgradeEffects,
elemMax,
selectedUpgrades,
}: ManaStatsSectionProps) {
const skills = useSkillStore((s) => s.skills);
const skillTiers = useSkillStore((s) => s.skillTiers);
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
const getTierMultiplier = (skillId: string) => {
return 1;
};
return (
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
<CardHeader className="pb-2">
<CardTitle className="text-[var(--mana-water)] game-panel-title text-xs flex items-center gap-2">
<Droplet className="w-4 h-4" />
Mana Stats
</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Base Max Mana:</span>
<span style={{ color: 'var(--text-secondary)' }}>100</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Mana Well Bonus:</span>
<span style={{ color: 'var(--mana-water)' }}>
{(() => {
const mw = skillTiers?.manaWell || 1;
const tieredSkillId = mw > 1 ? `manaWell_t${mw}` : 'manaWell';
const level = (skills || {})[tieredSkillId] || (skills || {}).manaWell || 0;
const tierMult = getTierMultiplier(tieredSkillId);
return `+${fmt(level * 100 * tierMult)} (${level} lvl × 100 × ${tierMult}x tier)`;
})()}
</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Prestige Mana Well:</span>
<span style={{ color: 'var(--mana-water)' }}>+{fmt((prestigeUpgrades.manaWell || 0) * 500)}</span>
</div>
{upgradeEffects.maxManaBonus > 0 && (
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--mana-light)' }}>Upgrade Mana Bonus:</span>
<span style={{ color: 'var(--mana-light)' }}>+{fmt(upgradeEffects.maxManaBonus)}</span>
</div>
)}
{upgradeEffects.maxManaMultiplier > 1 && (
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--mana-light)' }}>Upgrade Mana Multiplier:</span>
<span style={{ color: 'var(--mana-light)' }}>×{fmtDec(upgradeEffects.maxManaMultiplier, 2)}</span>
</div>
)}
<div className="flex justify-between text-sm font-semibold border-t border-[var(--border-subtle)] pt-2">
<span style={{ color: 'var(--text-secondary)' }}>Total Max Mana:</span>
<span style={{ color: 'var(--mana-water)' }}>{fmt(maxMana)}</span>
</div>
</div>
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Base Regen:</span>
<span style={{ color: 'var(--text-secondary)' }}>2/hr</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Mana Flow Bonus:</span>
<span style={{ color: 'var(--mana-water)' }}>
{(() => {
const mf = skillTiers?.manaFlow || 1;
const tieredSkillId = mf > 1 ? `manaFlow_t${mf}` : 'manaFlow';
const level = skills[tieredSkillId] || skills.manaFlow || 0;
const tierMult = getTierMultiplier(tieredSkillId);
return `+${fmtDec(level * 1 * tierMult, 2)}/hr (${level} lvl × 1 × ${tierMult}x tier)`;
})()}
</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Mana Spring Bonus:</span>
<span style={{ color: 'var(--mana-water)' }}>+{(skills.manaSpring || 0) * 2}/hr</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Prestige Mana Flow:</span>
<span style={{ color: 'var(--mana-water)' }}>+{fmtDec((prestigeUpgrades.manaFlow || 0) * 0.5)}/hr</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Temporal Echo:</span>
<span style={{ color: 'var(--mana-water)' }}>×{fmtDec(1 + (prestigeUpgrades.temporalEcho || 0) * 0.1, 2)}</span>
</div>
<div className="flex justify-between text-sm font-semibold border-t border-[var(--border-subtle)] pt-2">
<span style={{ color: 'var(--text-secondary)' }}>Base Regen:</span>
<span style={{ color: 'var(--mana-water)' }}>{fmtDec(baseRegen, 2)}/hr</span>
</div>
{upgradeEffects.regenBonus > 0 && (
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--mana-light)' }}>Upgrade Regen Bonus:</span>
<span style={{ color: 'var(--mana-light)' }}>+{fmtDec(upgradeEffects.regenBonus, 2)}/hr</span>
</div>
)}
{upgradeEffects.permanentRegenBonus > 0 && (
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--mana-light)' }}>Permanent Regen Bonus:</span>
<span style={{ color: 'var(--mana-light)' }}>+{fmtDec(upgradeEffects.permanentRegenBonus, 2)}/hr</span>
</div>
)}
{upgradeEffects.regenMultiplier > 1 && (
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--mana-light)' }}>Upgrade Regen Multiplier:</span>
<span style={{ color: 'var(--mana-light)' }}>×{fmtDec(upgradeEffects.regenMultiplier, 2)}</span>
</div>
)}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Click Mana Value:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+{clickMana}</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Mana Tap Bonus:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+{skills.manaTap || 0}</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Mana Surge Bonus:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+{(skills.manaSurge || 0) * 3}</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Mana Overflow:</span>
<span style={{ color: 'var(--mana-crystal)' }}>×{fmtDec(1 + (skills.manaOverflow || 0) * 0.25, 2)}</span>
</div>
</div>
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Meditation Multiplier:</span>
<span className={`font-semibold ${meditationMultiplier > 1.5 ? 'text-[var(--mana-stellar)]' : 'text-[var(--text-secondary)]'}`}>
{fmtDec(meditationMultiplier, 2)}x
</span>
</div>
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Incursion Strength:</span>
<span style={{ color: 'var(--color-danger)' }}>{Math.round(upgradeEffects.incursionStrength * 100)}%</span>
</div>
<div className="flex justify-between text-sm font-semibold border-t border-[var(--border-subtle)] pt-2">
<span style={{ color: 'var(--text-secondary)' }}>Effective Regen:</span>
<span style={{ color: 'var(--color-success)' }} className="font-semibold">{fmtDec(effectiveRegen, 2)}/hr</span>
</div>
</div>
</div>
{/* Special Effects */}
{(upgradeEffects.hasSteadyStream || upgradeEffects.hasManaTorrent ||
upgradeEffects.hasDesperateWells || upgradeEffects.manaCascadeBonus > 0 ||
upgradeEffects.manaWaterfallBonus > 0) && (
<>
<div className="mt-3 mb-2"><span className="text-xs text-[var(--mana-light)] game-panel-title">Special Effects</span></div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
{upgradeEffects.hasSteadyStream && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Steady Stream:</span>
<span style={{ color: 'var(--color-success)' }}>Immune to incursion</span>
</div>
)}
{upgradeEffects.manaCascadeBonus > 0 && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Mana Cascade:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+{fmtDec(upgradeEffects.manaCascadeBonus, 2)}/hr</span>
</div>
)}
{upgradeEffects.manaWaterfallBonus > 0 && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Mana Waterfall:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+{fmtDec(upgradeEffects.manaWaterfallBonus, 2)}/hr</span>
</div>
)}
{upgradeEffects.hasFlowSurge && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Flow Surge:</span>
<span style={{ color: 'var(--mana-crystal)' }}>Clicks +100% regen for 1hr</span>
</div>
)}
{upgradeEffects.hasManaOverflow && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Mana Overflow:</span>
<span style={{ color: 'var(--mana-crystal)' }}>Raw can exceed max by 20%</span>
</div>
)}
{upgradeEffects.hasEternalFlow && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Eternal Flow:</span>
<span style={{ color: 'var(--color-success)' }}>Regen immune to ALL penalties</span>
</div>
)}
{upgradeEffects.hasManaTorrent && upgradeEffects.rawMana > maxMana * 0.75 && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Mana Torrent:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+50% regen (high mana)</span>
</div>
)}
{upgradeEffects.hasDesperateWells && upgradeEffects.rawMana < maxMana * 0.25 && (
<div className="flex justify-between text-xs bg-[var(--bg-sunken)]/50 rounded px-2 py-1">
<span style={{ color: 'var(--text-secondary)' }}>Desperate Wells:</span>
<span style={{ color: 'var(--mana-crystal)' }}>+50% regen (low mana)</span>
</div>
)}
</div>
</>
)}
{/* Element Max */}
<div className="mt-3 pt-3 border-t border-[var(--border-subtle)]">
<div className="flex justify-between text-sm">
<span style={{ color: 'var(--text-muted)' }}>Element Capacity:</span>
<span style={{ color: 'var(--color-success)' }}>{elemMax}</span>
</div>
</div>
</CardContent>
</Card>
);
}