geo/frontend/components/subscription/UsageProgress.tsx

62 lines
1.8 KiB
TypeScript

"use client";
import { cn } from "@/lib/utils";
interface UsageProgressProps {
label: string;
current: number;
limit: number;
unit?: string;
className?: string;
}
export function UsageProgress({ label, current, limit, unit = "", className }: UsageProgressProps) {
const isUnlimited = limit === -1;
const percentage = isUnlimited ? 0 : limit > 0 ? Math.min((current / limit) * 100, 100) : 0;
const isWarning = !isUnlimited && percentage > 80;
const isCritical = !isUnlimited && percentage > 95;
const barColor = isCritical
? "bg-red-500"
: isWarning
? "bg-amber-500"
: "bg-primary";
const textColor = isCritical
? "text-red-600"
: isWarning
? "text-amber-600"
: "text-gray-900";
return (
<div className={cn("space-y-1.5", className)}>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">{label}</span>
<span className={cn("text-sm font-medium", textColor)}>
{isUnlimited
? `${current}${unit}`
: `${current}${unit} / ${limit}${unit}`}
</span>
</div>
{!isUnlimited && (
<div className="h-2 w-full rounded-full bg-gray-100 overflow-hidden">
<div
className={cn("h-full rounded-full transition-all duration-300", barColor)}
style={{ width: `${percentage}%` }}
/>
</div>
)}
{isUnlimited && (
<div className="h-2 w-full rounded-full bg-primary/10 overflow-hidden">
<div className="h-full w-0 rounded-full bg-primary" />
</div>
)}
{!isUnlimited && isWarning && (
<p className="text-xs text-amber-600">
{isCritical ? "额度即将用尽" : "额度使用已超过80%"}
</p>
)}
</div>
);
}