researcher page work

This commit is contained in:
sanwalsulehri 2025-09-21 09:52:32 +05:00
parent 50562be76f
commit df665a0424
3 changed files with 49 additions and 31 deletions

View file

@ -45,12 +45,19 @@ const DocumentSelector = React.memo(
// Calculate skip value for pagination // Calculate skip value for pagination
const skip = pageIndex * pageSize; const skip = pageIndex * pageSize;
const { documents, loading, isLoaded, fetchDocuments } = useDocuments( const { documents, loading, isLoaded, fetchDocuments, error } = useDocuments(
Number(search_space_id), Number(search_space_id),
true, true,
skip, skip,
pageSize pageSize
); );
// Refetch documents when pagination changes
useEffect(() => {
if (isOpen) {
fetchDocuments();
}
}, [skip, pageSize, isOpen, fetchDocuments]);
const handleOpenChange = useCallback( const handleOpenChange = useCallback(
(open: boolean) => { (open: boolean) => {
@ -105,6 +112,15 @@ const DocumentSelector = React.memo(
<p className="text-sm text-muted-foreground">Loading documents...</p> <p className="text-sm text-muted-foreground">Loading documents...</p>
</div> </div>
</div> </div>
) : error ? (
<div className="flex items-center justify-center h-full">
<div className="text-center space-y-2">
<p className="text-sm text-destructive">Error loading documents: {error}</p>
<Button onClick={fetchDocuments} variant="outline" size="sm">
Retry
</Button>
</div>
</div>
) : isLoaded ? ( ) : isLoaded ? (
<DocumentsDataTable <DocumentsDataTable
documents={documents} documents={documents}

View file

@ -66,14 +66,18 @@ const columns: ColumnDef<Document>[] = [
checked={ checked={
table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate") table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate")
} }
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} onCheckedChange={(value) => {
table.toggleAllPageRowsSelected(!!value);
}}
aria-label="Select all" aria-label="Select all"
/> />
), ),
cell: ({ row }) => ( cell: ({ row }) => (
<Checkbox <Checkbox
checked={row.getIsSelected()} checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)} onCheckedChange={(value) => {
row.toggleSelected(!!value);
}}
aria-label="Select row" aria-label="Select row"
/> />
), ),
@ -203,28 +207,22 @@ export function DocumentsDataTable({
const selection: Record<string, boolean> = {}; const selection: Record<string, boolean> = {};
initialSelectedDocuments.forEach((selectedDoc) => { initialSelectedDocuments.forEach((selectedDoc) => {
selection[selectedDoc.id] = true; // Find the document in the current documents array to get the correct row ID
const docInCurrentList = documents.find(doc => doc.id === selectedDoc.id);
if (docInCurrentList) {
selection[docInCurrentList.id.toString()] = true;
}
}); });
return selection; return selection;
}, [documents, initialSelectedDocuments]); }, [documents, initialSelectedDocuments]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>(() => initialRowSelection);
// Only update row selection when initialRowSelection actually changes and is not empty // Update row selection when initial selection changes
useEffect(() => { useEffect(() => {
const hasChanges = JSON.stringify(rowSelection) !== JSON.stringify(initialRowSelection); setRowSelection(initialRowSelection);
if (hasChanges && Object.keys(initialRowSelection).length > 0) {
setRowSelection(initialRowSelection);
}
}, [initialRowSelection]); }, [initialRowSelection]);
// Initialize row selection on mount
useEffect(() => {
if (Object.keys(rowSelection).length === 0 && Object.keys(initialRowSelection).length > 0) {
setRowSelection(initialRowSelection);
}
}, []);
const filteredDocuments = useMemo(() => { const filteredDocuments = useMemo(() => {
if (documentTypeFilter === "ALL") return documents; if (documentTypeFilter === "ALL") return documents;
return documents.filter((doc) => doc.document_type === documentTypeFilter); return documents.filter((doc) => doc.document_type === documentTypeFilter);
@ -237,12 +235,14 @@ export function DocumentsDataTable({
onSortingChange: setSorting, onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters, onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(), getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(), getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility, onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection, onRowSelectionChange: setRowSelection,
initialState: { pagination: { pageSize: 10 } }, // Disable internal pagination since we're handling it at the parent level
manualPagination: true,
pageCount: -1,
enableRowSelection: true,
state: { sorting, columnFilters, columnVisibility, rowSelection }, state: { sorting, columnFilters, columnVisibility, rowSelection },
}); });
@ -250,7 +250,7 @@ export function DocumentsDataTable({
const selectedRows = table.getFilteredSelectedRowModel().rows; const selectedRows = table.getFilteredSelectedRowModel().rows;
const selectedDocuments = selectedRows.map((row) => row.original); const selectedDocuments = selectedRows.map((row) => row.original);
onSelectionChange(selectedDocuments); onSelectionChange(selectedDocuments);
}, [rowSelection, onSelectionChange, table]); }, [rowSelection, table]);
const handleClearAll = () => setRowSelection({}); const handleClearAll = () => setRowSelection({});
@ -275,6 +275,7 @@ export function DocumentsDataTable({
const selectedCount = table.getFilteredSelectedRowModel().rows.length; const selectedCount = table.getFilteredSelectedRowModel().rows.length;
const totalFiltered = table.getFilteredRowModel().rows.length; const totalFiltered = table.getFilteredRowModel().rows.length;
return ( return (
<div className="flex flex-col h-full space-y-3 md:space-y-4"> <div className="flex flex-col h-full space-y-3 md:space-y-4">
{/* Header Controls */} {/* Header Controls */}

View file

@ -41,10 +41,10 @@ export function useDocuments(
const [isLoaded, setIsLoaded] = useState(false); // Memoization flag const [isLoaded, setIsLoaded] = useState(false); // Memoization flag
const fetchDocuments = useCallback(async () => { const fetchDocuments = useCallback(async () => {
if (isLoaded && lazy) return; // Avoid redundant calls in lazy mode
try { try {
setLoading(true); setLoading(true);
setError(null);
const response = await fetch( const response = await fetch(
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents?search_space_id=${searchSpaceId}&skip=${skip}&limit=${limit}`, `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents?search_space_id=${searchSpaceId}&skip=${skip}&limit=${limit}`,
{ {
@ -56,21 +56,22 @@ export function useDocuments(
); );
if (!response.ok) { if (!response.ok) {
const errorText = await response.text();
toast.error("Failed to fetch documents"); toast.error("Failed to fetch documents");
throw new Error("Failed to fetch documents"); throw new Error(`Failed to fetch documents: ${response.status} ${errorText}`);
} }
const data = await response.json(); const data = await response.json();
setDocuments(data); setDocuments(data || []);
setError(null);
setIsLoaded(true); setIsLoaded(true);
} catch (err: any) { } catch (err: any) {
setError(err.message || "Failed to fetch documents"); setError(err.message || "Failed to fetch documents");
console.error("Error fetching documents:", err); console.error("Error fetching documents:", err);
setDocuments([]);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, [searchSpaceId, skip, limit, isLoaded, lazy]); }, [searchSpaceId, skip, limit]);
useEffect(() => { useEffect(() => {
if (!lazy && searchSpaceId) { if (!lazy && searchSpaceId) {