58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { cn } from "@/lib/utils";
|
|
import { playChaosRiser } from "@/lib/sounds";
|
|
|
|
type Props = {
|
|
markedCount: number;
|
|
totalItems: number;
|
|
};
|
|
|
|
export function ChaosMeter({ markedCount, totalItems }: Props) {
|
|
const [prevCount, setPrevCount] = useState(markedCount);
|
|
|
|
const ratio = totalItems > 0 ? markedCount / totalItems : 0;
|
|
const percent = Math.round(ratio * 100);
|
|
|
|
useEffect(() => {
|
|
if (markedCount > prevCount && markedCount % 3 === 0) {
|
|
playChaosRiser();
|
|
}
|
|
setPrevCount(markedCount);
|
|
}, [markedCount, prevCount]);
|
|
|
|
const stage =
|
|
ratio < 0.25 ? "stable" :
|
|
ratio < 0.5 ? "unstable" :
|
|
ratio < 0.75 ? "critical" : "meltdown";
|
|
|
|
const stageLabels: Record<string, string> = {
|
|
stable: "✅ Sub stable",
|
|
unstable: "⚠️ Leaking",
|
|
critical: "🚨 MELTDOWN",
|
|
meltdown: "☢️ NUKE",
|
|
};
|
|
|
|
return (
|
|
<div className="w-full space-y-1">
|
|
<div className="flex justify-between text-xs font-mono text-slate-500">
|
|
<span>{stageLabels[stage]}</span>
|
|
<span>{percent}% chaos</span>
|
|
</div>
|
|
<div className="w-full bg-slate-900/60 rounded-full h-3 overflow-hidden border border-slate-700/30">
|
|
<div
|
|
className={cn(
|
|
"h-full rounded-full transition-all duration-500 ease-out",
|
|
stage === "stable" && "bg-gradient-to-r from-cyan-600 to-cyan-400",
|
|
stage === "unstable" && "bg-gradient-to-r from-amber-600 to-orange-400",
|
|
stage === "critical" && "bg-gradient-to-r from-orange-600 to-red-500 animate-pulse",
|
|
stage === "meltdown" && "bg-gradient-to-r from-red-600 to-purple-600 animate-pulse shadow-lg shadow-red-500/50"
|
|
)}
|
|
style={{ width: `${percent}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|