- Fix token averaging: calculate over active hours/days only (not full period) - Enable hourlyData query for all time ranges (not just 24h) - Rename 'Usage Forecast' to 'Usage Averages' (real data, not projections) - Add avg/request metric and active hours/days context - Update terminology: Input/Output Tokens with info tooltips - Add Estimated Cost stat card with per-model calculation - Add quota warning alert banner when models exceed 80% - Add ModelQuotaBar component with color thresholds
71 lines
2.4 KiB
TypeScript
71 lines
2.4 KiB
TypeScript
import React from 'react';
|
|
import { Skeleton } from '@/components/ui/skeleton';
|
|
import { Button } from '@/components/ui/button';
|
|
import { AlertTriangle, BarChart3, RotateCcw } from 'lucide-react';
|
|
|
|
interface ChartStatesProps {
|
|
isLoading: boolean;
|
|
error: Error | null;
|
|
isEmpty: boolean;
|
|
onRetry: () => void;
|
|
title: string;
|
|
emptyTitle: string;
|
|
emptyDescription: string;
|
|
errorMessage: string;
|
|
retryLabel: string;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export const ChartCard: React.FC<ChartStatesProps> = ({
|
|
isLoading,
|
|
error,
|
|
isEmpty,
|
|
onRetry,
|
|
title,
|
|
emptyTitle,
|
|
emptyDescription,
|
|
errorMessage,
|
|
retryLabel,
|
|
children,
|
|
}) => {
|
|
return (
|
|
<div className="bg-card flex flex-col rounded-xl border border-white/[0.06]">
|
|
<div className="flex flex-col p-5">
|
|
<div className="mb-4 flex items-center justify-between">
|
|
<h3 className="text-foreground text-[13px] font-semibold tracking-tight">{title}</h3>
|
|
</div>
|
|
<div className="flex-1">
|
|
{isLoading ? (
|
|
<div className="flex h-[280px] flex-col gap-3">
|
|
<Skeleton className="h-full w-full rounded-lg" />
|
|
</div>
|
|
) : error ? (
|
|
<div className="flex h-[280px] flex-col items-center justify-center gap-3">
|
|
<div className="bg-destructive/10 flex h-10 w-10 items-center justify-center rounded-lg">
|
|
<AlertTriangle className="text-destructive h-5 w-5" />
|
|
</div>
|
|
<p className="text-muted-foreground text-[13px]">{errorMessage}</p>
|
|
<Button variant="outline" size="sm" onClick={onRetry}>
|
|
<RotateCcw className="mr-1.5 h-3.5 w-3.5" />
|
|
{retryLabel}
|
|
</Button>
|
|
</div>
|
|
) : isEmpty ? (
|
|
<div className="flex h-[280px] flex-col items-center justify-center gap-2">
|
|
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-white/[0.04]">
|
|
<BarChart3 className="text-muted-foreground/60 h-5 w-5" />
|
|
</div>
|
|
<p className="text-foreground text-[13px] font-medium">{emptyTitle}</p>
|
|
<p className="text-muted-foreground max-w-[240px] text-center text-xs">
|
|
{emptyDescription}
|
|
</p>
|
|
</div>
|
|
) : (
|
|
children
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|