/* 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 { useEffect, useMemo } from 'react' import * as z from 'zod' import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { useTranslation } from 'react-i18next' import { Form, FormControl, FormDescription, FormField, FormLabel, FormMessage, } from '@/components/ui/form' import { Switch } from '@/components/ui/switch' import { SettingsControlChildren, SettingsForm, SettingsSwitchContent, SettingsControlGroup, SettingsSwitchItem, } from '../components/settings-form-layout' import { SettingsPageFormActions } from '../components/settings-page-context' import { SettingsSection } from '../components/settings-section' import { useUpdateOption } from '../hooks/use-update-option' import { HEADER_NAV_DEFAULT, type HeaderNavModulesConfig, serializeHeaderNavModules, } from './config' const headerNavSchema = z.object({ home: z.boolean(), console: z.boolean(), pricingEnabled: z.boolean(), pricingRequireAuth: z.boolean(), rankingsEnabled: z.boolean(), rankingsRequireAuth: z.boolean(), docs: z.boolean(), about: z.boolean(), }) type HeaderNavFormValues = z.infer type HeaderNavigationSectionProps = { config: HeaderNavModulesConfig initialSerialized: string } const toFormValues = (config: HeaderNavModulesConfig): HeaderNavFormValues => ({ home: config.home === undefined ? HEADER_NAV_DEFAULT.home : Boolean(config.home), console: config.console === undefined ? HEADER_NAV_DEFAULT.console : Boolean(config.console), pricingEnabled: config.pricing?.enabled === undefined ? HEADER_NAV_DEFAULT.pricing.enabled : Boolean(config.pricing.enabled), pricingRequireAuth: config.pricing?.requireAuth === undefined ? HEADER_NAV_DEFAULT.pricing.requireAuth : Boolean(config.pricing.requireAuth), rankingsEnabled: config.rankings?.enabled === undefined ? HEADER_NAV_DEFAULT.rankings.enabled : Boolean(config.rankings.enabled), rankingsRequireAuth: config.rankings?.requireAuth === undefined ? HEADER_NAV_DEFAULT.rankings.requireAuth : Boolean(config.rankings.requireAuth), docs: config.docs === undefined ? HEADER_NAV_DEFAULT.docs : Boolean(config.docs), about: config.about === undefined ? HEADER_NAV_DEFAULT.about : Boolean(config.about), }) export function HeaderNavigationSection({ config, initialSerialized, }: HeaderNavigationSectionProps) { const { t } = useTranslation() const updateOption = useUpdateOption() const formDefaults = useMemo(() => toFormValues(config), [config]) const form = useForm({ resolver: zodResolver(headerNavSchema), defaultValues: formDefaults, }) useEffect(() => { form.reset(formDefaults) }, [formDefaults, form]) const onSubmit = async (values: HeaderNavFormValues) => { const payload: HeaderNavModulesConfig = { ...config, home: values.home, console: values.console, docs: values.docs, about: values.about, pricing: { ...(config.pricing ?? HEADER_NAV_DEFAULT.pricing), enabled: values.pricingEnabled, requireAuth: values.pricingRequireAuth, }, rankings: { ...(config.rankings ?? HEADER_NAV_DEFAULT.rankings), enabled: values.rankingsEnabled, requireAuth: values.rankingsRequireAuth, }, } const serialized = serializeHeaderNavModules(payload) if (serialized === initialSerialized) { return } await updateOption.mutateAsync({ key: 'HeaderNavModules', value: serialized, }) } const resetToDefault = () => { form.reset(toFormValues(HEADER_NAV_DEFAULT)) } const simpleModules: Array<{ key: keyof HeaderNavFormValues title: string description: string }> = [ { key: 'home', title: t('Home'), description: t('Landing page with system overview.'), }, { key: 'console', title: t('Console'), description: t('User dashboard and quota controls.'), }, { key: 'docs', title: t('Docs'), description: t('Documentation or external knowledge base.'), }, { key: 'about', title: t('About'), description: t('Static page describing the platform.'), }, ] const accessModules: Array<{ enabledKey: keyof HeaderNavFormValues requireAuthKey: keyof HeaderNavFormValues requireAuthDependsOn: 'pricingEnabled' | 'rankingsEnabled' title: string description: string requireAuthTitle: string requireAuthDescription: string }> = [ { enabledKey: 'pricingEnabled', requireAuthKey: 'pricingRequireAuth', requireAuthDependsOn: 'pricingEnabled', title: t('Model Square'), description: t('Public model catalog and pricing page.'), requireAuthTitle: t('Require login to view models'), requireAuthDescription: t( 'Visitors must authenticate before accessing the pricing directory.' ), }, { enabledKey: 'rankingsEnabled', requireAuthKey: 'rankingsRequireAuth', requireAuthDependsOn: 'rankingsEnabled', title: t('Rankings'), description: t('Public rankings page based on live usage data.'), requireAuthTitle: t('Require login to view rankings'), requireAuthDescription: t( 'Visitors must authenticate before accessing the rankings page.' ), }, ] return ( {simpleModules.map((module) => ( ( {module.title} {module.description} )} /> ))} {accessModules.map((module) => ( ( {module.title} {module.description} )} /> ( {module.requireAuthTitle} {module.requireAuthDescription} )} /> ))} ) }