Files
echo-nexus/src/components/game/ResourceBar.tsx
T

102 lines
3.9 KiB
TypeScript
Executable File
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";
// 回响星核 / Echo Nexus — 顶栏资源栏
import { useGameStore } from "@/store/gameStore";
import { formatNum, PRESTIGE } from "@/lib/game/config";
import { Gem, Lightbulb, Waves, RotateCcw } from "lucide-react";
import { Progress } from "@/components/ui/progress";
export function ResourceBar({ onPrestige }: { onPrestige: () => void }) {
const crystals = useGameStore((s) => s.crystals);
const crystalsPerSec = useGameStore((s) => s.crystalsPerSec);
const insights = useGameStore((s) => s.insights);
const contact = useGameStore((s) => s.contact);
const ascensions = useGameStore((s) => s.ascensions);
const blueprints = useGameStore((s) => s.blueprints);
return (
<div className="flex flex-wrap items-center gap-x-3 gap-y-2 sm:gap-x-4 px-3.5 py-2.5 rounded-2xl border border-white/10 bg-black/40 backdrop-blur-md">
{/* 晶体 */}
<Stat
icon={<Gem className="h-4 w-4 text-emerald-400" />}
label="记忆晶体"
value={formatNum(crystals)}
sub={`+${crystalsPerSec.toFixed(1)}/s`}
glow="rgba(52,211,153,0.4)"
/>
<div className="h-9 w-px bg-gradient-to-b from-transparent via-white/15 to-transparent hidden sm:block" />
{/* 洞见 */}
<Stat
icon={<Lightbulb className="h-4 w-4 text-amber-400" />}
label="技术洞见"
value={formatNum(insights)}
sub="解码产出"
glow="rgba(251,191,36,0.4)"
/>
<div className="h-9 w-px bg-gradient-to-b from-transparent via-white/15 to-transparent hidden sm:block" />
{/* 接触进度 */}
<div className="flex-1 min-w-[200px] flex flex-col gap-1.5">
<div className="flex items-center gap-2">
<Waves className="h-4 w-4 text-fuchsia-400 shrink-0" />
<span className="text-xs text-muted-foreground whitespace-nowrap">接触进度</span>
<span className="text-xs font-mono font-semibold text-fuchsia-300 ml-auto tabular-nums">
{contact.toFixed(1)}%
</span>
{contact >= 100 && (
<button
onClick={onPrestige}
className="text-[10px] px-2 py-0.5 rounded-full bg-fuchsia-500/20 border border-fuchsia-400/50 text-fuchsia-200 hover:bg-fuchsia-500/30 transition animate-pulse whitespace-nowrap ml-1"
>
飞升
</button>
)}
</div>
<Progress
value={contact}
className="h-1.5 bg-white/10 [&>div]:bg-gradient-to-r [&>div]:from-fuchsia-500 [&>div]:to-rose-400"
/>
</div>
<div className="h-9 w-px bg-gradient-to-b from-transparent via-white/15 to-transparent hidden sm:block" />
{/* 飞升 */}
<div className="flex items-center gap-2.5">
<RotateCcw className="h-4 w-4 text-rose-400 shrink-0" />
<div className="flex flex-col gap-0.5">
<span className="text-[10px] text-muted-foreground leading-none">飞升</span>
<div className="flex items-baseline gap-1.5">
<span className="text-sm font-mono font-semibold leading-none">
{ascensions}
</span>
<span className="text-amber-300 text-xs leading-none">×{blueprints.length}</span>
</div>
</div>
</div>
</div>
);
}
function Stat({
icon,
label,
value,
sub,
glow,
}: {
icon: React.ReactNode;
label: string;
value: string;
sub: string;
glow: string;
}) {
return (
<div className="flex items-center gap-2.5" style={{ filter: `drop-shadow(0 0 6px ${glow})` }}>
{icon}
<div className="flex flex-col gap-0.5">
<span className="text-[10px] text-muted-foreground leading-none">{label}</span>
<div className="flex items-baseline gap-1.5">
<span className="text-sm font-mono font-semibold leading-none tabular-nums">{value}</span>
<span className="text-[10px] text-muted-foreground/80 whitespace-nowrap">{sub}</span>
</div>
</div>
</div>
);
}