'use client' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Checkbox } from '@/components/ui/checkbox' import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' import { Label } from '@/components/ui/label' import { updateSystemConfig, testSMTP } from '@/app/actions/admin-settings' import { toast } from 'sonner' import { useState, useEffect } from 'react' import Link from 'next/link' import { TestTube, ExternalLink } from 'lucide-react' type AIProvider = 'ollama' | 'openai' | 'custom' interface AvailableModels { tags: string[] embeddings: string[] } const MODELS_2026 = { ollama: { tags: ['llama3:latest', 'llama3.2:latest', 'granite4:latest', 'mistral:latest', 'mixtral:latest', 'phi3:latest', 'gemma2:latest', 'qwen2:latest'], embeddings: ['embeddinggemma:latest', 'mxbai-embed-large:latest', 'nomic-embed-text:latest'] }, openai: { tags: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo'], embeddings: ['text-embedding-3-small', 'text-embedding-3-large', 'text-embedding-ada-002'] }, custom: { tags: ['gpt-4o-mini', 'gpt-4o', 'claude-3-haiku', 'claude-3-sonnet', 'llama-3.1-8b'], embeddings: ['text-embedding-3-small', 'text-embedding-3-large', 'text-embedding-ada-002'] } } export function AdminSettingsForm({ config }: { config: Record }) { const [isSaving, setIsSaving] = useState(false) const [isTesting, setIsTesting] = useState(false) // Local state for Checkbox const [allowRegister, setAllowRegister] = useState(config.ALLOW_REGISTRATION !== 'false') const [smtpSecure, setSmtpSecure] = useState(config.SMTP_SECURE === 'true') const [smtpIgnoreCert, setSmtpIgnoreCert] = useState(config.SMTP_IGNORE_CERT === 'true') // AI Provider state - separated for tags and embeddings const [tagsProvider, setTagsProvider] = useState((config.AI_PROVIDER_TAGS as AIProvider) || 'ollama') const [embeddingsProvider, setEmbeddingsProvider] = useState((config.AI_PROVIDER_EMBEDDING as AIProvider) || 'ollama') // Sync state with config when server revalidates useEffect(() => { setAllowRegister(config.ALLOW_REGISTRATION !== 'false') setSmtpSecure(config.SMTP_SECURE === 'true') setSmtpIgnoreCert(config.SMTP_IGNORE_CERT === 'true') setTagsProvider((config.AI_PROVIDER_TAGS as AIProvider) || 'ollama') setEmbeddingsProvider((config.AI_PROVIDER_EMBEDDING as AIProvider) || 'ollama') }, [config]) const handleSaveSecurity = async (formData: FormData) => { setIsSaving(true) const data = { ALLOW_REGISTRATION: allowRegister ? 'true' : 'false', } const result = await updateSystemConfig(data) setIsSaving(false) if (result.error) { toast.error('Failed to update security settings') } else { toast.success('Security Settings updated') } } const handleSaveAI = async (formData: FormData) => { setIsSaving(true) const data: Record = {} // Tags provider configuration const tagsProv = formData.get('AI_PROVIDER_TAGS') as AIProvider data.AI_PROVIDER_TAGS = tagsProv data.AI_MODEL_TAGS = formData.get('AI_MODEL_TAGS') as string if (tagsProv === 'ollama') { data.OLLAMA_BASE_URL = formData.get('OLLAMA_BASE_URL_TAGS') as string } else if (tagsProv === 'openai') { data.OPENAI_API_KEY = formData.get('OPENAI_API_KEY') as string } else if (tagsProv === 'custom') { data.CUSTOM_OPENAI_API_KEY = formData.get('CUSTOM_OPENAI_API_KEY_TAGS') as string data.CUSTOM_OPENAI_BASE_URL = formData.get('CUSTOM_OPENAI_BASE_URL_TAGS') as string } // Embeddings provider configuration const embedProv = formData.get('AI_PROVIDER_EMBEDDING') as AIProvider data.AI_PROVIDER_EMBEDDING = embedProv data.AI_MODEL_EMBEDDING = formData.get('AI_MODEL_EMBEDDING') as string if (embedProv === 'ollama') { data.OLLAMA_BASE_URL = formData.get('OLLAMA_BASE_URL_EMBEDDING') as string } else if (embedProv === 'openai') { data.OPENAI_API_KEY = formData.get('OPENAI_API_KEY') as string } else if (embedProv === 'custom') { data.CUSTOM_OPENAI_API_KEY = formData.get('CUSTOM_OPENAI_API_KEY_EMBEDDING') as string data.CUSTOM_OPENAI_BASE_URL = formData.get('CUSTOM_OPENAI_BASE_URL_EMBEDDING') as string } const result = await updateSystemConfig(data) setIsSaving(false) if (result.error) { toast.error('Failed to update AI settings') } else { toast.success('AI Settings updated') setTagsProvider(tagsProv) setEmbeddingsProvider(embedProv) } } const handleSaveSMTP = async (formData: FormData) => { setIsSaving(true) const data = { SMTP_HOST: formData.get('SMTP_HOST') as string, SMTP_PORT: formData.get('SMTP_PORT') as string, SMTP_USER: formData.get('SMTP_USER') as string, SMTP_PASS: formData.get('SMTP_PASS') as string, SMTP_FROM: formData.get('SMTP_FROM') as string, SMTP_IGNORE_CERT: smtpIgnoreCert ? 'true' : 'false', SMTP_SECURE: smtpSecure ? 'true' : 'false', } const result = await updateSystemConfig(data) setIsSaving(false) if (result.error) { toast.error('Failed to update SMTP settings') } else { toast.success('SMTP Settings updated') } } const handleTestEmail = async () => { setIsTesting(true) try { const result: any = await testSMTP() if (result.success) { toast.success('Test email sent successfully!') } else { toast.error(`Failed: ${result.error}`) } } catch (e: any) { toast.error(`Error: ${e.message}`) } finally { setIsTesting(false) } } return (
Security Settings Manage access control and registration policies.
setAllowRegister(!!c)} />

If disabled, new users can only be added by an Administrator via the User Management page.

AI Configuration Configure AI providers for auto-tagging and semantic search. Use different providers for optimal performance.
{/* Tags Generation Section */}

🏷️ Tags Generation Provider

AI provider for automatic tag suggestions. Recommended: Ollama (free, local).

{/* Ollama Tags Config */} {tagsProvider === 'ollama' && (

Select an Ollama model installed on your system

)} {/* OpenAI Tags Config */} {tagsProvider === 'openai' && (

Your OpenAI API key from platform.openai.com

gpt-4o-mini = Best value • gpt-4o = Best quality

)} {/* Custom OpenAI Tags Config */} {tagsProvider === 'custom' && (

Common models for OpenAI-compatible APIs

)}
{/* Embeddings Section */}

🔍 Embeddings Provider

AI provider for semantic search embeddings. Recommended: OpenAI (best quality).

{/* Ollama Embeddings Config */} {embeddingsProvider === 'ollama' && (

Select an embedding model installed on your system

)} {/* OpenAI Embeddings Config */} {embeddingsProvider === 'openai' && (

Your OpenAI API key from platform.openai.com

text-embedding-3-small = Best value • text-embedding-3-large = Best quality

)} {/* Custom OpenAI Embeddings Config */} {embeddingsProvider === 'custom' && (

Common embedding models for OpenAI-compatible APIs

)}
SMTP Configuration Configure email server for password resets.
setSmtpSecure(!!c)} />
setSmtpIgnoreCert(!!c)} />
) }