/*
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 { useMemo, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Link } from '@tanstack/react-router'
import {
ArrowRight,
BookOpen,
Check,
ChevronDown,
ChevronUp,
Circle,
CreditCard,
FileText,
KeyRound,
ListChecks,
Play,
RadioTower,
ShieldCheck,
TerminalSquare,
Timer,
type LucideIcon,
} from 'lucide-react'
import { motion, useReducedMotion } from 'motion/react'
import { useTranslation } from 'react-i18next'
import { useAuthStore } from '@/stores/auth-store'
import { getUserModels } from '@/lib/api'
import { MOTION_TRANSITION } from '@/lib/motion'
import { ROLE } from '@/lib/roles'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { CopyButton } from '@/components/copy-button'
import {
CardStaggerContainer,
CardStaggerItem,
} from '@/components/page-transition'
import { fetchTokenKey, getApiKeys } from '@/features/keys/api'
import type { ApiKey } from '@/features/keys/types'
import {
useApiInfo,
useDashboardContentVisibility,
} from '../../hooks/use-status-data'
import { AnnouncementsPanel } from './announcements-panel'
import { ApiInfoPanel } from './api-info-panel'
import { FAQPanel } from './faq-panel'
import { PerformanceHealthPanel } from './performance-health-panel'
import { SummaryCards } from './summary-cards'
import { UptimePanel } from './uptime-panel'
const SETUP_GUIDE_VISIBILITY_STORAGE_KEY =
'dashboard_overview_setup_guide_expanded'
const SETUP_GUIDE_CODE_PATTERN = [
'const request = await client.responses.create({',
" model: 'gpt-4.1-mini',",
" input: 'Start routing traffic',",
'})',
'',
'if (request.output_text) {',
' console.log(request.output_text)',
'}',
].join('\n')
type DashboardActionPath =
| '/keys'
| '/wallet'
| '/playground'
| '/channels'
| '/usage-logs'
| '/pricing'
interface StartStep {
title: string
description: string
to: DashboardActionPath
icon: LucideIcon
completed: boolean
}
interface QuickAction {
title: string
description: string
to: DashboardActionPath
icon: LucideIcon
adminOnly?: boolean
}
interface RequestExample {
endpoint: string
model: string
keyName: string
displayKey: string
curl: string
ready: boolean
}
interface HeroSignal {
label: string
value: string
icon: LucideIcon
}
function getSavedSetupGuideExpanded(): boolean | null {
if (typeof window === 'undefined') return null
const saved = window.localStorage.getItem(SETUP_GUIDE_VISIBILITY_STORAGE_KEY)
if (saved === 'expanded') return true
if (saved === 'collapsed') return false
return null
}
function saveSetupGuideExpanded(expanded: boolean): void {
if (typeof window === 'undefined') return
window.localStorage.setItem(
SETUP_GUIDE_VISIBILITY_STORAGE_KEY,
expanded ? 'expanded' : 'collapsed'
)
}
function getCurrentOrigin(): string {
if (typeof window === 'undefined') return ''
return window.location.origin
}
function normalizeEndpoint(sourceUrl?: string): string {
const fallback = `${getCurrentOrigin()}/v1/chat/completions`
const trimmed = sourceUrl?.trim()
if (!trimmed) return fallback
const withoutTrailingSlash = trimmed.replace(/\/+$/, '')
if (withoutTrailingSlash.endsWith('/v1/chat/completions')) {
return withoutTrailingSlash
}
if (withoutTrailingSlash.endsWith('/v1')) {
return `${withoutTrailingSlash}/chat/completions`
}
return `${withoutTrailingSlash}/v1/chat/completions`
}
function getPreferredKey(keys: ApiKey[]): ApiKey | null {
return keys.find((item) => item.status === 1) ?? keys[0] ?? null
}
function formatDisplayKey(key?: string): string {
if (!key) return 'sk-...'
if (key.length <= 14) return key
return `${key.slice(0, 7)}...${key.slice(-4)}`
}
function buildCurlCommand(args: {
endpoint: string
apiKey: string
model: string
}): string {
return [
`curl ${args.endpoint} \\`,
' -H "Content-Type: application/json" \\',
` -H "Authorization: Bearer ${args.apiKey}" \\`,
` -d '{"model":"${args.model}","messages":[{"role":"user","content":"Say hello in one sentence."}]}'`,
].join('\n')
}
function SetupGuideBackdrop(props: { compact?: boolean }) {
return (
<>
{SETUP_GUIDE_CODE_PATTERN}
>
)
}
function StartStepItem(props: {
step: StartStep
index: number
isLast: boolean
}) {
const Icon = props.step.icon
const StatusIcon = props.step.completed ? Check : Circle
return (