RealBlocks / client /src /store /projectStore.ts
incognitolm
1
6919b2c
Raw
History Blame Contribute Delete
3.54 kB
import { create } from 'zustand';
import { getSocket } from '../hooks/useWebSocket';
import { Project, FrameworkType } from '../types';
interface ProjectStore {
projects: Project[];
currentProject: Project | null;
loading: boolean;
error: string | null;
fetchProjects: () => Promise<void>;
loadProject: (id: string) => Promise<void>;
createProject: (name: string, framework: FrameworkType, description?: string) => Promise<Project>;
updateProject: (id: string, updates: any) => Promise<void>;
deleteProject: (id: string) => Promise<void>;
setCurrentProject: (project: Project | null) => void;
syncProject: (id: string) => Promise<void>;
}
function wsEmit<T>(event: string, data?: any): Promise<T> {
return new Promise((resolve, reject) => {
// Wait for socket to be connected (with timeout)
const attempt = (tries: number) => {
const socket = getSocket();
if (socket?.connected) {
socket.emit(event, data ?? {}, (response: any) => {
if (response?.error) reject(new Error(response.error));
else resolve(response as T);
});
} else if (tries < 50) {
setTimeout(() => attempt(tries + 1), 100);
} else {
reject(new Error('Not connected to server'));
}
};
attempt(0);
});
}
export const useProjectStore = create<ProjectStore>((set, get) => ({
projects: [],
currentProject: null,
loading: false,
error: null,
fetchProjects: async () => {
set({ loading: true, error: null });
try {
const { projects } = await wsEmit<{ projects: Project[] }>('project_list');
set({ projects, loading: false });
} catch (err: any) {
set({ error: err.message, loading: false });
}
},
loadProject: async (id: string) => {
set({ loading: true, error: null });
try {
const { project } = await wsEmit<{ project: Project }>('project_load', { projectId: id });
set({ currentProject: project, loading: false });
} catch (err: any) {
set({ error: err.message, loading: false });
}
},
createProject: async (name: string, framework: FrameworkType, description?: string) => {
set({ loading: true, error: null });
try {
const { project } = await wsEmit<{ project: Project }>('project_create', {
name, framework, description,
});
set((state) => ({ projects: [project, ...state.projects], loading: false }));
return project;
} catch (err: any) {
set({ error: err.message, loading: false });
throw err;
}
},
updateProject: async (id: string, updates: any) => {
try {
await wsEmit('project_update', { projectId: id, updates });
set((state) => ({
currentProject: state.currentProject?.id === id
? { ...state.currentProject, ...updates }
: state.currentProject,
}));
} catch (err: any) {
set({ error: err.message });
}
},
deleteProject: async (id: string) => {
try {
await wsEmit('project_delete', { projectId: id });
set((state) => ({
projects: state.projects.filter((p) => p.id !== id),
currentProject: state.currentProject?.id === id ? null : state.currentProject,
}));
} catch (err: any) {
set({ error: err.message });
}
},
setCurrentProject: (project) => set({ currentProject: project }),
syncProject: async (id: string) => {
try {
await wsEmit('project_sync', { projectId: id });
} catch (err: any) {
set({ error: err.message });
}
},
}));