fix: Activity Log — replace useInfiniteQuery with simple useQuery + cursor
The useInfiniteQuery with tRPC as-any cast wasn't passing cursors correctly, causing no data to load on initial page visit. Replaced with simple useQuery + manual cursor state: - First 50 entries load immediately on mount - "Load more" button appends next page via cursor - Filter changes reset cursor and entries - keepPreviousData prevents flash during pagination Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useMemo, useCallback } from "react";
|
||||
import { useState, useMemo, useCallback, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import type { Route } from "next";
|
||||
import { trpc } from "~/lib/trpc/client.js";
|
||||
@@ -209,45 +209,39 @@ export function ActivityLogClient() {
|
||||
return input;
|
||||
}, [entityType, action, userId, search, startDate, endDate]);
|
||||
|
||||
type AuditListPage = { items: Array<{
|
||||
id: string;
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
action: string;
|
||||
changes: unknown;
|
||||
createdAt: Date;
|
||||
source: string | null;
|
||||
entityName: string | null;
|
||||
summary: string | null;
|
||||
user: { id: string; name: string | null; email: string } | null;
|
||||
}>; nextCursor?: string };
|
||||
const [cursor, setCursor] = useState<string | undefined>(undefined);
|
||||
const [allEntries, setAllEntries] = useState<any[]>([]);
|
||||
const [hasNextPage, setHasNextPage] = useState(false);
|
||||
|
||||
const {
|
||||
data,
|
||||
isLoading,
|
||||
fetchNextPage,
|
||||
hasNextPage,
|
||||
isFetchingNextPage,
|
||||
// Keep as any to avoid tRPC TS depth limits with useInfiniteQuery
|
||||
} = (trpc.auditLog.list.useInfiniteQuery as any)(
|
||||
queryInput,
|
||||
{
|
||||
getNextPageParam: (lastPage: AuditListPage) => lastPage.nextCursor ?? undefined,
|
||||
initialCursor: undefined,
|
||||
staleTime: 30_000,
|
||||
},
|
||||
) as {
|
||||
data: { pages: AuditListPage[] } | undefined;
|
||||
isLoading: boolean;
|
||||
fetchNextPage: () => void;
|
||||
hasNextPage: boolean;
|
||||
isFetchingNextPage: boolean;
|
||||
};
|
||||
const { data, isLoading, isFetching } = (trpc.auditLog.list as any).useQuery(
|
||||
{ ...queryInput, ...(cursor ? { cursor } : {}) },
|
||||
{ staleTime: 30_000, keepPreviousData: true },
|
||||
) as { data: { items: any[]; nextCursor?: string } | undefined; isLoading: boolean; isFetching: boolean };
|
||||
|
||||
const allEntries = useMemo(() => {
|
||||
if (!data) return [];
|
||||
return data.pages.flatMap((page) => page.items);
|
||||
}, [data]);
|
||||
// Append new page results
|
||||
useEffect(() => {
|
||||
if (!data) return;
|
||||
if (!cursor) {
|
||||
// First page or filter change — replace
|
||||
setAllEntries(data.items);
|
||||
} else {
|
||||
// Subsequent page — append
|
||||
setAllEntries((prev) => [...prev, ...data.items]);
|
||||
}
|
||||
setHasNextPage(!!data.nextCursor);
|
||||
}, [data, cursor]);
|
||||
|
||||
// Reset cursor when filters change
|
||||
useEffect(() => {
|
||||
setCursor(undefined);
|
||||
setAllEntries([]);
|
||||
}, [entityType, action, userId, search, startDate, endDate]);
|
||||
|
||||
function loadMore() {
|
||||
if (data?.nextCursor) {
|
||||
setCursor(data.nextCursor);
|
||||
}
|
||||
}
|
||||
|
||||
const toggleExpand = useCallback((id: string) => {
|
||||
setExpandedId((prev) => (prev === id ? null : id));
|
||||
@@ -462,11 +456,11 @@ export function ActivityLogClient() {
|
||||
{hasNextPage && (
|
||||
<div className="flex justify-center pt-4">
|
||||
<button
|
||||
onClick={() => fetchNextPage()}
|
||||
disabled={isFetchingNextPage}
|
||||
onClick={loadMore}
|
||||
disabled={isFetching}
|
||||
className="rounded-lg border border-gray-300 bg-white px-6 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 dark:border-slate-600 dark:bg-slate-800 dark:text-gray-300 dark:hover:bg-slate-700"
|
||||
>
|
||||
{isFetchingNextPage ? "Loading..." : "Load more"}
|
||||
{isFetching ? "Loading..." : "Load more"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user