import React, { useCallback } from "react"; import { appContext } from "../../hooks/provider"; import SignInModal from "../signin"; import { useSettingsStore } from "../store"; import { settingsAPI } from "../views/api"; import GeneralSettings from "./tabs/GeneralSettings/GeneralSettings"; import AgentSettingsTab from "./tabs/agentSettings/AgentSettingsTab"; import AdvancedConfigEditor from "./tabs/advancedSetings/AdvancedSettings"; import { Button, Divider, Flex, message, Modal, Spin, Tabs, Typography, } from "antd"; import { validateAll } from "./validation"; interface SettingsMenuProps { isOpen: boolean; onClose: () => void; } const SettingsModal: React.FC = ({ isOpen, onClose }) => { const { darkMode, setDarkMode, user } = React.useContext(appContext); const [isEmailModalOpen, setIsEmailModalOpen] = React.useState(false); const [hasChanges, setHasChanges] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false); const [originalConfig, setOriginalConfig] = React.useState(null); const { config, updateConfig, resetToDefaults } = useSettingsStore(); React.useEffect(() => { if (isOpen) { setHasChanges(false); setIsLoading(true); // Load settings when modal opens const loadSettings = async () => { if (user?.email) { try { const settings = await settingsAPI.getSettings(user.email); // Merge backend settings with frontend defaults const { config: defaultConfig } = useSettingsStore.getState(); const mergedConfig = { ...defaultConfig, ...settings }; // Always use the merged config since we provide proper defaults updateConfig(mergedConfig); setOriginalConfig(mergedConfig); } catch (error) { message.error( "Failed to load settings. Using defaults. Error: " + error ); resetToDefaults(); setOriginalConfig(null); } } setIsLoading(false); }; loadSettings(); } }, [isOpen, user?.email]); const handleUpdateConfig = async (changes: any) => { updateConfig(changes); setHasChanges(true); }; const handleResetDefaults = async () => { resetToDefaults(); setHasChanges(true); }; const handleClose = useCallback(async () => { // Check all validation states before saving const validationErrors = validateAll(config); if (validationErrors.length > 0) { const errors = validationErrors.join("\n"); message.error(errors); return; } // Only save if there are actual changes const hasActualChanges = originalConfig && JSON.stringify(config) !== JSON.stringify(originalConfig); if (hasActualChanges && user?.email) { try { await settingsAPI.updateSettings(user.email, config); message.success("Updated settings!"); } catch (error) { message.error("Failed to save settings"); console.error("Failed to save settings:", error); return; } } onClose(); }, [config, originalConfig, user?.email, onClose]); const tabItems = { general: { label: "General", children: ( <> General Settings ), }, agents: { label: "Agent Settings", children: ( <> Agent Settings ), }, advanced_config: { label: "Advanced Settings", children: ( <> Advanced Settings ), }, }; return ( <> {hasChanges && ( Warning: Settings changes will only apply when you create a new session )} , ]} > {isLoading ? ( ) : ( ({ key, label, children }) )} /> )} setIsEmailModalOpen(false)} /> ); }; export default SettingsModal;