mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-14 21:59:30 +02:00
- Resolve issues/store.ts: keep client-only store, port pagination strategy (open_only + closed page) to core/issues/queries.ts - Resolve issues-page.tsx, batch-action-toolbar.tsx: keep TQ mutations - Auto-merge agents/page.tsx trigger null fix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import { queryOptions } from "@tanstack/react-query";
|
|
import { api } from "@/shared/api";
|
|
|
|
export const issueKeys = {
|
|
all: (wsId: string) => ["issues", wsId] as const,
|
|
list: (wsId: string) => [...issueKeys.all(wsId), "list"] as const,
|
|
detail: (wsId: string, id: string) =>
|
|
[...issueKeys.all(wsId), "detail", id] as const,
|
|
timeline: (issueId: string) => ["issues", "timeline", issueId] as const,
|
|
reactions: (issueId: string) => ["issues", "reactions", issueId] as const,
|
|
subscribers: (issueId: string) =>
|
|
["issues", "subscribers", issueId] as const,
|
|
};
|
|
|
|
const CLOSED_PAGE_SIZE = 50;
|
|
|
|
/**
|
|
* CACHE SHAPE NOTE: The raw cache stores ListIssuesResponse ({ issues, total }),
|
|
* but `select` transforms it to Issue[] for consumers. Mutations and ws-updaters
|
|
* must use setQueryData<ListIssuesResponse>(...) — NOT setQueryData<Issue[]>.
|
|
*
|
|
* Fetches all open issues + first page of closed issues (matching main's pagination strategy).
|
|
*/
|
|
export function issueListOptions(wsId: string) {
|
|
return queryOptions({
|
|
queryKey: issueKeys.list(wsId),
|
|
queryFn: async () => {
|
|
const [openRes, closedRes] = await Promise.all([
|
|
api.listIssues({ open_only: true }),
|
|
api.listIssues({ status: "done", limit: CLOSED_PAGE_SIZE, offset: 0 }),
|
|
]);
|
|
return {
|
|
issues: [...openRes.issues, ...closedRes.issues],
|
|
total: openRes.total + closedRes.total,
|
|
};
|
|
},
|
|
select: (data) => data.issues,
|
|
});
|
|
}
|
|
|
|
export function issueDetailOptions(wsId: string, id: string) {
|
|
return queryOptions({
|
|
queryKey: issueKeys.detail(wsId, id),
|
|
queryFn: () => api.getIssue(id),
|
|
});
|
|
}
|
|
|
|
export function issueTimelineOptions(issueId: string) {
|
|
return queryOptions({
|
|
queryKey: issueKeys.timeline(issueId),
|
|
queryFn: () => api.listTimeline(issueId),
|
|
});
|
|
}
|
|
|
|
export function issueReactionsOptions(issueId: string) {
|
|
return queryOptions({
|
|
queryKey: issueKeys.reactions(issueId),
|
|
queryFn: async () => {
|
|
const issue = await api.getIssue(issueId);
|
|
return issue.reactions ?? [];
|
|
},
|
|
});
|
|
}
|
|
|
|
export function issueSubscribersOptions(issueId: string) {
|
|
return queryOptions({
|
|
queryKey: issueKeys.subscribers(issueId),
|
|
queryFn: () => api.listIssueSubscribers(issueId),
|
|
});
|
|
}
|