/* 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 } from 'react' import { useTranslation } from 'react-i18next' import { useAuthStore } from '@/stores/auth-store' import { useStatus } from '@/hooks/use-status' export type TopNavLink = { title: string href: string disabled?: boolean external?: boolean } // Default navigation configuration const DEFAULT_HEADER_NAV_MODULES = { home: true, console: true, pricing: { enabled: true, requireAuth: false }, rankings: { enabled: true, requireAuth: false }, docs: true, about: true, } function parseAccessModule( raw: unknown, fallback: { enabled: boolean; requireAuth: boolean } ) { if ( typeof raw === 'boolean' || typeof raw === 'string' || typeof raw === 'number' ) { return { enabled: raw === true || raw === 'true' || raw === '1' || raw === 1, requireAuth: fallback.requireAuth, } } if (raw && typeof raw === 'object') { const record = raw as Record return { enabled: typeof record.enabled === 'boolean' ? record.enabled : fallback.enabled, requireAuth: typeof record.requireAuth === 'boolean' ? record.requireAuth : fallback.requireAuth, } } return { ...fallback } } function parseHeaderNavModules( raw: unknown ): typeof DEFAULT_HEADER_NAV_MODULES { if (!raw || String(raw).trim() === '') { return DEFAULT_HEADER_NAV_MODULES } try { const parsed = JSON.parse(String(raw)) as Record return { ...DEFAULT_HEADER_NAV_MODULES, ...parsed, pricing: parseAccessModule( parsed.pricing, DEFAULT_HEADER_NAV_MODULES.pricing ), rankings: parseAccessModule( parsed.rankings, DEFAULT_HEADER_NAV_MODULES.rankings ), } } catch { return DEFAULT_HEADER_NAV_MODULES } } /** * Generate top navigation links based on HeaderNavModules configuration from backend /api/status * Backend format example (stringified JSON): * { * home: true, * console: true, * pricing: { enabled: true, requireAuth: false }, * rankings: { enabled: true, requireAuth: false }, * docs: true, * about: true * } */ export function useTopNavLinks(): TopNavLink[] { const { t } = useTranslation() const { status } = useStatus() const { auth } = useAuthStore() // Parse HeaderNavModules const modules = useMemo(() => { return parseHeaderNavModules(status?.HeaderNavModules) }, [status?.HeaderNavModules]) // Documentation link (may be external) const docsLink: string | undefined = status?.docs_link as string | undefined const isAuthed = !!auth?.user const links: TopNavLink[] = [] // Home if (modules?.home !== false) { links.push({ title: t('Home'), href: '/' }) } // Console -> /dashboard (new console path) if (modules?.console !== false) { links.push({ title: t('Console'), href: '/dashboard' }) } // Pricing const pricing = modules?.pricing if (pricing && typeof pricing === 'object' && pricing.enabled) { const disabled = pricing.requireAuth && !isAuthed links.push({ title: t('Model Square'), href: '/pricing', disabled }) } // Rankings const rankings = modules?.rankings if (rankings && typeof rankings === 'object' && rankings.enabled) { const disabled = rankings.requireAuth && !isAuthed links.push({ title: t('Rankings'), href: '/rankings', disabled }) } // Docs (supports external links) if (modules?.docs !== false) { if (docsLink) { links.push({ title: t('Docs'), href: docsLink, external: true }) } else { links.push({ title: t('Docs'), href: '/docs' }) } } // About if (modules?.about !== false) { links.push({ title: t('About'), href: '/about' }) } return links }