mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-07 16:34:26 +00:00
Rename root folders
This commit is contained in:
120
app/src/contexts/AuthContext.jsx
Normal file
120
app/src/contexts/AuthContext.jsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
useCallback,
|
||||
useEffect,
|
||||
} from 'react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import * as authApi from '../services/authApi';
|
||||
|
||||
const AuthContext = createContext(null);
|
||||
|
||||
export const AuthProvider = ({ children }) => {
|
||||
const [user, setUser] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
// Load user data on mount
|
||||
useEffect(() => {
|
||||
const initializeAuth = async () => {
|
||||
try {
|
||||
const storedToken = localStorage.getItem('accessToken');
|
||||
if (storedToken) {
|
||||
authApi.setAuthToken(storedToken);
|
||||
const userData = await authApi.getCurrentUser();
|
||||
setUser(userData);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize auth:', error);
|
||||
localStorage.removeItem('accessToken');
|
||||
authApi.clearAuthToken();
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setInitialized(true);
|
||||
}
|
||||
};
|
||||
|
||||
initializeAuth();
|
||||
}, []);
|
||||
|
||||
const login = useCallback(async (email, password) => {
|
||||
try {
|
||||
const { accessToken, user: userData } = await authApi.login(
|
||||
email,
|
||||
password
|
||||
);
|
||||
localStorage.setItem('accessToken', accessToken);
|
||||
authApi.setAuthToken(accessToken);
|
||||
setUser(userData);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Logged in successfully',
|
||||
color: 'green',
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: error.message || 'Login failed',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const logout = useCallback(async () => {
|
||||
try {
|
||||
await authApi.logout();
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error);
|
||||
} finally {
|
||||
localStorage.removeItem('accessToken');
|
||||
authApi.clearAuthToken();
|
||||
setUser(null);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const refreshToken = useCallback(async () => {
|
||||
try {
|
||||
const { accessToken } = await authApi.refreshToken();
|
||||
localStorage.setItem('accessToken', accessToken);
|
||||
authApi.setAuthToken(accessToken);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Token refresh failed:', error);
|
||||
await logout();
|
||||
return false;
|
||||
}
|
||||
}, [logout]);
|
||||
|
||||
const refreshUser = useCallback(async () => {
|
||||
try {
|
||||
const userData = await authApi.getCurrentUser();
|
||||
setUser(userData);
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh user data:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const value = {
|
||||
user,
|
||||
loading,
|
||||
initialized,
|
||||
login,
|
||||
logout,
|
||||
refreshToken,
|
||||
refreshUser,
|
||||
};
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error('useAuth must be used within an AuthProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
36
app/src/contexts/ModalContext.jsx
Normal file
36
app/src/contexts/ModalContext.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
|
||||
const ModalContext = createContext();
|
||||
|
||||
export const ModalProvider = ({ children }) => {
|
||||
const [newFileModalVisible, setNewFileModalVisible] = useState(false);
|
||||
const [deleteFileModalVisible, setDeleteFileModalVisible] = useState(false);
|
||||
const [commitMessageModalVisible, setCommitMessageModalVisible] =
|
||||
useState(false);
|
||||
const [settingsModalVisible, setSettingsModalVisible] = useState(false);
|
||||
const [switchWorkspaceModalVisible, setSwitchWorkspaceModalVisible] =
|
||||
useState(false);
|
||||
const [createWorkspaceModalVisible, setCreateWorkspaceModalVisible] =
|
||||
useState(false);
|
||||
|
||||
const value = {
|
||||
newFileModalVisible,
|
||||
setNewFileModalVisible,
|
||||
deleteFileModalVisible,
|
||||
setDeleteFileModalVisible,
|
||||
commitMessageModalVisible,
|
||||
setCommitMessageModalVisible,
|
||||
settingsModalVisible,
|
||||
setSettingsModalVisible,
|
||||
switchWorkspaceModalVisible,
|
||||
setSwitchWorkspaceModalVisible,
|
||||
createWorkspaceModalVisible,
|
||||
setCreateWorkspaceModalVisible,
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalContext.Provider value={value}>{children}</ModalContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useModalContext = () => useContext(ModalContext);
|
||||
211
app/src/contexts/WorkspaceContext.jsx
Normal file
211
app/src/contexts/WorkspaceContext.jsx
Normal file
@@ -0,0 +1,211 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { useMantineColorScheme } from '@mantine/core';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import {
|
||||
fetchLastWorkspaceName,
|
||||
getWorkspace,
|
||||
updateWorkspace,
|
||||
updateLastWorkspaceName,
|
||||
deleteWorkspace,
|
||||
listWorkspaces,
|
||||
} from '../services/api';
|
||||
import { DEFAULT_WORKSPACE_SETTINGS } from '../utils/constants';
|
||||
|
||||
const WorkspaceContext = createContext();
|
||||
|
||||
export const WorkspaceProvider = ({ children }) => {
|
||||
const [currentWorkspace, setCurrentWorkspace] = useState(null);
|
||||
const [workspaces, setWorkspaces] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
||||
|
||||
const loadWorkspaces = useCallback(async () => {
|
||||
try {
|
||||
const workspaceList = await listWorkspaces();
|
||||
setWorkspaces(workspaceList);
|
||||
return workspaceList;
|
||||
} catch (error) {
|
||||
console.error('Failed to load workspaces:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to load workspaces list',
|
||||
color: 'red',
|
||||
});
|
||||
return [];
|
||||
}
|
||||
}, []);
|
||||
|
||||
const loadWorkspaceData = useCallback(async (workspaceName) => {
|
||||
try {
|
||||
const workspace = await getWorkspace(workspaceName);
|
||||
setCurrentWorkspace(workspace);
|
||||
setColorScheme(workspace.theme);
|
||||
} catch (error) {
|
||||
console.error('Failed to load workspace data:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to load workspace data',
|
||||
color: 'red',
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const loadFirstAvailableWorkspace = useCallback(async () => {
|
||||
try {
|
||||
const allWorkspaces = await listWorkspaces();
|
||||
if (allWorkspaces.length > 0) {
|
||||
const firstWorkspace = allWorkspaces[0];
|
||||
await updateLastWorkspaceName(firstWorkspace.name);
|
||||
await loadWorkspaceData(firstWorkspace.name);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load first available workspace:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to load workspace',
|
||||
color: 'red',
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const initializeWorkspace = async () => {
|
||||
try {
|
||||
const { lastWorkspaceName } = await fetchLastWorkspaceName();
|
||||
if (lastWorkspaceName) {
|
||||
await loadWorkspaceData(lastWorkspaceName);
|
||||
} else {
|
||||
await loadFirstAvailableWorkspace();
|
||||
}
|
||||
await loadWorkspaces();
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize workspace:', error);
|
||||
await loadFirstAvailableWorkspace();
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
initializeWorkspace();
|
||||
}, []);
|
||||
|
||||
const switchWorkspace = useCallback(async (workspaceName) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
await updateLastWorkspaceName(workspaceName);
|
||||
await loadWorkspaceData(workspaceName);
|
||||
await loadWorkspaces();
|
||||
} catch (error) {
|
||||
console.error('Failed to switch workspace:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to switch workspace',
|
||||
color: 'red',
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const deleteCurrentWorkspace = useCallback(async () => {
|
||||
if (!currentWorkspace) return;
|
||||
|
||||
try {
|
||||
const allWorkspaces = await loadWorkspaces();
|
||||
if (allWorkspaces.length <= 1) {
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message:
|
||||
'Cannot delete the last workspace. At least one workspace must exist.',
|
||||
color: 'red',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete workspace and get the next workspace ID
|
||||
const response = await deleteWorkspace(currentWorkspace.name);
|
||||
|
||||
// Load the new workspace data
|
||||
await loadWorkspaceData(response.nextWorkspaceName);
|
||||
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Workspace deleted successfully',
|
||||
color: 'green',
|
||||
});
|
||||
|
||||
await loadWorkspaces();
|
||||
} catch (error) {
|
||||
console.error('Failed to delete workspace:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to delete workspace',
|
||||
color: 'red',
|
||||
});
|
||||
}
|
||||
}, [currentWorkspace]);
|
||||
|
||||
const updateSettings = useCallback(
|
||||
async (newSettings) => {
|
||||
if (!currentWorkspace) return;
|
||||
|
||||
try {
|
||||
const updatedWorkspace = {
|
||||
...currentWorkspace,
|
||||
...newSettings,
|
||||
};
|
||||
|
||||
const response = await updateWorkspace(
|
||||
currentWorkspace.name,
|
||||
updatedWorkspace
|
||||
);
|
||||
setCurrentWorkspace(response);
|
||||
setColorScheme(response.theme);
|
||||
await loadWorkspaces();
|
||||
} catch (error) {
|
||||
console.error('Failed to save settings:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, setColorScheme]
|
||||
);
|
||||
|
||||
const updateColorScheme = useCallback(
|
||||
(newTheme) => {
|
||||
setColorScheme(newTheme);
|
||||
},
|
||||
[setColorScheme]
|
||||
);
|
||||
|
||||
const value = {
|
||||
currentWorkspace,
|
||||
workspaces,
|
||||
settings: currentWorkspace || DEFAULT_WORKSPACE_SETTINGS,
|
||||
updateSettings,
|
||||
loading,
|
||||
colorScheme,
|
||||
updateColorScheme,
|
||||
switchWorkspace,
|
||||
deleteCurrentWorkspace,
|
||||
};
|
||||
|
||||
return (
|
||||
<WorkspaceContext.Provider value={value}>
|
||||
{children}
|
||||
</WorkspaceContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useWorkspace = () => {
|
||||
const context = useContext(WorkspaceContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useWorkspace must be used within a WorkspaceProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user