File
Blob: src/client/stores/workspace-directory.ts
| 1 | import { create } from "zustand"; |
| 2 | import type { MemberWorkspaceRow } from "./db/bland-db"; |
| 3 | |
| 4 | export interface WorkspaceDirectoryState { |
| 5 | workspaces: MemberWorkspaceRow[]; |
| 6 | } |
| 7 | |
| 8 | const initialState: WorkspaceDirectoryState = { |
| 9 | workspaces: [], |
| 10 | }; |
| 11 | |
| 12 | export const useWorkspaceDirectoryStore = create<WorkspaceDirectoryState>(() => initialState); |
| 13 | |
| 14 | export function applyWorkspaceDirectoryProjection(workspaces: MemberWorkspaceRow[]): void { |
| 15 | useWorkspaceDirectoryStore.setState({ workspaces }, true); |
| 16 | } |
| 17 | |
| 18 | export function resetWorkspaceDirectoryProjection(): void { |
| 19 | useWorkspaceDirectoryStore.setState(initialState, true); |
| 20 | } |
| 21 | |
| 22 | export function selectMemberWorkspaces(state: WorkspaceDirectoryState): MemberWorkspaceRow[] { |
| 23 | return state.workspaces; |
| 24 | } |
| 25 | |
| 26 | export function selectMemberWorkspaceCount(state: WorkspaceDirectoryState): number { |
| 27 | return state.workspaces.length; |
| 28 | } |
| 29 | |
| 30 | export function selectWorkspaceBySlug(state: WorkspaceDirectoryState, slug: string): MemberWorkspaceRow | null { |
| 31 | return state.workspaces.find((w) => w.slug === slug) ?? null; |
| 32 | } |
| 33 | |
| 34 | export function selectWorkspaceById(state: WorkspaceDirectoryState, id: string): MemberWorkspaceRow | null { |
| 35 | return state.workspaces.find((w) => w.id === id) ?? null; |
| 36 | } |
| 37 | |
| 38 | /** |
| 39 | * Root-redirect / home-slug preference. Prefers the last-visited workspace |
| 40 | * when the caller still has membership; falls back to the first listed |
| 41 | * workspace. Returns null when the caller has no member workspaces. |
| 42 | */ |
| 43 | export function selectFirstMemberSlug( |
| 44 | state: WorkspaceDirectoryState, |
| 45 | lastVisitedWorkspaceId: string | null, |
| 46 | ): string | null { |
| 47 | if (lastVisitedWorkspaceId) { |
| 48 | const match = state.workspaces.find((w) => w.id === lastVisitedWorkspaceId); |
| 49 | if (match) return match.slug; |
| 50 | } |
| 51 | return state.workspaces[0]?.slug ?? null; |
| 52 | } |
| 53 | |
| 54 | export function useMemberWorkspaces(): MemberWorkspaceRow[] { |
| 55 | return useWorkspaceDirectoryStore(selectMemberWorkspaces); |
| 56 | } |
| 57 | |
| 58 | export function useMemberWorkspaceCount(): number { |
| 59 | return useWorkspaceDirectoryStore(selectMemberWorkspaceCount); |
| 60 | } |
| 61 | |
| 62 | export function useWorkspaceBySlug(slug: string | null | undefined): MemberWorkspaceRow | null { |
| 63 | return useWorkspaceDirectoryStore((s) => (slug ? selectWorkspaceBySlug(s, slug) : null)); |
| 64 | } |