Fix inbox badge logic and landing view
This commit is contained in:
101
ui/src/hooks/useInboxBadge.ts
Normal file
101
ui/src/hooks/useInboxBadge.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { accessApi } from "../api/access";
|
||||
import { ApiError } from "../api/client";
|
||||
import { approvalsApi } from "../api/approvals";
|
||||
import { dashboardApi } from "../api/dashboard";
|
||||
import { heartbeatsApi } from "../api/heartbeats";
|
||||
import { issuesApi } from "../api/issues";
|
||||
import { queryKeys } from "../lib/queryKeys";
|
||||
import {
|
||||
computeInboxBadgeData,
|
||||
loadDismissedInboxItems,
|
||||
saveDismissedInboxItems,
|
||||
} from "../lib/inbox";
|
||||
|
||||
const TOUCHED_ISSUE_STATUSES = "backlog,todo,in_progress,in_review,blocked,done";
|
||||
|
||||
export function useDismissedInboxItems() {
|
||||
const [dismissed, setDismissed] = useState<Set<string>>(loadDismissedInboxItems);
|
||||
|
||||
useEffect(() => {
|
||||
const handleStorage = (event: StorageEvent) => {
|
||||
if (event.key !== "paperclip:inbox:dismissed") return;
|
||||
setDismissed(loadDismissedInboxItems());
|
||||
};
|
||||
window.addEventListener("storage", handleStorage);
|
||||
return () => window.removeEventListener("storage", handleStorage);
|
||||
}, []);
|
||||
|
||||
const dismiss = (id: string) => {
|
||||
setDismissed((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(id);
|
||||
saveDismissedInboxItems(next);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
return { dismissed, dismiss };
|
||||
}
|
||||
|
||||
export function useInboxBadge(companyId: string | null | undefined) {
|
||||
const { dismissed } = useDismissedInboxItems();
|
||||
|
||||
const { data: approvals = [] } = useQuery({
|
||||
queryKey: queryKeys.approvals.list(companyId!),
|
||||
queryFn: () => approvalsApi.list(companyId!),
|
||||
enabled: !!companyId,
|
||||
});
|
||||
|
||||
const { data: joinRequests = [] } = useQuery({
|
||||
queryKey: queryKeys.access.joinRequests(companyId!),
|
||||
queryFn: async () => {
|
||||
try {
|
||||
return await accessApi.listJoinRequests(companyId!, "pending_approval");
|
||||
} catch (err) {
|
||||
if (err instanceof ApiError && (err.status === 401 || err.status === 403)) {
|
||||
return [];
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
enabled: !!companyId,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const { data: dashboard } = useQuery({
|
||||
queryKey: queryKeys.dashboard(companyId!),
|
||||
queryFn: () => dashboardApi.summary(companyId!),
|
||||
enabled: !!companyId,
|
||||
});
|
||||
|
||||
const { data: touchedIssues = [] } = useQuery({
|
||||
queryKey: queryKeys.issues.listTouchedByMe(companyId!),
|
||||
queryFn: () =>
|
||||
issuesApi.list(companyId!, {
|
||||
touchedByUserId: "me",
|
||||
status: TOUCHED_ISSUE_STATUSES,
|
||||
}),
|
||||
enabled: !!companyId,
|
||||
});
|
||||
|
||||
const { data: heartbeatRuns = [] } = useQuery({
|
||||
queryKey: queryKeys.heartbeats(companyId!),
|
||||
queryFn: () => heartbeatsApi.list(companyId!),
|
||||
enabled: !!companyId,
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
computeInboxBadgeData({
|
||||
approvals,
|
||||
joinRequests,
|
||||
dashboard,
|
||||
heartbeatRuns,
|
||||
touchedIssues,
|
||||
dismissed,
|
||||
}),
|
||||
[approvals, joinRequests, dashboard, heartbeatRuns, touchedIssues, dismissed],
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user