"use client"; /** * useMentionSources — the R3 mention popup's data sources, scoped to one * workspace (all of them are the caller's already-visible content — no extra * scoping beyond the sidebar; the Security section rule). * * People — workspace members (the Phase-2 members endpoint, exists). * Teams — the workspace's teams (the Phase-2 teams endpoint, exists). * Pages — the page tree (the sidebar's `usePageTree`, reused — no new * endpoint; the search runs client-side over it, R3 decision). * Databases — the workspace's databases (`GET /workspaces/:wid/databases`, * the small list endpoint the R3 spec adds — already present). * * Each source is a TanStack query (cached — the sidebar already fetches * members + the tree, so those are usually warm). The popup's fuzzy search is * client-side over the fetched lists (`buildMentionGroups`), not per-keypress * network. */ import { useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; import { workspaceApi } from "@/lib/api"; import { useWorkspaceMembers } from "@/hooks/use-workspace"; import { usePageTree } from "@/hooks/use-pages"; import type { MentionSource } from "@/components/mentions/mention-model"; import type { PageTreeEntry } from "@/lib/types"; /** Flatten a (nested) page tree to the leaf entries the popup can mention. */ function flattenPages(entries: PageTreeEntry[] | undefined): { id: string; title: string }[] { const out: { id: string; title: string }[] = []; const walk = (list: PageTreeEntry[] | undefined) => { for (const e of list ?? []) { out.push({ id: e.id, title: e.title }); if (e.children) walk(e.children); } }; walk(entries); return out; } export function useMentionSources(workspaceId: string) { const enabled = workspaceId.length > 0; const { data: members, isLoading: loadingMembers } = useWorkspaceMembers(workspaceId); const { data: tree, isLoading: loadingTree } = usePageTree(workspaceId); const { data: teams, isLoading: loadingTeams } = useQuery({ queryKey: ["workspaces", workspaceId, "teams"], queryFn: () => workspaceApi.teams(workspaceId), enabled }); const { data: databases, isLoading: loadingDatabases } = useQuery({ queryKey: ["workspaces", workspaceId, "databases"], queryFn: () => workspaceApi.databases(workspaceId, { limit: 50 }), enabled }); const source = useMemo( () => ({ people: (members ?? []).map((m) => m.user), teams: (teams ?? []).map((t) => ({ id: t.id, name: t.name, memberCount: t.memberCount })), pages: flattenPages(tree), databases: (databases ?? []).map((d) => ({ id: d.id, title: d.title, icon: d.icon })) }), [members, teams, tree, databases] ); return { source, isLoading: loadingMembers || loadingTree || loadingTeams || loadingDatabases }; }