185 lines
6.3 KiB
TypeScript
185 lines
6.3 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { SettingsNav, SettingsSection, SettingToggle, SettingSelect, SettingInput } from '@/components/settings'
|
|
import { updateAISettings } from '@/app/actions/ai-settings'
|
|
import { toast } from 'sonner'
|
|
import { useLanguage } from '@/lib/i18n'
|
|
|
|
export default function AISettingsPage() {
|
|
const { t } = useLanguage()
|
|
const [apiKey, setApiKey] = useState('')
|
|
|
|
// Mock settings state - in real implementation, load from server
|
|
const [settings, setSettings] = useState({
|
|
titleSuggestions: true,
|
|
semanticSearch: true,
|
|
paragraphRefactor: true,
|
|
memoryEcho: true,
|
|
memoryEchoFrequency: 'daily' as 'daily' | 'weekly' | 'custom',
|
|
aiProvider: 'auto' as 'auto' | 'openai' | 'ollama',
|
|
preferredLanguage: 'auto' as 'auto' | 'en' | 'fr' | 'es' | 'de' | 'fa' | 'it' | 'pt' | 'ru' | 'zh' | 'ja' | 'ko' | 'ar' | 'hi' | 'nl' | 'pl',
|
|
demoMode: false
|
|
})
|
|
|
|
const handleToggle = async (feature: string, value: boolean) => {
|
|
setSettings(prev => ({ ...prev, [feature]: value }))
|
|
try {
|
|
await updateAISettings({ [feature]: value })
|
|
} catch (error) {
|
|
toast.error(t('aiSettings.error'))
|
|
setSettings(settings) // Revert on error
|
|
}
|
|
}
|
|
|
|
const handleFrequencyChange = async (value: string) => {
|
|
setSettings(prev => ({ ...prev, memoryEchoFrequency: value as any }))
|
|
try {
|
|
await updateAISettings({ memoryEchoFrequency: value as any })
|
|
} catch (error) {
|
|
toast.error(t('aiSettings.error'))
|
|
}
|
|
}
|
|
|
|
const handleProviderChange = async (value: string) => {
|
|
setSettings(prev => ({ ...prev, aiProvider: value as any }))
|
|
try {
|
|
await updateAISettings({ aiProvider: value as any })
|
|
} catch (error) {
|
|
toast.error(t('aiSettings.error'))
|
|
}
|
|
}
|
|
|
|
const handleApiKeyChange = async (value: string) => {
|
|
setApiKey(value)
|
|
// TODO: Implement API key persistence
|
|
|
|
}
|
|
|
|
return (
|
|
<div className="container mx-auto py-10 px-4 max-w-6xl">
|
|
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
|
{/* Sidebar Navigation */}
|
|
<aside className="lg:col-span-1">
|
|
<SettingsNav />
|
|
</aside>
|
|
|
|
{/* Main Content */}
|
|
<main className="lg:col-span-3 space-y-6">
|
|
<div>
|
|
<h1 className="text-3xl font-bold mb-2">{t('aiSettings.title')}</h1>
|
|
<p className="text-gray-600 dark:text-gray-400">
|
|
{t('aiSettings.description')}
|
|
</p>
|
|
</div>
|
|
|
|
{/* AI Provider */}
|
|
<SettingsSection
|
|
title={t('aiSettings.provider')}
|
|
icon={<span className="text-2xl">🤖</span>}
|
|
description={t('aiSettings.providerDesc')}
|
|
>
|
|
<SettingSelect
|
|
label={t('aiSettings.provider')}
|
|
description={t('aiSettings.providerDesc')}
|
|
value={settings.aiProvider}
|
|
options={[
|
|
{
|
|
value: 'auto',
|
|
label: t('aiSettings.providerAuto'),
|
|
description: t('aiSettings.providerAutoDesc')
|
|
},
|
|
{
|
|
value: 'ollama',
|
|
label: t('aiSettings.providerOllama'),
|
|
description: t('aiSettings.providerOllamaDesc')
|
|
},
|
|
{
|
|
value: 'openai',
|
|
label: t('aiSettings.providerOpenAI'),
|
|
description: t('aiSettings.providerOpenAIDesc')
|
|
},
|
|
]}
|
|
onChange={handleProviderChange}
|
|
/>
|
|
|
|
{settings.aiProvider === 'openai' && (
|
|
<SettingInput
|
|
label={t('admin.ai.apiKey')}
|
|
description={t('admin.ai.openAIKeyDescription')}
|
|
value={apiKey}
|
|
type="password"
|
|
placeholder="sk-..."
|
|
onChange={handleApiKeyChange}
|
|
/>
|
|
)}
|
|
</SettingsSection>
|
|
|
|
{/* Feature Toggles */}
|
|
<SettingsSection
|
|
title={t('aiSettings.features')}
|
|
icon={<span className="text-2xl">✨</span>}
|
|
description={t('aiSettings.description')}
|
|
>
|
|
<SettingToggle
|
|
label={t('titleSuggestions.available').replace('💡 ', '')}
|
|
description={t('aiSettings.titleSuggestionsDesc')}
|
|
checked={settings.titleSuggestions}
|
|
onChange={(checked) => handleToggle('titleSuggestions', checked)}
|
|
/>
|
|
|
|
<SettingToggle
|
|
label={t('semanticSearch.exactMatch')}
|
|
description={t('semanticSearch.searching')}
|
|
checked={settings.semanticSearch}
|
|
onChange={(checked) => handleToggle('semanticSearch', checked)}
|
|
/>
|
|
|
|
<SettingToggle
|
|
label={t('paragraphRefactor.title')}
|
|
description={t('aiSettings.paragraphRefactorDesc')}
|
|
checked={settings.paragraphRefactor}
|
|
onChange={(checked) => handleToggle('paragraphRefactor', checked)}
|
|
/>
|
|
|
|
<SettingToggle
|
|
label={t('memoryEcho.title')}
|
|
description={t('memoryEcho.dailyInsight')}
|
|
checked={settings.memoryEcho}
|
|
onChange={(checked) => handleToggle('memoryEcho', checked)}
|
|
/>
|
|
|
|
{settings.memoryEcho && (
|
|
<SettingSelect
|
|
label={t('aiSettings.frequency')}
|
|
description={t('aiSettings.frequencyDesc')}
|
|
value={settings.memoryEchoFrequency}
|
|
options={[
|
|
{ value: 'daily', label: t('aiSettings.frequencyDaily') },
|
|
{ value: 'weekly', label: t('aiSettings.frequencyWeekly') },
|
|
{ value: 'custom', label: 'Custom' },
|
|
]}
|
|
onChange={handleFrequencyChange}
|
|
/>
|
|
)}
|
|
</SettingsSection>
|
|
|
|
{/* Demo Mode */}
|
|
<SettingsSection
|
|
title={t('demoMode.title')}
|
|
icon={<span className="text-2xl">🎭</span>}
|
|
description={t('demoMode.description')}
|
|
>
|
|
<SettingToggle
|
|
label={t('demoMode.title')}
|
|
description={t('demoMode.description')}
|
|
checked={settings.demoMode}
|
|
onChange={(checked) => handleToggle('demoMode', checked)}
|
|
/>
|
|
</SettingsSection>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|