Skip to content

Commit 0b83b5c

Browse files
committed
fix: online presence issue
1 parent 82647a6 commit 0b83b5c

2 files changed

Lines changed: 29 additions & 139 deletions

File tree

Client/src/pages/DashBoard.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
useInviteUser,
1111
} from "../store/workspace.store";
1212
import type { WorkspaceRole } from "../api/workspace.api";
13+
import type { WorkspaceWithRole } from "../store/workspace.store";
1314

1415
const ROLE_COLORS: Record<WorkspaceRole, string> = {
1516
Owner: "bg-gradient-to-r from-purple-500 to-pink-500",
@@ -38,26 +39,30 @@ const Dashboard: React.FC = () => {
3839

3940
const ITEMS_PER_PAGE = 6;
4041

42+
// ✅ Fetch workspace metadata once
4143
useEffect(() => {
42-
if (user?.id) {
43-
// fetch workspaces on mount and after user id changes
44+
if (user?.id && workspaces.length === 0) {
4445
fetchWorkspaces().catch((err) =>
4546
console.error("Failed to fetch workspaces:", err)
4647
);
4748
}
48-
}, [user?.id, fetchWorkspaces]);
49+
}, [user?.id, fetchWorkspaces, workspaces.length]);
4950

5051
const handleSendInvite = async (workspaceId: string, email: string) => {
5152
if (!email.trim()) return;
5253

5354
try {
54-
// send invite
5555
await inviteUser(workspaceId, email.trim());
5656

57-
// refetch workspaces to reflect new invite immediately
58-
await fetchWorkspaces();
57+
// ✅ Optional: update state locally
58+
const wsIndex = workspaces.findIndex((w) => w.id === workspaceId);
59+
if (wsIndex !== -1) {
60+
const updated: WorkspaceWithRole = {
61+
...workspaces[wsIndex],
62+
};
63+
workspaces[wsIndex] = updated;
64+
}
5965

60-
// reset modal
6166
setInviteOpen(null);
6267
setInviteEmail("");
6368
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -72,8 +77,9 @@ const Dashboard: React.FC = () => {
7277
const handleCreate = async (e: React.FormEvent) => {
7378
e.preventDefault();
7479
if (!newWorkspaceName.trim()) return;
75-
await createWorkspace({ name: newWorkspaceName.trim() });
76-
setNewWorkspaceName("");
80+
81+
const ws = await createWorkspace({ name: newWorkspaceName.trim() });
82+
if (ws) setNewWorkspaceName("");
7783
};
7884

7985
const filteredWorkspaces =

Client/src/store/workspace.store.ts

Lines changed: 14 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,32 @@ import {
33
type Workspace,
44
type WorkspaceMember,
55
type WorkspaceRole,
6-
type WorkspaceWithMembers,
76
type CreateWorkspaceDto,
87
workspaceApi,
98
} from "../api/workspace.api";
10-
11-
import { useAuthStore } from "./auth.store";
9+
// import { useAuthStore } from "./auth.store";
1210

1311
export interface WorkspaceWithRole extends Workspace {
1412
currentUserRole: WorkspaceRole;
1513
}
1614

1715
interface WorkspaceState {
18-
workspaces: WorkspaceWithRole[]; // list
16+
workspaces: WorkspaceWithRole[];
1917
currentWorkspace:
2018
| (WorkspaceWithRole & { members?: WorkspaceMember[] })
2119
| null;
2220
isLoading: boolean;
2321
error: string | null;
2422

2523
fetchWorkspaces: () => Promise<void>;
26-
fetchWorkspace: (id: string) => Promise<void>;
2724
createWorkspace: (
2825
dto: CreateWorkspaceDto
2926
) => Promise<WorkspaceWithRole | null>;
30-
updateWorkspaceName: (
31-
id: string,
32-
name: string
33-
) => Promise<WorkspaceWithRole | null>;
34-
deleteWorkspace: (id: string) => Promise<void>;
35-
leaveWorkspace: (id: string) => Promise<void>;
3627
inviteUser: (workspaceId: string, email: string) => Promise<void>;
37-
3828
reset: () => void;
3929
}
4030

41-
// Map list membership -> WorkspaceWithRole
31+
// map membership -> WorkspaceWithRole
4232
const membershipToWorkspaceWithRole = (
4333
membership: WorkspaceMember
4434
): WorkspaceWithRole => {
@@ -53,30 +43,6 @@ const membershipToWorkspaceWithRole = (
5343
};
5444
};
5545

56-
// Map single workspace (with members) -> WorkspaceWithRole (+members)
57-
const workspaceWithMembersToWorkspaceWithRole = (
58-
workspace: WorkspaceWithMembers,
59-
currentUserId?: string
60-
): WorkspaceWithRole & { members: WorkspaceMember[] } => {
61-
let role: WorkspaceRole = "Viewer";
62-
if (currentUserId && workspace.members) {
63-
const m = workspace.members.find((m) => m.userId === currentUserId);
64-
if (m) {
65-
role = m.role;
66-
}
67-
}
68-
69-
return {
70-
id: workspace.id,
71-
name: workspace.name,
72-
ownerId: workspace.ownerId,
73-
createdAt: workspace.createdAt,
74-
updatedAt: workspace.updatedAt,
75-
currentUserRole: role,
76-
members: workspace.members,
77-
};
78-
};
79-
8046
export const useWorkspaceStore = create<WorkspaceState>((set) => ({
8147
workspaces: [],
8248
currentWorkspace: null,
@@ -86,7 +52,7 @@ export const useWorkspaceStore = create<WorkspaceState>((set) => ({
8652
fetchWorkspaces: async () => {
8753
set({ isLoading: true, error: null });
8854
try {
89-
const memberships = await workspaceApi.getUserWorkspaces(); // WorkspaceMember[]
55+
const memberships = await workspaceApi.getUserWorkspaces();
9056
const data = memberships.map(membershipToWorkspaceWithRole);
9157
set({ workspaces: data, isLoading: false });
9258
} catch (err: unknown) {
@@ -96,29 +62,19 @@ export const useWorkspaceStore = create<WorkspaceState>((set) => ({
9662
}
9763
},
9864

99-
fetchWorkspace: async (id: string) => {
100-
set({ isLoading: true, error: null });
101-
try {
102-
const raw = await workspaceApi.getWorkspaceById(id); // WorkspaceWithMembers
103-
const currentUser = useAuthStore.getState().user;
104-
const ws = workspaceWithMembersToWorkspaceWithRole(raw, currentUser?.id);
105-
set({ currentWorkspace: ws, isLoading: false });
106-
} catch (err: unknown) {
107-
const message =
108-
err instanceof Error ? err.message : "Failed to load workspace";
109-
set({ error: message, isLoading: false, currentWorkspace: null });
110-
}
111-
},
112-
11365
createWorkspace: async (dto: CreateWorkspaceDto) => {
11466
set({ isLoading: true, error: null });
11567
try {
116-
const created = await workspaceApi.createWorkspace(dto); // WorkspaceWithMembers
117-
const currentUser = useAuthStore.getState().user;
118-
const ws = workspaceWithMembersToWorkspaceWithRole(
119-
created,
120-
currentUser?.id
121-
);
68+
const created = await workspaceApi.createWorkspace(dto);
69+
// const currentUser = useAuthStore.getState().user;
70+
const ws: WorkspaceWithRole = {
71+
id: created.id,
72+
name: created.name,
73+
ownerId: created.ownerId,
74+
createdAt: created.createdAt,
75+
updatedAt: created.updatedAt,
76+
currentUserRole: "Owner",
77+
};
12278

12379
set((state) => ({
12480
workspaces: [...state.workspaces, ws],
@@ -134,66 +90,6 @@ export const useWorkspaceStore = create<WorkspaceState>((set) => ({
13490
}
13591
},
13692

137-
updateWorkspaceName: async (id: string, name: string) => {
138-
set({ isLoading: true, error: null });
139-
try {
140-
const updated = await workspaceApi.updateWorkspaceName(id, name); // WorkspaceWithMembers
141-
const currentUser = useAuthStore.getState().user;
142-
const ws = workspaceWithMembersToWorkspaceWithRole(
143-
updated,
144-
currentUser?.id
145-
);
146-
147-
set((state) => ({
148-
workspaces: state.workspaces.map((w) => (w.id === id ? ws : w)),
149-
currentWorkspace:
150-
state.currentWorkspace?.id === id ? ws : state.currentWorkspace,
151-
isLoading: false,
152-
}));
153-
154-
return ws;
155-
} catch (err: unknown) {
156-
const message =
157-
err instanceof Error ? err.message : "Failed to update workspace";
158-
set({ error: message, isLoading: false });
159-
return null;
160-
}
161-
},
162-
163-
deleteWorkspace: async (id: string) => {
164-
set({ isLoading: true, error: null });
165-
try {
166-
await workspaceApi.deleteWorkspace(id);
167-
set((state) => ({
168-
workspaces: state.workspaces.filter((w) => w.id !== id),
169-
currentWorkspace:
170-
state.currentWorkspace?.id === id ? null : state.currentWorkspace,
171-
isLoading: false,
172-
}));
173-
} catch (err: unknown) {
174-
const message =
175-
err instanceof Error ? err.message : "Failed to delete workspace";
176-
set({ error: message, isLoading: false });
177-
}
178-
},
179-
180-
leaveWorkspace: async (id: string) => {
181-
set({ isLoading: true, error: null });
182-
try {
183-
await workspaceApi.leaveWorkspace(id);
184-
set((state) => ({
185-
workspaces: state.workspaces.filter((w) => w.id !== id),
186-
currentWorkspace:
187-
state.currentWorkspace?.id === id ? null : state.currentWorkspace,
188-
isLoading: false,
189-
}));
190-
} catch (err: unknown) {
191-
const message =
192-
err instanceof Error ? err.message : "Failed to leave workspace";
193-
set({ error: message, isLoading: false });
194-
}
195-
},
196-
19793
inviteUser: async (workspaceId: string, email: string) => {
19894
set({ isLoading: true, error: null });
19995
try {
@@ -216,22 +112,10 @@ export const useWorkspaceStore = create<WorkspaceState>((set) => ({
216112
}));
217113

218114
export const useWorkspaces = () => useWorkspaceStore((s) => s.workspaces);
219-
export const useWorkspaceCurrent = () =>
220-
useWorkspaceStore((s) => s.currentWorkspace);
221115
export const useWorkspaceLoading = () => useWorkspaceStore((s) => s.isLoading);
222-
export const useWorkspaceError = () => useWorkspaceStore((s) => s.error);
223-
224116
export const useFetchWorkspaces = () =>
225117
useWorkspaceStore((s) => s.fetchWorkspaces);
226-
export const useFetchWorkspace = () =>
227-
useWorkspaceStore((s) => s.fetchWorkspace);
228118
export const useCreateWorkspace = () =>
229119
useWorkspaceStore((s) => s.createWorkspace);
230-
export const useUpdateWorkspaceName = () =>
231-
useWorkspaceStore((s) => s.updateWorkspaceName);
232-
export const useDeleteWorkspace = () =>
233-
useWorkspaceStore((s) => s.deleteWorkspace);
234-
export const useLeaveWorkspace = () =>
235-
useWorkspaceStore((s) => s.leaveWorkspace);
236120
export const useInviteUser = () => useWorkspaceStore((s) => s.inviteUser);
237121
export const useResetWorkspaces = () => useWorkspaceStore((s) => s.reset);

0 commit comments

Comments
 (0)