Skip to content
File

Blob: src/client/components/workspace/use-workspace-view.ts

typescript58 lines
1import { createContext, use } from "react";
2import { hasWorkspaceIdentity, type WorkspaceRouteState } from "@/client/lib/workspace-route-model";
3import {
4 useWorkspaceHead,
5 useWorkspacePages as useReplicaPages,
6 useWorkspaceMembers as useReplicaMembers,
7 useWorkspaceRole as useReplicaRole,
8} from "@/client/stores/workspace-replica";
9import type { Page, Workspace, WorkspaceMember, WorkspaceRole } from "@/shared/types";
10 
11export interface WorkspaceViewContext {
12 route: WorkspaceRouteState;
13 canonicalSlug: string | undefined;
14}
15 
16export const WorkspaceViewCtx = createContext<WorkspaceViewContext | null>(null);
17 
18export function useWorkspaceView(): WorkspaceViewContext {
19 const ctx = use(WorkspaceViewCtx);
20 if (!ctx) throw new Error("useWorkspaceView must be used inside WorkspaceViewProvider");
21 return ctx;
22}
23 
24export function useMaybeWorkspaceView(): WorkspaceViewContext | null {
25 return use(WorkspaceViewCtx);
26}
27 
28export function useWorkspaceRouteState(): WorkspaceRouteState {
29 return useWorkspaceView().route;
30}
31 
32export function useWorkspacePages(): Page[] {
33 const { route } = useWorkspaceView();
34 const workspaceId = hasWorkspaceIdentity(route) ? route.workspaceId : null;
35 return useReplicaPages(workspaceId);
36}
37 
38export function useWorkspaceMembers(): WorkspaceMember[] {
39 const { route } = useWorkspaceView();
40 const workspaceId = hasWorkspaceIdentity(route) ? route.workspaceId : null;
41 return useReplicaMembers(workspaceId);
42}
43 
44/** Caller's role in the current workspace (read from the replica — null when
45 * no membership exists or the current view is shared-surface). */
46export function useWorkspaceRole(): WorkspaceRole | null {
47 const { route } = useWorkspaceView();
48 const workspaceId = hasWorkspaceIdentity(route) ? route.workspaceId : null;
49 return useReplicaRole(workspaceId);
50}
51 
52/** Live workspace identity, read from the authoritative replica store. */
53export function useCurrentWorkspace(): Workspace | null {
54 const { route } = useWorkspaceView();
55 const workspaceId = hasWorkspaceIdentity(route) ? route.workspaceId : null;
56 return useWorkspaceHead(workspaceId);
57}