diff --git a/frontend/bun.lock b/frontend/bun.lock index 3819a1a..df86383 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.3", + "@paca-ai/plugin-sdk-react": "^0.3.4", "@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.3", "", { "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-YpXq7IbD9Ke11FZLmBMfldsRZ+alzckEMCb+moh8si9KvjX5rLJgiNIpQNWJ90TcpokpT/E4/eVCYy3ViV9zFA=="], + "@paca-ai/plugin-sdk-react": ["@paca-ai/plugin-sdk-react@0.3.4", "", { "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-KE9TBWwIdPV2u4CvJ26r7rhqAdVJcsd1G4GqiK3jjTbWpRw33247l7ksV01YdaVtpvLaXHx10x369SxiHHMXYw=="], "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], diff --git a/frontend/package.json b/frontend/package.json index fe29054..2f9f1c4 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.3", + "@paca-ai/plugin-sdk-react": "^0.3.4", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", "typescript": "^5.8.3", diff --git a/frontend/src/TimeTrackingPage.tsx b/frontend/src/TimeTrackingPage.tsx index 741e9a6..f6be1d7 100644 --- a/frontend/src/TimeTrackingPage.tsx +++ b/frontend/src/TimeTrackingPage.tsx @@ -1,5 +1,5 @@ import { PluginApiClient, PluginQueryClientProvider } from "@paca-ai/plugin-sdk-react"; -import { keepPreviousData, useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { keepPreviousData, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/react-query"; import { Check, ChevronLeft, @@ -232,13 +232,6 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { placeholderData: keepPreviousData, }); const memberOptions = memberOptionsPage?.items ?? []; - const { data: tasks = [] } = useQuery({ - queryKey: ["plugin", PLUGIN_ID, "core", "tasks", projectId ?? ""], - queryFn: () => api.listTasks(), - enabled: isProject, - }); - const taskTitle = (taskId: string) => - tasks.find((t) => t.id === taskId)?.title ?? taskId; // ── Main list query ──────────────────────────────────────────────────────── @@ -297,6 +290,29 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { ); const memberName = (memberId: string) => memberNames.get(memberId) ?? memberId; + // Titles for the tasks that appear on this page of logs, fetched by id (the + // task list is paged, so it cannot be read whole to resolve names). + const logTaskIds = useMemo( + () => + isProject + ? [...new Set(((logPage?.logs ?? []) as TimeLog[]).map((l) => l.task_id))].sort() + : [], + [isProject, logPage], + ); + const taskQueries = useQueries({ + queries: logTaskIds.map((taskId) => ({ + queryKey: ["plugin", PLUGIN_ID, "core", "task", projectId ?? "", taskId], + queryFn: () => api.getTask(taskId), + staleTime: 60_000, + })), + }); + const taskTitles = useMemo( + () => new Map(logTaskIds.map((id, i) => [id, taskQueries[i]?.data?.title] as const)), + // eslint-disable-next-line react-hooks/exhaustive-deps + [logTaskIds, taskQueries.map((q) => q.data?.title).join("\u0000")], + ); + const taskTitle = (taskId: string) => taskTitles.get(taskId) ?? taskId; + const rows: DisplayRow[] = useMemo(() => { const logs = logPage?.logs ?? []; if (isProject) { @@ -322,7 +338,7 @@ function TimeTrackingPageInner({ scope }: TimeTrackingPageProps) { minutesSpent: l.minutes_spent, note: l.note, })); - }, [logPage, isProject, memberNames, tasks]); + }, [logPage, isProject, memberNames, taskTitles]); const total = logPage?.total ?? 0; const totalMinutes = logPage?.total_minutes ?? 0; diff --git a/plugin.json b/plugin.json index da93372..8f25aa0 100644 --- a/plugin.json +++ b/plugin.json @@ -2,8 +2,8 @@ "id": "com.paca.time-logging", "displayName": "Time Logging", "description": "Lets project members manually log time spent on tasks (date, duration, note) and view per-member totals for a project.", - "version": "0.2.4", - "minCoreVersion": "v0.19.0", + "version": "0.2.5", + "minCoreVersion": "v0.19.1", "permissions": ["db.read", "db.write", "events.subscribe"], "customPermissions": [ {