"use client"; import { cn } from "@app/lib/cn"; import { aiUsageAnalyticsFiltersSchema, aiUsageAnalyticsQueries, type AiUsageAnalyticsFilters } from "@app/lib/queries"; import { useIsFetching, useQuery, useQueryClient } from "@tanstack/react-query"; import { RefreshCw, XIcon } from "lucide-react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { DateRangePicker, type DateTimeValue } from "./DateTimePicker"; import { Button } from "./ui/button"; import { Card, CardHeader } from "./ui/card"; import { Label } from "./ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select"; import { Separator } from "./ui/separator"; import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo"; import { HorizontalTabs, type TabItem } from "./HorizontalTabs"; import { OverviewTab } from "./ai-usage-analytics/OverviewTab"; import { ProvidersTab } from "./ai-usage-analytics/ProvidersTab"; import { ResourcesTab } from "./ai-usage-analytics/ResourcesTab"; import { UsersRolesTab } from "./ai-usage-analytics/UsersRolesTab"; export type AiUsageAnalyticsDataProps = { orgId: string; }; const AI_USAGE_ANALYTICS_QUERY_PREFIX = ["AI_USAGE_ANALYTICS"]; export function AiUsageAnalyticsData(props: AiUsageAnalyticsDataProps) { const searchParams = useSearchParams(); const path = usePathname(); const router = useRouter(); const queryClient = useQueryClient(); const filters = aiUsageAnalyticsFiltersSchema.parse( Object.fromEntries(searchParams.entries()) ); const isEmptySearchParams = Object.values(filters).every( (v) => v === undefined ); const dateRange = { startDate: filters.timeStart ? new Date(filters.timeStart) : getSevenDaysAgo(), endDate: filters.timeEnd ? new Date(filters.timeEnd) : new Date() }; const { data: filterOptions } = useQuery( aiUsageAnalyticsQueries.filterOptions({ orgId: props.orgId, filters: { timeStart: filters.timeStart, timeEnd: filters.timeEnd } }) ); const isFetching = useIsFetching({ queryKey: [...AI_USAGE_ANALYTICS_QUERY_PREFIX, props.orgId] }) > 0; function setFilter(key: keyof AiUsageAnalyticsFilters, value?: string) { const newSearch = new URLSearchParams(searchParams); newSearch.delete(key); if (value !== undefined) { newSearch.set(key, value); } router.replace(`${path}?${newSearch.toString()}`); } function handleTimeRangeUpdate(start: DateTimeValue, end: DateTimeValue) { const newSearch = new URLSearchParams(searchParams); const timeRegex = /^(?\d{1,2})\:(?\d{1,2})(\:(?\d{1,2}))?$/; if (start.date) { const startDate = new Date(start.date); if (start.time) { const time = timeRegex.exec(start.time); const groups = time?.groups ?? {}; startDate.setHours(Number(groups.hours)); startDate.setMinutes(Number(groups.minutes)); if (groups.seconds) { startDate.setSeconds(Number(groups.seconds)); } } newSearch.set("timeStart", startDate.toISOString()); } if (end.date) { const endDate = new Date(end.date); if (end.time) { const time = timeRegex.exec(end.time); const groups = time?.groups ?? {}; endDate.setHours(Number(groups.hours)); endDate.setMinutes(Number(groups.minutes)); if (groups.seconds) { endDate.setSeconds(Number(groups.seconds)); } } newSearch.set("timeEnd", endDate.toISOString()); } router.replace(`${path}?${newSearch.toString()}`); } function getDateTime(date: Date) { return `${date.getHours()}:${date.getMinutes()}`; } const providerOptions = (filterOptions?.providers ?? []).map((p) => ({ value: String(p.id), label: p.name ?? `Provider #${p.id}` })); const modelOptions = (filterOptions?.models ?? []).map((m) => ({ value: m, label: m })); const resourceOptions = (filterOptions?.resources ?? []).map((r) => ({ value: String(r.id), label: r.name ?? `Resource #${r.id}` })); const roleOptions = (filterOptions?.roles ?? []).map((r) => ({ value: String(r.id), label: r.name ?? `Role #${r.id}` })); const userOptions = (filterOptions?.users ?? []).map((u) => ({ value: u.id, label: u.email ?? u.id })); const tabs: TabItem[] = [ { title: "Overview", href: "#" }, { title: "Provider Usage", href: "#" }, { title: "Resources", href: "#" }, { title: "Users & Roles", href: "#" } ]; return (
setFilter("providerId", v)} /> setFilter("model", v)} /> setFilter("resourceId", v)} /> setFilter("roleId", v)} /> setFilter("userId", v)} /> {!isEmptySearchParams && ( )}
); } type FilterSelectProps = { id: string; label: string; value?: string; options: { value: string; label: string }[]; placeholder: string; onValueChange: (value?: string) => void; }; function FilterSelect(props: FilterSelectProps) { return (
); }