76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
import { useEffect, useMemo } from "react";
|
|
import { useSearchParams } from "@/lib/router";
|
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import { issuesApi } from "../api/issues";
|
|
import { agentsApi } from "../api/agents";
|
|
import { heartbeatsApi } from "../api/heartbeats";
|
|
import { useCompany } from "../context/CompanyContext";
|
|
import { useBreadcrumbs } from "../context/BreadcrumbContext";
|
|
import { queryKeys } from "../lib/queryKeys";
|
|
import { EmptyState } from "../components/EmptyState";
|
|
import { IssuesList } from "../components/IssuesList";
|
|
import { CircleDot } from "lucide-react";
|
|
|
|
export function Issues() {
|
|
const { selectedCompanyId } = useCompany();
|
|
const { setBreadcrumbs } = useBreadcrumbs();
|
|
const [searchParams] = useSearchParams();
|
|
const queryClient = useQueryClient();
|
|
|
|
const { data: agents } = useQuery({
|
|
queryKey: queryKeys.agents.list(selectedCompanyId!),
|
|
queryFn: () => agentsApi.list(selectedCompanyId!),
|
|
enabled: !!selectedCompanyId,
|
|
});
|
|
|
|
const { data: liveRuns } = useQuery({
|
|
queryKey: queryKeys.liveRuns(selectedCompanyId!),
|
|
queryFn: () => heartbeatsApi.liveRunsForCompany(selectedCompanyId!),
|
|
enabled: !!selectedCompanyId,
|
|
refetchInterval: 5000,
|
|
});
|
|
|
|
const liveIssueIds = useMemo(() => {
|
|
const ids = new Set<string>();
|
|
for (const run of liveRuns ?? []) {
|
|
if (run.issueId) ids.add(run.issueId);
|
|
}
|
|
return ids;
|
|
}, [liveRuns]);
|
|
|
|
useEffect(() => {
|
|
setBreadcrumbs([{ label: "Issues" }]);
|
|
}, [setBreadcrumbs]);
|
|
|
|
const { data: issues, isLoading, error } = useQuery({
|
|
queryKey: queryKeys.issues.list(selectedCompanyId!),
|
|
queryFn: () => issuesApi.list(selectedCompanyId!),
|
|
enabled: !!selectedCompanyId,
|
|
});
|
|
|
|
const updateIssue = useMutation({
|
|
mutationFn: ({ id, data }: { id: string; data: Record<string, unknown> }) =>
|
|
issuesApi.update(id, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.issues.list(selectedCompanyId!) });
|
|
},
|
|
});
|
|
|
|
if (!selectedCompanyId) {
|
|
return <EmptyState icon={CircleDot} message="Select a company to view issues." />;
|
|
}
|
|
|
|
return (
|
|
<IssuesList
|
|
issues={issues ?? []}
|
|
isLoading={isLoading}
|
|
error={error as Error | null}
|
|
agents={agents}
|
|
liveIssueIds={liveIssueIds}
|
|
viewStateKey="paperclip:issues-view"
|
|
initialAssignees={searchParams.get("assignee") ? [searchParams.get("assignee")!] : undefined}
|
|
onUpdateIssue={(id, data) => updateIssue.mutate({ id, data })}
|
|
/>
|
|
);
|
|
}
|