From fbaaf3ce0a3a4f19654e0436eb04934fa6c7a192 Mon Sep 17 00:00:00 2001 From: pikann22 Date: Fri, 16 Oct 2026 13:58:12 +0000 Subject: [PATCH 1/2] fix: use server-side member search and id lookup Co-Authored-By: Claude Sonnet 5.5 --- frontend/src/TimeTrackingPage.tsx | 51 ++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/frontend/src/TimeTrackingPage.tsx b/frontend/src/TimeTrackingPage.tsx index 9eda8b8..741e9a6 100644 --- a/frontend/src/TimeTrackingPage.tsx +++ b/frontend/src/TimeTrackingPage.tsx @@ -222,18 +222,21 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { // embedded by the backend (see TimeLogWithContext) — there's no single // project to resolve these against generically the way project scope does. - const { data: members = [] } = useQuery({ - queryKey: ["plugin", PLUGIN_ID, "core", "members", projectId ?? ""], - queryFn: () => api.listMembers(), + // The member filter's options are a server-side search over the team (first + // page of matches), not the whole team. + const [memberSearch, setMemberSearch] = useState(""); + const { data: memberOptionsPage } = useQuery({ + queryKey: ["plugin", PLUGIN_ID, "core", "members", projectId ?? "", memberSearch], + queryFn: () => api.listMembers({ search: memberSearch, pageSize: 50 }), enabled: isProject, + placeholderData: keepPreviousData, }); + const memberOptions = memberOptionsPage?.items ?? []; const { data: tasks = [] } = useQuery({ queryKey: ["plugin", PLUGIN_ID, "core", "tasks", projectId ?? ""], queryFn: () => api.listTasks(), enabled: isProject, }); - const memberName = (memberId: string) => - members.find((m) => m.id === memberId)?.full_name ?? memberId; const taskTitle = (taskId: string) => tasks.find((t) => t.id === taskId)?.title ?? taskId; @@ -274,6 +277,26 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { placeholderData: keepPreviousData, }); + // Names for the members that appear on this page of logs, looked up by id. + const logMemberIds = useMemo( + () => + isProject + ? [...new Set(((logPage?.logs ?? []) as TimeLog[]).map((l) => l.member_id))].sort() + : [], + [isProject, logPage], + ); + const { data: logMembersPage } = useQuery({ + queryKey: ["plugin", PLUGIN_ID, "core", "members-by-id", projectId ?? "", logMemberIds.join(",")], + queryFn: () => api.listMembers({ ids: logMemberIds, pageSize: 100 }), + enabled: isProject && logMemberIds.length > 0, + placeholderData: keepPreviousData, + }); + const memberNames = useMemo( + () => new Map((logMembersPage?.items ?? []).map((m) => [m.id, m.full_name || m.username])), + [logMembersPage], + ); + const memberName = (memberId: string) => memberNames.get(memberId) ?? memberId; + const rows: DisplayRow[] = useMemo(() => { const logs = logPage?.logs ?? []; if (isProject) { @@ -299,7 +322,7 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { minutesSpent: l.minutes_spent, note: l.note, })); - }, [logPage, isProject, members, tasks]); + }, [logPage, isProject, memberNames, tasks]); const total = logPage?.total ?? 0; const totalMinutes = logPage?.total_minutes ?? 0; @@ -448,6 +471,14 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { > Member + setMemberSearch(e.target.value)} + placeholder="Search members" + aria-label="Search members" + className="min-w-36 rounded-lg bg-muted/40 px-2.5 py-1.5 text-xs" + /> From 30cca9d428254ce6e50acca5be4f92538aab6ee1 Mon Sep 17 00:00:00 2001 From: pikann22 Date: Fri, 16 Oct 2026 14:10:48 +0000 Subject: [PATCH 2/2] chore: bump plugin-sdk-react to ^0.3.3 Co-Authored-By: Claude Sonnet 5.5 --- frontend/bun.lock | 4 ++-- frontend/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/bun.lock b/frontend/bun.lock index c4ba6fb..3819a1a 100644 --- a/frontend/bun.lock +++ b/frontend/bun.lock @@ -12,7 +12,7 @@ }, "devDependencies": { "@originjs/vite-plugin-federation": "^1.3.6", - "@paca-ai/plugin-sdk-react": "^0.3.0", + "@paca-ai/plugin-sdk-react": "^0.3.3", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", "@vitejs/plugin-react": "^4.3.0", @@ -124,7 +124,7 @@ "@originjs/vite-plugin-federation": ["@originjs/vite-plugin-federation@1.4.1", "", { "dependencies": { "estree-walker": "^3.0.2", "magic-string": "^0.27.0" } }, "sha512-Uo08jW5pj1t58OUKuZNkmzcfTN2pqeVuAWCCiKf/75/oll4Efq4cHOqSE1FXMlvwZNGDziNdDyBbQ5IANem3CQ=="], - "@paca-ai/plugin-sdk-react": ["@paca-ai/plugin-sdk-react@0.3.0", "", { "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-vSGwfDXWQ3NbPnwpvxa0JacO8XXsUYsji5gIHGTxMWkYA5KmW4Qnfzx6oKs2sLuVZRGdSXJ07cyCgNDXnXHjcA=="], + "@paca-ai/plugin-sdk-react": ["@paca-ai/plugin-sdk-react@0.3.3", "", { "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-YpXq7IbD9Ke11FZLmBMfldsRZ+alzckEMCb+moh8si9KvjX5rLJgiNIpQNWJ90TcpokpT/E4/eVCYy3ViV9zFA=="], "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], diff --git a/frontend/package.json b/frontend/package.json index 22cbdf2..fe29054 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,7 @@ }, "devDependencies": { "@originjs/vite-plugin-federation": "^1.3.6", - "@paca-ai/plugin-sdk-react": "^0.3.0", + "@paca-ai/plugin-sdk-react": "^0.3.3", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", "typescript": "^5.8.3",