What is my Problem?
I searched for "as"
The status filter shows "1" (meaning 1 filter is active)
The pagination shows "1 - 3 of 3" (meaning it found 3 matching items)
BUT the table is showing 7 rows of data, not 3!
The checkboxes are not working (none are checked even though you said you selected all)
import { useMemo, useState, useEffect } from "react";
import { Head, Link } from "@inertiajs/react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardFooter, CardHeader, CardHeading, CardTable, CardToolbar } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { DataGrid } from "@/components/ui/data-grid";
import { DataGridColumnHeader } from "@/components/ui/data-grid-column-header";
import { DataGridPagination } from "@/components/ui/data-grid-pagination";
import {
DataGridTable,
DataGridTableRowSelect,
DataGridTableRowSelectAll,
} from "@/components/ui/data-grid-table";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import {
ColumnDef,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
PaginationState,
RowSelectionState,
SortingState,
VisibilityState,
useReactTable,
} from "@tanstack/react-table";
import { Filter, Search, Plus, X } from "lucide-react";
import * as AppRoutes from "@/routes/apps";
import { App, AppIndexProps } from "@/types/apps/app";
import { AppLayout } from "@/layouts/app/app-layout";
import { generalSettings } from "@/config/general.config";
import ActionsCell from "./partials/action-cell";
export default function AppIndex({ apps }: AppIndexProps) {
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: generalSettings.pagination_count,
});
const [sorting, setSorting] = useState<SortingState>([{ id: "app_name", desc: false }]);
const [searchQuery, setSearchQuery] = useState("");
const [statusFilter, setStatusFilter] = useState<string[]>([]);
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
// Filtering Logic
const filteredData = useMemo(() => {
return apps.data.filter((item) => {
// Filter by status
const matchesStatus = statusFilter.length === 0 ||
(statusFilter.includes("Active") && item.is_active) ||
(statusFilter.includes("Inactive") && !item.is_active);
// Filter by search query
const searchLower = searchQuery.toLowerCase();
const matchesSearch = !searchQuery ||
item.app_name.toLowerCase().includes(searchLower) ||
item.app_id.toLowerCase().includes(searchLower) ||
(item.slug && item.slug.toLowerCase().includes(searchLower));
return matchesStatus && matchesSearch;
});
}, [apps.data, searchQuery, statusFilter]);
// Reset pagination when filters change
useEffect(() => {
setPagination(prev => ({ ...prev, pageIndex: 0 }));
}, [searchQuery, statusFilter]);
// Reset row selection when filters change
useEffect(() => {
setRowSelection({});
}, [searchQuery, statusFilter]);
// Status counts for filter badges
const statusCounts = useMemo(() => {
return apps.data.reduce((acc, item) => {
const status = item.is_active ? "Active" : "Inactive";
acc[status] = (acc[status] || 0) + 1;
return acc;
}, {} as Record<string, number>);
}, [apps.data]);
const columns = useMemo<ColumnDef<App>[]>(
() => [
{
id: "select",
header: () => <DataGridTableRowSelectAll />,
cell: ({ row }) => <DataGridTableRowSelect row={row} />,
enableSorting: false,
enableHiding: false,
enableResizing: false,
size: 40,
meta: {
headerClassName: "",
cellClassName: "",
},
},
{
accessorKey: "app_name",
id: "app_name",
header: ({ column }) => <DataGridColumnHeader title="Application" visibility={true} column={column} />,
cell: ({ row }) => (
<div className="flex items-center gap-3">
<Avatar className="size-9 rounded-lg">
<AvatarImage src={row.original.app_icon || ""} alt={row.original.app_name} />
<AvatarFallback className="rounded-lg bg-primary/10 text-primary font-bold">
{row.original.app_name.charAt(0)}
</AvatarFallback>
</Avatar>
<div className="flex flex-col">
<span className="font-semibold text-foreground leading-none mb-1">
{row.original.app_name}
</span>
<span className="text-xs text-muted-foreground">
{row.original.slug}
</span>
</div>
</div>
),
enableSorting: true,
enableHiding: false,
enableResizing: true,
size: 250,
},
{
accessorKey: "app_id",
id: "app_id",
header: ({ column }) => <DataGridColumnHeader title="Package ID" visibility={true} column={column} />,
cell: ({ row }) => (
<code className="text-xs bg-muted px-1.5 py-0.5 rounded text-muted-foreground">
{row.original.app_id}
),
enableSorting: true,
enableHiding: true,
enableResizing: true,
size: 200,
},
{
accessorKey: "app_version",
id: "app_version",
header: ({ column }) => <DataGridColumnHeader title="Version" visibility={true} column={column} />,
cell: ({ row }) => (
<Badge variant="secondary" appearance="outline">
{row.original.app_version}
</Badge>
),
enableSorting: true,
enableHiding: true,
enableResizing: true,
size: 100,
},
{
accessorKey: "is_active",
id: "is_active",
header: ({ column }) => <DataGridColumnHeader title="Status" visibility={true} column={column} />,
cell: ({ row }) => (
<Badge variant={row.original.is_active ? "primary" : "secondary"} appearance="outline">
{row.original.is_active ? "Active" : "Inactive"}
</Badge>
),
enableSorting: true,
enableHiding: true,
enableResizing: true,
size: 100,
},
{
id: "actions",
header: "",
cell: ({ row }) => <ActionsCell row={row} />,
enableSorting: false,
enableHiding: false,
enableResizing: false,
size: 60,
},
],
[]
);
const [columnOrder, setColumnOrder] = useState<string[]>(
columns.map((column) => column.id as string)
);
const table = useReactTable({
columns,
data: filteredData,
pageCount: Math.ceil(filteredData.length / pagination.pageSize),
getRowId: (row: App) => row.id.toString(),
state: {
pagination,
sorting,
rowSelection,
columnVisibility,
columnOrder,
},
enableRowSelection: true,
columnResizeMode: "onChange",
onRowSelectionChange: setRowSelection,
onColumnVisibilityChange: setColumnVisibility,
onColumnOrderChange: setColumnOrder,
onPaginationChange: setPagination,
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
});
console.log("Apps.data length:", apps.data.length);
console.log("Table state data:", table.options.data.length);
return (
<AppLayout>
<div className="container mx-auto py-8">
<Head title="Manage Apps" />
<DataGrid
table={table}
recordCount={filteredData.length}
tableLayout={{
columnsPinnable: true,
columnsResizable: true,
columnsMovable: true,
columnsVisibility: true,
}}
>
<Card>
<CardHeader className="py-5">
<CardHeading>
<div className="flex items-center gap-3">
<div className="relative">
<Search className="size-4 text-muted-foreground absolute start-3 top-1/2 -translate-y-1/2" />
<Input
placeholder="Search apps..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="ps-9 w-64"
/>
{searchQuery.length > 0 && (
<Button
mode="icon"
variant="ghost"
className="absolute end-1.5 top-1/2 -translate-y-1/2 h-6 w-6"
onClick={() => setSearchQuery("")}
>
<X className="size-3" />
</Button>
)}
</div>
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">
<Filter className="size-4" />
Status
{statusFilter.length > 0 && (
<Badge size="sm" appearance="outline">
{statusFilter.length}
</Badge>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-44 p-3" align="start">
<div className="space-y-3">
<div className="text-xs font-medium text-muted-foreground">Filters</div>
<div className="space-y-3">
{Object.keys(statusCounts).map((status) => (
<div key={status} className="flex items-center gap-2.5">
<Checkbox
id={status}
checked={statusFilter.includes(status)}
onCheckedChange={(checked) => {
setStatusFilter(prev =>
checked === true
? [...prev, status]
: prev.filter(s => s !== status)
);
}}
/>
<Label
htmlFor={status}
className="grow flex items-center justify-between font-normal gap-1.5 cursor-pointer"
>
{status}
<span className="text-muted-foreground">
{statusCounts[status]}
</span>
</Label>
</div>
))}
</div>
</div>
</PopoverContent>
</Popover>
</div>
</CardHeading>
<CardToolbar>
<Link href={AppRoutes.create()}>
<Button>
<Plus className="size-4" />
Add New App
</Button>
</Link>
</CardToolbar>
</CardHeader>
<CardTable>
<ScrollArea>
<DataGridTable />
<ScrollBar orientation="horizontal" />
</ScrollArea>
</CardTable>
<CardFooter>
<DataGridPagination />
</CardFooter>
</Card>
</DataGrid>
</div>
</AppLayout>
);
} Hi,
Unfortunately we can not debug your code and reproduce your issue.
If the datatable is working in the original template then when you copied into your project and customized it the issue caused.
Please try to recover the original data-grid code and do your customizations step by step in order to implement it for your project.
Regards,
Sean