/* Copyright (C) 2023-2026 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { getRouteApi, useNavigate } from '@tanstack/react-router' import { Eye, EyeOff } from 'lucide-react' import { useState, useCallback, useMemo, lazy, Suspense } from 'react' import { useTranslation } from 'react-i18next' import { SectionPageLayout } from '@/components/layout' import { FadeIn } from '@/components/page-transition' import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Tooltip, TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip' import { ROLE } from '@/lib/roles' import { cn } from '@/lib/utils' import { useAuthStore } from '@/stores/auth-store' import { ModelsChartPreferences } from './components/models/models-chart-preferences' import { ModelsFilter } from './components/models/models-filter-dialog' import { OverviewDashboard } from './components/overview/overview-dashboard' import { DEFAULT_TIME_GRANULARITY } from './constants' import { buildDefaultDashboardFilters, getDefaultDays, getSavedChartPreferences, getSavedGranularity, saveChartPreferences, } from './lib' import { type DashboardSectionId, DASHBOARD_DEFAULT_SECTION, DASHBOARD_SECTION_IDS, } from './section-registry' import type { DashboardChartPreferences, DashboardFilters, QuotaDataItem, UserChartsFilters, } from './types' const route = getRouteApi('/_authenticated/dashboard/$section') const LOG_STAT_CARD_FALLBACK_KEYS = [ 'count', 'quota', 'tokens', 'average-rpm', 'average-tpm', ] as const const PERFORMANCE_METRIC_FALLBACK_KEYS = [ 'success-rate', 'average-latency', 'throughput', ] as const const PERFORMANCE_MODEL_FALLBACK_KEYS = [ 'primary-model', 'secondary-model', ] as const const LazyLogStatCards = lazy(() => import('./components/models/log-stat-cards').then((m) => ({ default: m.LogStatCards, })) ) const LazyModelCharts = lazy(() => import('./components/models/model-charts').then((m) => ({ default: m.ModelCharts, })) ) const LazyConsumptionDistributionChart = lazy(() => import('./components/models/consumption-distribution-chart').then((m) => ({ default: m.ConsumptionDistributionChart, })) ) const LazyPerformanceOverview = lazy(() => import('./components/models/performance-overview').then((m) => ({ default: m.PerformanceOverview, })) ) const LazyUserCharts = lazy(() => import('./components/users/user-charts').then((m) => ({ default: m.UserCharts, })) ) const LazyFlowCharts = lazy(() => import('./components/flow/flow-charts').then((m) => ({ default: m.FlowCharts, })) ) function LogStatCardsFallback() { return (
{LOG_STAT_CARD_FALLBACK_KEYS.map((key, index) => (
))}
) } function ModelChartsFallback() { return (
) } function PerformanceOverviewFallback() { return (
{PERFORMANCE_METRIC_FALLBACK_KEYS.map((key) => (
))}
{PERFORMANCE_MODEL_FALLBACK_KEYS.map((key) => ( ))}
) } const SECTION_META: Record = { overview: { titleKey: 'Overview', }, models: { titleKey: 'Model Call Analytics', }, flow: { titleKey: 'Flow', }, users: { titleKey: 'User Analytics', }, } export function Dashboard() { const { t } = useTranslation() const navigate = useNavigate() const params = route.useParams() const userRole = useAuthStore((state) => state.auth.user?.role) const activeSection = (params.section ?? DASHBOARD_DEFAULT_SECTION) as DashboardSectionId const [modelData, setModelData] = useState([]) const [dataLoading, setDataLoading] = useState(false) const [chartPreferences, setChartPreferences] = useState(() => getSavedChartPreferences()) const [modelFilters, setModelFilters] = useState(() => buildDefaultDashboardFilters(getSavedChartPreferences()) ) const [userChartsFilters, setUserChartsFilters] = useState( () => { const granularity = getSavedGranularity() return { timeGranularity: granularity, selectedRange: getDefaultDays(granularity), topUserLimit: 10, } } ) const [flowSensitiveVisible, setFlowSensitiveVisible] = useState(true) const handleFilterChange = useCallback((filters: DashboardFilters) => { setModelFilters(filters) }, []) const handleResetFilters = useCallback(() => { setModelFilters(buildDefaultDashboardFilters(chartPreferences)) }, [chartPreferences]) const handleDataUpdate = useCallback( (data: QuotaDataItem[], loading: boolean) => { setModelData(data) setDataLoading(loading) }, [] ) const handleChartPreferencesChange = useCallback( (preferences: DashboardChartPreferences) => { setChartPreferences(preferences) setModelFilters(buildDefaultDashboardFilters(preferences)) saveChartPreferences(preferences) }, [] ) const meta = SECTION_META[activeSection] ?? SECTION_META.overview const isAdmin = Boolean(userRole && userRole >= ROLE.ADMIN) const visibleSections = useMemo( () => DASHBOARD_SECTION_IDS.filter( (section) => section !== 'overview' && (section !== 'users' || isAdmin) ), [isAdmin] ) const handleSectionChange = useCallback( (section: string) => { void navigate({ to: '/dashboard/$section', params: { section: section as DashboardSectionId }, }) }, [navigate] ) const showSectionTabs = activeSection !== 'overview' && visibleSections.length > 1 const modelActions = activeSection === 'models' ? ( <> ) : null const flowActions = activeSection === 'flow' ? ( <> setFlowSensitiveVisible((prev) => !prev)} aria-label={ flowSensitiveVisible ? t('Hide sensitive data') : t('Show sensitive data') } className='text-muted-foreground hover:text-foreground size-8' /> } > {flowSensitiveVisible ? : } {flowSensitiveVisible ? t('Hide sensitive data') : t('Show sensitive data')} ) : null const sectionActions = modelActions ?? flowActions return ( {t(meta.titleKey)}
{activeSection !== 'overview' && (
{showSectionTabs ? ( {visibleSections.map((section) => ( {t(SECTION_META[section].titleKey)} ))} ) : (
)} {sectionActions != null && (
{sectionActions}
)}
)} {activeSection === 'overview' && } {activeSection === 'models' && ( <> }> {isAdmin && ( }> )} }> }> )} {activeSection === 'users' && ( }> )} {activeSection === 'flow' && ( }> )}
) }