import React, { useReducer, useEffect, useCallback, useRef } from 'react'; import { Modal, Badge, Button, Group, Title, Stack, Accordion, } from '@mantine/core'; import { notifications } from '@mantine/notifications'; import { useWorkspace } from '../../../contexts/WorkspaceContext'; import AppearanceSettings from './AppearanceSettings'; import EditorSettings from './EditorSettings'; import GitSettings from './GitSettings'; import GeneralSettings from './GeneralSettings'; import { useModalContext } from '../../../contexts/ModalContext'; import DangerZoneSettings from './DangerZoneSettings'; import AccordionControl from '../AccordionControl'; const initialState = { localSettings: {}, initialSettings: {}, hasUnsavedChanges: false, }; function settingsReducer(state, action) { switch (action.type) { case 'INIT_SETTINGS': return { ...state, localSettings: action.payload, initialSettings: action.payload, hasUnsavedChanges: false, }; case 'UPDATE_LOCAL_SETTINGS': const newLocalSettings = { ...state.localSettings, ...action.payload }; const hasChanges = JSON.stringify(newLocalSettings) !== JSON.stringify(state.initialSettings); return { ...state, localSettings: newLocalSettings, hasUnsavedChanges: hasChanges, }; case 'MARK_SAVED': return { ...state, initialSettings: state.localSettings, hasUnsavedChanges: false, }; default: return state; } } const WorkspaceSettings = () => { const { currentWorkspace, updateSettings } = useWorkspace(); const { settingsModalVisible, setSettingsModalVisible } = useModalContext(); const [state, dispatch] = useReducer(settingsReducer, initialState); const isInitialMount = useRef(true); useEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; const settings = { name: currentWorkspace.name, theme: currentWorkspace.theme, autoSave: currentWorkspace.autoSave, showHiddenFiles: currentWorkspace.showHiddenFiles, gitEnabled: currentWorkspace.gitEnabled, gitUrl: currentWorkspace.gitUrl, gitUser: currentWorkspace.gitUser, gitToken: currentWorkspace.gitToken, gitAutoCommit: currentWorkspace.gitAutoCommit, gitCommitMsgTemplate: currentWorkspace.gitCommitMsgTemplate, }; dispatch({ type: 'INIT_SETTINGS', payload: settings }); } }, [currentWorkspace]); const handleInputChange = useCallback((key, value) => { dispatch({ type: 'UPDATE_LOCAL_SETTINGS', payload: { [key]: value } }); }, []); const handleSubmit = async () => { try { if (!state.localSettings.name?.trim()) { notifications.show({ message: 'Workspace name cannot be empty', color: 'red', }); return; } await updateSettings(state.localSettings); dispatch({ type: 'MARK_SAVED' }); notifications.show({ message: 'Settings saved successfully', color: 'green', }); setSettingsModalVisible(false); } catch (error) { console.error('Failed to save settings:', error); notifications.show({ message: 'Failed to save settings: ' + error.message, color: 'red', }); } }; const handleClose = useCallback(() => { setSettingsModalVisible(false); }, [setSettingsModalVisible]); return ( Workspace Settings} centered size="lg" > {state.hasUnsavedChanges && ( Unsaved Changes )} ({ control: { paddingTop: theme.spacing.md, paddingBottom: theme.spacing.md, }, item: { borderBottom: `1px solid ${ theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3] }`, '&[data-active]': { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[7] : theme.colors.gray[0], }, }, chevron: { '&[data-rotate]': { transform: 'rotate(180deg)', }, }, })} > General Appearance handleInputChange('theme', newTheme) } /> Editor handleInputChange('autoSave', value) } showHiddenFiles={state.localSettings.showHiddenFiles} onShowHiddenFilesChange={(value) => handleInputChange('showHiddenFiles', value) } /> Git Integration Danger Zone ); }; export default WorkspaceSettings;