Forráskód Böngészése

Updated Imports page to show a table instead.

vtugulan 3 napja
szülő
commit
84f09e1f49
2 módosított fájl, 229 hozzáadás és 54 törlés
  1. 218 0
      app/components/imports/ImportsTable.tsx
  2. 11 54
      app/imports/page.tsx

+ 218 - 0
app/components/imports/ImportsTable.tsx

@@ -0,0 +1,218 @@
+"use client";
+
+import React, { useState } from "react";
+import {
+    ColumnDef,
+    flexRender,
+    getCoreRowModel,
+    getPaginationRowModel,
+    getSortedRowModel,
+    useReactTable,
+    SortingState,
+} from "@tanstack/react-table";
+import { Button } from "@/components/ui/button";
+import {
+    Table,
+    TableBody,
+    TableCell,
+    TableHead,
+    TableHeader,
+    TableRow,
+} from "@/components/ui/table";
+import { Badge } from "@/components/ui/badge";
+import { format } from "date-fns";
+import { FileText, Edit, Trash2, Calendar, ChevronLeft, ChevronRight } from "lucide-react";
+
+interface Import {
+    id: number;
+    name: string;
+    importDate: string;
+    layoutId: number;
+    layout: {
+        id: number;
+        name: string;
+    };
+}
+
+interface ImportsTableProps {
+    data: Import[];
+    onView: (importRecord: Import) => void;
+    onEdit: (importRecord: Import) => void;
+    onDelete: (id: number) => void;
+}
+
+export function ImportsTable({ data, onView, onEdit, onDelete }: ImportsTableProps) {
+    const [sorting, setSorting] = useState<SortingState>([
+        { id: "importDate", desc: true },
+    ]);
+
+    const columns: ColumnDef<Import>[] = [
+        {
+            accessorKey: "name",
+            header: "Name",
+            cell: ({ row }) => (
+                <div className="font-medium">{row.getValue("name")}</div>
+            ),
+        },
+        {
+            accessorKey: "layout.name",
+            header: "Layout",
+            cell: ({ row }) => (
+                <Badge variant="outline" className="dark:border-gray-600 dark:text-gray-300">
+                    {row.original.layout.name}
+                </Badge>
+            ),
+        },
+        {
+            accessorKey: "importDate",
+            header: "Import Date",
+            cell: ({ row }) => {
+                const date = new Date(row.getValue("importDate"));
+                return (
+                    <div className="flex items-center text-sm text-muted-foreground">
+                        <Calendar className="mr-2 h-3 w-3" />
+                        {format(date, "MMM d, yyyy HH:mm")}
+                    </div>
+                );
+            },
+        },
+        {
+            id: "actions",
+            header: "Actions",
+            cell: ({ row }) => (
+                <div className="flex gap-2">
+                    <Button
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => onView(row.original)}
+                        title="View details"
+                    >
+                        <FileText className="h-4 w-4" />
+                    </Button>
+                    <Button
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => onEdit(row.original)}
+                        title="Edit import"
+                    >
+                        <Edit className="h-4 w-4" />
+                    </Button>
+                    <Button
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => onDelete(row.original.id)}
+                        title="Delete import"
+                        className="text-destructive hover:text-destructive"
+                    >
+                        <Trash2 className="h-4 w-4" />
+                    </Button>
+                </div>
+            ),
+            enableSorting: false,
+        },
+    ];
+
+    const table = useReactTable({
+        data,
+        columns,
+        state: {
+            sorting,
+        },
+        onSortingChange: setSorting,
+        getCoreRowModel: getCoreRowModel(),
+        getPaginationRowModel: getPaginationRowModel(),
+        getSortedRowModel: getSortedRowModel(),
+        initialState: {
+            pagination: {
+                pageSize: 10,
+            },
+        },
+    });
+
+    return (
+        <div className="space-y-4">
+            <div className="rounded-md border bg-white dark:bg-gray-800 dark:border-gray-700">
+                <Table>
+                    <TableHeader>
+                        {table.getHeaderGroups().map((headerGroup) => (
+                            <TableRow key={headerGroup.id} className="dark:border-gray-700">
+                                {headerGroup.headers.map((header) => (
+                                    <TableHead
+                                        key={header.id}
+                                        onClick={header.column.getToggleSortingHandler()}
+                                        className={header.column.getCanSort() ? "cursor-pointer select-none" : ""}
+                                    >
+                                        <div className="flex items-center gap-1">
+                                            {flexRender(
+                                                header.column.columnDef.header,
+                                                header.getContext()
+                                            )}
+                                            {header.column.getIsSorted() && (
+                                                <span>
+                                                    {header.column.getIsSorted() === "asc" ? "↑" : "↓"}
+                                                </span>
+                                            )}
+                                        </div>
+                                    </TableHead>
+                                ))}
+                            </TableRow>
+                        ))}
+                    </TableHeader>
+                    <TableBody>
+                        {table.getRowModel().rows?.length ? (
+                            table.getRowModel().rows.map((row) => (
+                                <TableRow
+                                    key={row.id}
+                                    data-state={row.getIsSelected() && "selected"}
+                                    className="dark:border-gray-700"
+                                >
+                                    {row.getVisibleCells().map((cell) => (
+                                        <TableCell key={cell.id}>
+                                            {flexRender(cell.column.columnDef.cell, cell.getContext())}
+                                        </TableCell>
+                                    ))}
+                                </TableRow>
+                            ))
+                        ) : (
+                            <TableRow>
+                                <TableCell colSpan={columns.length} className="h-24 text-center">
+                                    No results.
+                                </TableCell>
+                            </TableRow>
+                        )}
+                    </TableBody>
+                </Table>
+            </div>
+
+            <div className="flex items-center justify-between">
+                <div className="text-sm text-muted-foreground">
+                    Showing {table.getRowModel().rows.length} of {data.length} imports
+                </div>
+                <div className="flex items-center space-x-2">
+                    <Button
+                        variant="outline"
+                        size="sm"
+                        onClick={() => table.previousPage()}
+                        disabled={!table.getCanPreviousPage()}
+                    >
+                        <ChevronLeft className="h-4 w-4 mr-1" />
+                        Previous
+                    </Button>
+                    <div className="text-sm font-medium">
+                        Page {table.getState().pagination.pageIndex + 1} of{" "}
+                        {table.getPageCount()}
+                    </div>
+                    <Button
+                        variant="outline"
+                        size="sm"
+                        onClick={() => table.nextPage()}
+                        disabled={!table.getCanNextPage()}
+                    >
+                        Next
+                        <ChevronRight className="h-4 w-4 ml-1" />
+                    </Button>
+                </div>
+            </div>
+        </div>
+    );
+}

