"use client"; import { useRouter } from "next/navigation"; import { useRef } from "react"; import { truncateText } from "@/lib/truncate-text"; import { PaginationStatus } from "@/lib/types"; import { useInfiniteScroll } from "@/hooks/useInfiniteScroll"; import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Skeleton } from "@/components/ui/skeleton"; // Generic table row data interface export interface LogTableRow { id: string; input: string; output: string; model: string; createdTime: string; detailPath: string; } interface LogsTableProps { /** Array of log table row data to display */ data: LogTableRow[]; /** Current loading/error status */ status: PaginationStatus; /** Whether more data is available to load */ hasMore?: boolean; /** Error state, null if no error */ error: Error | null; /** Table caption for accessibility */ caption: string; /** Message to show when no data is available */ emptyMessage: string; /** Callback function to load more data */ onLoadMore?: () => void; } export function LogsTable({ data, status, hasMore = false, error, caption, emptyMessage, onLoadMore, }: LogsTableProps) { const router = useRouter(); const tableContainerRef = useRef(null); // Use Intersection Observer for infinite scroll const sentinelRef = useInfiniteScroll(onLoadMore, { enabled: hasMore && status === "idle", rootMargin: "100px", threshold: 0.1, }); // Fixed header component const FixedHeader = () => (
Input Output Model Created
); if (status === "loading") { return (
{[...Array(3)].map((_, i) => ( ))}
); } if (status === "error") { return (
Unable to load chat completions
{error?.message || "An unexpected error occurred while loading the data."}
); } if (data.length === 0) { return

{emptyMessage}

; } return (
{caption} {data.map((row) => ( router.push(row.detailPath)} className="cursor-pointer hover:bg-muted/50" > {truncateText(row.input)} {truncateText(row.output)} {row.model} {row.createdTime} ))} {/* Sentinel element for infinite scroll */} {hasMore && status === "idle" && ( )} {status === "loading-more" && (
Loading more...
)} {!hasMore && data.length > 0 && ( No more items to load )}
); }