/* 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 { useForm } from 'react-hook-form' import { useTranslation } from 'react-i18next' import { Form, FormControl, FormDescription, FormField, FormLabel, } 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 { SIDEBAR_MODULES_DEFAULT, type SidebarModulesAdminConfig, serializeSidebarModulesAdmin, } from './config' type SidebarModulesSectionProps = { config: SidebarModulesAdminConfig initialSerialized: string } type SidebarFormValues = SidebarModulesAdminConfig const toTitleCase = (value: string) => value.replaceAll(/[_-]+/g, ' ').replaceAll(/\b\w/g, (char) => char.toUpperCase()) export function SidebarModulesSection({ config, initialSerialized, }: SidebarModulesSectionProps) { const { t } = useTranslation() const updateOption = useUpdateOption() const sectionMeta: Record = { chat: { title: t('Chat area'), description: t('Playground experiments and live conversations.'), }, console: { title: t('Console area'), description: t('Dashboards, tokens, and usage analytics.'), }, personal: { title: t('Personal area'), description: t('Wallet management and personal preferences.'), }, admin: { title: t('Admin area'), description: t('Global configuration and administrative tools.'), }, } const moduleMeta: Record< string, Record > = { chat: { playground: { title: t('Playground'), description: t('Experiment with prompts and models in real time.'), }, chat: { title: t('Chat'), description: t('Access previous conversations and start new ones.'), }, }, console: { detail: { title: t('Dashboard'), description: t('Aggregated usage metrics and trend charts.'), }, token: { title: t('Token management'), description: t('Create, revoke, and audit API tokens.'), }, log: { title: t('Usage logs'), description: t('Detailed request logs for investigations.'), }, midjourney: { title: t('Drawing logs'), description: t('History of MjProxy-style image tasks.'), }, task: { title: t('Task logs'), description: t('Background job tracker for queued work.'), }, }, personal: { topup: { title: t('Wallet'), description: t('Top up balance and view billing history.'), }, personal: { title: t('Profile'), description: t('Personal settings and profile management.'), }, }, admin: { channel: { title: t('Channels'), description: t('Configure upstream providers and routing.'), }, models: { title: t('Models'), description: t('Manage catalog visibility and pricing.'), }, redemption: { title: t('Redeem codes'), description: t('Create and review invite or credit codes.'), }, user: { title: t('Users'), description: t('Administer user accounts and roles.'), }, setting: { title: t('System settings'), description: t('Advanced platform configuration.'), }, subscription: { title: t('Subscription Management'), description: t('Manage subscription plans and pricing.'), }, }, } const formDefaults = useMemo(() => config, [config]) const form = useForm({ defaultValues: formDefaults, }) useEffect(() => { form.reset(formDefaults) }, [formDefaults, form]) const onSubmit = async (values: SidebarFormValues) => { const serialized = serializeSidebarModulesAdmin(values) if (serialized === initialSerialized) { return } await updateOption.mutateAsync({ key: 'SidebarModulesAdmin', value: serialized, }) } const resetToDefault = () => { form.reset(SIDEBAR_MODULES_DEFAULT) } const sections = Object.entries(config) return (
{sections.map(([sectionKey, sectionConfig]) => { const sectionInfo = sectionMeta[sectionKey] ?? { title: toTitleCase(sectionKey), description: t('Custom sidebar section'), } const modules = Object.entries(sectionConfig).filter( ([moduleKey]) => moduleKey !== 'enabled' ) return ( ( {sectionInfo.title} {sectionInfo.description} )} /> {modules.map(([moduleKey]) => { const moduleInfo = moduleMeta[sectionKey]?.[moduleKey] ?? { title: toTitleCase(moduleKey), description: t('Custom module'), } return ( ( {moduleInfo.title} {moduleInfo.description} )} /> ) })} ) })}
) }