diff --git a/src/app/(app)/usage/page.tsx b/src/app/(app)/usage/page.tsx index 9a192df0e..687408aa9 100644 --- a/src/app/(app)/usage/page.tsx +++ b/src/app/(app)/usage/page.tsx @@ -18,7 +18,7 @@ import { formatLargeNumber, } from '@/lib/utils'; import { useState, useEffect } from 'react'; -import { useRouter } from 'next/navigation'; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; import { StreakCalendar } from '@/components/profile/StreakCalendar'; import { UsageWarning } from '@/components/usage/UsageWarning'; import type { UsageTableColumn, UsageTableRow } from '@/components/usage/UsageTableBase'; @@ -42,6 +42,8 @@ type UsageResponse = { usage: UsageData[]; }; +type GroupBy = 'day' | 'model'; + async function fetchUsageData(groupByModel: boolean, viewType: string): Promise { const response = await fetch( `/api/profile/usage?groupByModel=${groupByModel}&viewType=${viewType}` @@ -134,10 +136,26 @@ function transformUsageDataForStreakCalendar( export default function UsagePage() { const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); const trpc = useTRPC(); - const [groupByModel, setGroupByModel] = useState(false); + const groupByParam = searchParams.get('groupBy'); + const groupBy: GroupBy = groupByParam === 'model' ? 'model' : 'day'; + const groupByModel = groupBy === 'model'; const [viewType, setViewType] = useState('personal'); + const handleGroupByChange = (nextGroupBy: GroupBy) => { + const params = new URLSearchParams(searchParams.toString()); + if (nextGroupBy === 'day') { + params.delete('groupBy'); + } else { + params.set('groupBy', nextGroupBy); + } + + const query = params.toString(); + router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false }); + }; + const { data: usageData, isLoading, @@ -540,14 +558,14 @@ export default function UsagePage() { diff --git a/src/components/organizations/usage-details/OrganizationUsageDetails.tsx b/src/components/organizations/usage-details/OrganizationUsageDetails.tsx index 64e6d7b1d..433751198 100644 --- a/src/components/organizations/usage-details/OrganizationUsageDetails.tsx +++ b/src/components/organizations/usage-details/OrganizationUsageDetails.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState, useMemo } from 'react'; import { useSession } from 'next-auth/react'; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; import { useOrganizationUsageDetails, useOrganizationUsageTimeseries, @@ -39,6 +40,8 @@ import { OrganizationAdminContextProvider } from '@/components/organizations/Org // Chart color constant const CHART_COLOR = '#3b82f6'; +type GroupBy = 'day' | 'model'; + export function OrganizationUsageDetailsPage({ organizationId }: { organizationId: string }) { return ( @@ -48,9 +51,15 @@ export function OrganizationUsageDetailsPage({ organizationId }: { organizationI } export function OrganizationUsageDetails({ organizationId }: { organizationId: string }) { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + // State management const [timePeriod, setTimePeriod] = useState('week'); - const [groupByModel, setGroupByModel] = useState(false); + const groupByParam = searchParams.get('groupBy'); + const groupBy: GroupBy = groupByParam === 'model' ? 'model' : 'day'; + const groupByModel = groupBy === 'model'; const [selectedMetric, setSelectedMetric] = useState('cost'); const [chartSplitBy, setChartSplitBy] = useState({ provider: false, @@ -58,6 +67,18 @@ export function OrganizationUsageDetails({ organizationId }: { organizationId: s tokenType: false, }); + const handleGroupByChange = (nextGroupBy: GroupBy) => { + const params = new URLSearchParams(searchParams.toString()); + if (nextGroupBy === 'day') { + params.delete('groupBy'); + } else { + params.set('groupBy', nextGroupBy); + } + + const query = params.toString(); + router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false }); + }; + // Context and session const { data: session } = useSession(); const currentUserEmail = session?.user?.email; @@ -327,14 +348,14 @@ export function OrganizationUsageDetails({ organizationId }: { organizationId: s