/* 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 ( <>