import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { UsageSummaryCards } from "./UsageSummaryCards"; import { UsageTrendChart } from "./UsageTrendChart"; import { RequestLogTable } from "./RequestLogTable"; import { ProviderStatsTable } from "./ProviderStatsTable"; import { ModelStatsTable } from "./ModelStatsTable"; import type { AppTypeFilter, UsageRangeSelection } from "@/types/usage"; import { motion } from "framer-motion"; import { BarChart3, ListFilter, Activity, RefreshCw, Coins, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useQueryClient } from "@tanstack/react-query"; import { usageKeys } from "@/lib/query/usage"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; import { PricingConfigPanel } from "@/components/usage/PricingConfigPanel"; import { cn } from "@/lib/utils"; import { getLocaleFromLanguage } from "./format"; import { getUsageRangePresetLabel, resolveUsageRange } from "@/lib/usageRange"; import { UsageDateRangePicker } from "./UsageDateRangePicker"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; const APP_FILTER_OPTIONS: AppTypeFilter[] = [ "all", "claude", "codex", "gemini", "hermes", ]; export function UsageDashboard() { const { t, i18n } = useTranslation(); const queryClient = useQueryClient(); const [range, setRange] = useState({ preset: "today" }); const [appType, setAppType] = useState("all"); const [refreshIntervalMs, setRefreshIntervalMs] = useState(30000); const refreshIntervalOptionsMs = [0, 5000, 10000, 30000, 60000] as const; const changeRefreshInterval = () => { const currentIndex = refreshIntervalOptionsMs.indexOf( refreshIntervalMs as (typeof refreshIntervalOptionsMs)[number], ); const safeIndex = currentIndex >= 0 ? currentIndex : 3; const nextIndex = (safeIndex + 1) % refreshIntervalOptionsMs.length; const next = refreshIntervalOptionsMs[nextIndex]; setRefreshIntervalMs(next); queryClient.invalidateQueries({ queryKey: usageKeys.all }); }; const language = i18n.resolvedLanguage || i18n.language || "en"; const locale = getLocaleFromLanguage(language); const resolvedRange = useMemo(() => resolveUsageRange(range), [range]); const rangeLabel = useMemo(() => { if (range.preset !== "custom") { return getUsageRangePresetLabel(range.preset, t); } return `${new Date(resolvedRange.startDate * 1000).toLocaleString(locale)} - ${new Date( resolvedRange.endDate * 1000, ).toLocaleString(locale)}`; }, [locale, range, resolvedRange.endDate, resolvedRange.startDate, t]); return (

{t("usage.title")}

{t("usage.subtitle")}

{APP_FILTER_OPTIONS.map((type) => ( ))}
setRange(nextRange)} />
{t("usage.requestLogs")} {t("usage.providerStats")} {t("usage.modelStats")}

{t("settings.advanced.pricing.title")}

{t("settings.advanced.pricing.description")}

); }