import { useEffect, useMemo, useState } from 'react'; import { fetchAdminSettings, saveAdminSettings } from './api/settingsApi'; import AdminTabs from './components/AdminTabs'; import SettingField from './components/SettingField'; const TAB_GENERAL = 'general'; const TAB_APPEARANCE = 'appearance'; const TAB_API = 'api'; const TAB_BEHAVIOR = 'behavior'; const tabs = [ { id: TAB_GENERAL, label: 'General Settings' }, { id: TAB_API, label: 'API Settings' }, { id: TAB_APPEARANCE, label: 'Appearance' }, { id: TAB_BEHAVIOR, label: 'Behavior Controls' }, ]; function getFieldConfig(meta, settings) { const selectedProvider = settings?.acosmaia_api_provider || 'openrouter'; const apiFields = [ { name: 'acosmaia_api_provider', label: 'AI Provider', type: 'card-selector', className: 'wp-ai-provider-selector', options: [ { label: 'OpenRouter', value: 'openrouter' }, { label: 'OpenAI', value: 'openai' }, { label: 'Google Gemini', value: 'gemini' }, ], description: 'Select which AI provider to use for chat responses.', }, ]; // OpenRouter fields if (selectedProvider === 'openrouter') { apiFields.push( { name: 'acosmaia_openrouter_key', label: 'OpenRouter API Key', type: 'password', placeholder: 'sk-or-...', description: 'Get your key from https://openrouter.ai', }, { name: 'acosmaia_model', label: 'AI Model', type: 'select', options: meta?.model_options || [], description: 'Select the AI model to use for responses.', } ); } // OpenAI fields if (selectedProvider === 'openai') { apiFields.push( { name: 'acosmaia_openai_key', label: 'OpenAI API Key', type: 'password', placeholder: 'sk-...', description: 'Get your key from https://platform.openai.com/api-keys', }, { name: 'acosmaia_openai_model', label: 'OpenAI Model', type: 'select', options: [ { label: 'GPT-3.5 Turbo', value: 'gpt-3.5-turbo' }, { label: 'GPT-4', value: 'gpt-4' }, { label: 'GPT-4 Turbo', value: 'gpt-4-turbo-preview' }, ], description: 'Select the OpenAI model to use.', } ); } // Gemini fields if (selectedProvider === 'gemini') { apiFields.push( { name: 'acosmaia_gemini_key', label: 'Google Gemini API Key', type: 'password', placeholder: 'AIzaSy...', description: 'Get your key from https://makersuite.google.com/app/apikey', }, { name: 'acosmaia_gemini_model', label: 'Gemini Model', type: 'select', options: [ { label: 'Gemini Pro', value: 'gemini-pro' }, { label: 'Gemini 1.5 Pro', value: 'gemini-1.5-pro' }, ], description: 'Select the Gemini model to use.', } ); } // Common settings for all providers apiFields.push( { name: 'acosmaia_temperature', label: 'Temperature (0-2)', type: 'number', min: 0, max: 2, step: 0.1, description: 'Controls AI creativity: 0 = focused & factual, 0.5 = balanced (default), 2 = creative & varied. Use lower values for product recommendations.' }, { name: 'acosmaia_max_tokens', label: 'Max response tokens', type: 'number', min: 100, max: 4000, step: 1 }, { name: 'acosmaia_timeout', label: 'Timeout (seconds)', type: 'number', min: 5, max: 120, step: 1 }, { name: 'acosmaia_max_products', label: 'Max products to show', type: 'number', min: 1, max: 20, step: 1, description: 'Controls how many product cards can appear in the chat response.' }, { name: 'acosmaia_daily_limit', label: 'Daily token limit', type: 'number', min: 0, step: 1 }, { name: 'acosmaia_monthly_limit', label: 'Monthly token limit', type: 'number', min: 0, step: 1 } ); return { [TAB_GENERAL]: [ { name: 'acosmaia_enabled', label: 'Enable assistant', type: 'checkbox' }, { name: 'acosmaia_assistant_name', label: 'Assistant name', type: 'text' }, { name: 'acosmaia_welcome_message', label: 'Welcome message', type: 'textarea', rows: 3 }, ], [TAB_APPEARANCE]: [ { name: 'acosmaia_chat_position', label: 'Chat position', description: 'Choose where the floating chat button appears on your storefront.', type: 'card-selector', options: meta?.position_options || [], className: 'wp-ai-appearance-position', }, { name: 'acosmaia_bubble_icon', label: 'Bubble icon', description: 'Pick the icon style used in the floating chat button.', type: 'icon-selector', options: meta?.bubble_icon_options || [], className: 'wp-ai-appearance-icon', }, { name: 'acosmaia_chat_color', label: 'Primary color', description: 'Used for chat accents, header, and bubble color.', type: 'color', placeholder: '#0073aa', className: 'wp-ai-appearance-color', }, { name: 'acosmaia_default_theme', label: 'Default theme', description: 'Set the default visual mode for the chat window.', type: 'card-selector', options: meta?.theme_options || [], className: 'wp-ai-appearance-theme', }, ], [TAB_API]: apiFields, [TAB_BEHAVIOR]: [ { name: 'acosmaia_restrict_product_only', label: 'Only product-related replies', type: 'checkbox' }, { name: 'acosmaia_enabled_pages', label: 'Page Access For AI', type: 'multi-checkbox', options: meta?.page_options || [], description: 'Enable pages whose content should be available to AI responses.', className: 'wp-ai-page-access', }, { name: 'acosmaia_fallback_response', label: 'Fallback response', type: 'textarea', rows: 3 }, { name: 'acosmaia_knowledge_text', label: 'Store knowledge', type: 'textarea', rows: 4 }, ], }; } export default function AdminApp() { const { api_url: apiUrl = '', nonce = '' } = window.acosmaiaAdmin || {}; const [activeTab, setActiveTab] = useState(TAB_GENERAL); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); const [message, setMessage] = useState(''); const [meta, setMeta] = useState(null); const [stats, setStats] = useState(null); const [settings, setSettings] = useState({}); useEffect(() => { let isMounted = true; fetchAdminSettings(apiUrl, nonce) .then((data) => { if (!isMounted) return; setSettings(data.options || {}); setStats(data.stats || null); setMeta(data.meta || null); }) .catch((err) => { if (!isMounted) return; setError(err.message || 'Unable to load settings.'); }) .finally(() => { if (isMounted) setLoading(false); }); return () => { isMounted = false; }; }, [apiUrl, nonce]); const fieldsByTab = useMemo(() => getFieldConfig(meta, settings), [meta, settings]); const updateField = (name, value) => { setSettings((prev) => ({ ...prev, [name]: value })); if (message) setMessage(''); if (error) setError(''); }; const onSave = async () => { setSaving(true); setError(''); setMessage(''); try { const data = await saveAdminSettings(apiUrl, nonce, settings); setSettings(data.options || settings); setStats(data.stats || stats); setMessage('Settings saved successfully.'); } catch (err) { setError(err.message || 'Save failed.'); } finally { setSaving(false); } }; if (loading) { return
Loading AI Chat settings...
; } return (

WP AI Chat Assistance - Settings

Configure storefront chat, model behavior, and usage controls.

{stats ? (
{stats.total_chats || 0}Total chats
{stats.daily_tokens || 0}Daily tokens
{stats.monthly_tokens || 0}Monthly tokens
{stats.failed_queries || 0}Failed queries
) : null}
{(fieldsByTab[activeTab] || []).map((field) => ( ))}
{message ? {message} : null} {error ? {error} : null}
); }