+ 11 - 54
app/imports/page.tsx

@@ -1,15 +1,14 @@
 'use client';
 
 import { useState, useEffect, useCallback } from 'react';
-import { Plus, FileText, Calendar, Trash2, Edit } from 'lucide-react';
+import { Plus, FileText } from 'lucide-react';
 import { Button } from '@/components/ui/button';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
-import { Badge } from '@/components/ui/badge';
-import { format } from 'date-fns';
+import { Card, CardContent } from '@/components/ui/card';
 import { getImports, deleteImport } from '@/app/actions/imports';
 import { CreateImportDialog } from '@/app/components/imports/CreateImportDialog';
 import { EditImportDialog } from '@/app/components/imports/EditImportDialog';
 import { ImportDetailDialog } from '@/app/components/imports/ImportDetailDialog';
+import { ImportsTable } from '@/app/components/imports/ImportsTable';
 import { useToast } from '@/hooks/use-toast';
 
 interface Import {
@@ -166,55 +165,13 @@ export default function ImportsPage() {
             </CardContent>
           </Card>
         ) : (
-          <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
-            {imports.map((importRecord) => (
-              <Card key={importRecord.id} className="hover:shadow-lg transition-shadow dark:bg-gray-800 dark:border-gray-700">
-                <CardHeader>
-                  <div className="flex justify-between items-start">
-                    <div>
-                      <CardTitle className="text-lg text-gray-900 dark:text-white">{importRecord.name}</CardTitle>
-                      <CardDescription className="dark:text-gray-300">
-                        Layout: {importRecord.layout.name}
-                      </CardDescription>
-                    </div>
-                    <Badge variant="outline" className="dark:border-gray-600 dark:text-gray-300">
-                      <Calendar className="mr-1 h-3 w-3" />
-                      {format(new Date(importRecord.importDate), 'MMM d, yyyy')}
-                    </Badge>
-                  </div>
-                </CardHeader>
-                <CardContent>
-                  <div className="flex justify-between items-center">
-                    <div className="flex gap-2">
-                      <Button
-                        variant="ghost"
-                        size="sm"
-                        onClick={() => handleViewImport(importRecord)}
-                        className="dark:hover:bg-gray-700"
-                      >
-                        <FileText className="h-4 w-4" />
-                      </Button>
-                      <Button
-                        variant="ghost"
-                        size="sm"
-                        onClick={() => handleEditImport(importRecord)}
-                        className="dark:hover:bg-gray-700"
-                      >
-                        <Edit className="h-4 w-4" />
-                      </Button>
-                      <Button
-                        variant="ghost"
-                        size="sm"
-                        onClick={() => handleDeleteImport(importRecord.id)}
-                        className="dark:hover:bg-gray-700"
-                      >
-                        <Trash2 className="h-4 w-4" />
-                      </Button>
-                    </div>
-                  </div>
-                </CardContent>
-              </Card>
-            ))}
+          <div className="w-full">
+            <ImportsTable
+              data={imports}
+              onView={handleViewImport}
+              onEdit={handleEditImport}
+              onDelete={handleDeleteImport}
+            />
           </div>
         )}
 
@@ -239,4 +196,4 @@ export default function ImportsPage() {
       </div>
     </div>
   );
-}
+}