From b35066835b75aa64963ff49fa6230a90d8ed70de Mon Sep 17 00:00:00 2001 From: tungdtsothink Date: Mon, 7 Jul 2025 16:08:06 +0700 Subject: [PATCH] Add sort for user table and refactor permission page --- src/app/api/user/[id]/route.ts | 15 +++-- src/app/modules/user/[id]/page.tsx | 2 +- src/app/modules/user/[id]/permission/page.tsx | 16 ++--- src/app/modules/user/page.tsx | 3 +- src/components/customers/customer-columns.tsx | 2 +- src/components/ui/server-data-table.tsx | 5 +- src/components/users/user-columns.tsx | 59 +++++++++++++++++-- src/database/db.json | 40 ++++++------- 8 files changed, 96 insertions(+), 46 deletions(-) diff --git a/src/app/api/user/[id]/route.ts b/src/app/api/user/[id]/route.ts index f0219a0..9d61d83 100644 --- a/src/app/api/user/[id]/route.ts +++ b/src/app/api/user/[id]/route.ts @@ -5,10 +5,11 @@ import { join } from "path"; export async function GET( request: Request, - { params }: { params: { id: string } } + { params }: { params: Promise<{ id: string }> } ) { try { - const userId = parseInt(params.id); + const { id } = await params; + const userId = parseInt(id); if (isNaN(userId)) { return NextResponse.json( @@ -45,10 +46,11 @@ export async function GET( export async function PUT( request: Request, - { params }: { params: { id: string } } + { params }: { params: Promise<{ id: string }> } ) { try { - const userId = parseInt(params.id); + const { id } = await params; + const userId = parseInt(id); if (isNaN(userId)) { return NextResponse.json( @@ -129,10 +131,11 @@ export async function PUT( export async function DELETE( request: Request, - { params }: { params: { id: string } } + { params }: { params: Promise<{ id: string }> } ) { try { - const userId = parseInt(params.id); + const { id } = await params; + const userId = parseInt(id); if (isNaN(userId)) { return NextResponse.json( diff --git a/src/app/modules/user/[id]/page.tsx b/src/app/modules/user/[id]/page.tsx index b626be6..23038b6 100644 --- a/src/app/modules/user/[id]/page.tsx +++ b/src/app/modules/user/[id]/page.tsx @@ -39,7 +39,7 @@ export default function UserEditPage() { try { setIsLoading(true); const response = await axios.get(`/api/user/${userId}`); - const userData = response.data; + const userData = response.data.data; // Access the nested data property form.reset({ username: userData.username, diff --git a/src/app/modules/user/[id]/permission/page.tsx b/src/app/modules/user/[id]/permission/page.tsx index 8ce4bf6..736acc6 100644 --- a/src/app/modules/user/[id]/permission/page.tsx +++ b/src/app/modules/user/[id]/permission/page.tsx @@ -40,7 +40,6 @@ export default function UserPermissionPage() { const [user, setUser] = useState(null); const [permissions, setPermissions] = useState([]); - const [userPermissions, setUserPermissions] = useState([]); const [selectedPermissions, setSelectedPermissions] = useState>(new Set()); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); @@ -55,7 +54,7 @@ export default function UserPermissionPage() { if (!userResponse.ok) { throw new Error("Failed to fetch user data"); } - const userData = await userResponse.json(); + const userData: User = await userResponse.json(); setUser(userData); // Fetch all permissions @@ -63,7 +62,7 @@ export default function UserPermissionPage() { if (!permissionsResponse.ok) { throw new Error("Failed to fetch permissions"); } - const permissionsData = await permissionsResponse.json(); + const permissionsData: Permission[] = await permissionsResponse.json(); setPermissions(permissionsData); // Fetch user permissions @@ -71,13 +70,12 @@ export default function UserPermissionPage() { if (!userPermissionsResponse.ok) { throw new Error("Failed to fetch user permissions"); } - const userPermissionsData = await userPermissionsResponse.json(); - setUserPermissions(userPermissionsData); + const userPermissionsData: UserPermission[] = await userPermissionsResponse.json(); // Set selected permissions const selectedIds: Set = new Set(userPermissionsData.map((up: UserPermission) => up.permissionId as number)); setSelectedPermissions(selectedIds); - } catch (error) { + } catch (error: unknown) { console.error("Error fetching data:", error); toast.error("Failed to load user permissions"); } finally { @@ -104,14 +102,12 @@ export default function UserPermissionPage() { const axios = (await import("axios")).default; - const response = await axios.put(`/api/user/${userId}/permissions`, { + await axios.put(`/api/user/${userId}/permissions`, { permissionIds: Array.from(selectedPermissions), }); - const updatedPermissions = response.data; - setUserPermissions(updatedPermissions); toast.success("User permissions updated successfully!"); - } catch (error: any) { + } catch (error: unknown) { console.error("Error updating permissions:", error); toast.error("Failed to update permissions"); } finally { diff --git a/src/app/modules/user/page.tsx b/src/app/modules/user/page.tsx index 65367d8..ab03fa0 100644 --- a/src/app/modules/user/page.tsx +++ b/src/app/modules/user/page.tsx @@ -10,6 +10,7 @@ import axios from "axios"; import { ServerDataTable } from "@/components/ui/server-data-table"; import { User, createUserColumns } from "@/components/users/user-columns"; import { Header } from "@/components/common/header"; +import { SortingState } from "@tanstack/react-table"; interface PaginationInfo { page: number; @@ -49,7 +50,7 @@ export default function UserPage() { }); // Initialize search and sorting state to match query const [searchValue, setSearchValue] = useState(query.search); - const [sorting, setSorting] = useState<{ id: string; desc: boolean }[]>( + const [sorting, setSorting] = useState( query.sortBy ? [{ id: query.sortBy, desc: query.sortOrder === "desc" }] : [] ); diff --git a/src/components/customers/customer-columns.tsx b/src/components/customers/customer-columns.tsx index a3e8796..2730bbe 100644 --- a/src/components/customers/customer-columns.tsx +++ b/src/components/customers/customer-columns.tsx @@ -71,7 +71,7 @@ export const createCustomerColumns = ({ const customer = row.original; return (
onEdit(customer.id)} > {customer.firstNameEn} {customer.lastNameEn} diff --git a/src/components/ui/server-data-table.tsx b/src/components/ui/server-data-table.tsx index ec28eef..c526967 100644 --- a/src/components/ui/server-data-table.tsx +++ b/src/components/ui/server-data-table.tsx @@ -5,6 +5,7 @@ import { flexRender, getCoreRowModel, getSortedRowModel, + SortingState, useReactTable, } from "@tanstack/react-table"; import { useEffect, useRef, useCallback } from "react"; @@ -34,9 +35,9 @@ interface ServerDataTableProps { onSearchChange: (search: string) => void; onSortingChange: (sortBy: string, sortOrder: "asc" | "desc") => void; searchValue: string; - sorting: { id: string; desc: boolean }[]; + sorting: SortingState; setSearchValue: (value: string) => void; - setSorting: (value: { id: string; desc: boolean }[]) => void; + setSorting: (value: SortingState) => void; } export function ServerDataTable({ diff --git a/src/components/users/user-columns.tsx b/src/components/users/user-columns.tsx index 3354aef..11ff23a 100644 --- a/src/components/users/user-columns.tsx +++ b/src/components/users/user-columns.tsx @@ -1,5 +1,6 @@ import { Button } from "@/components/ui/button"; -import { Key } from "lucide-react"; +import { Key, ArrowUpDown } from "lucide-react"; +import { Column } from "@tanstack/react-table"; export interface User { id: number; @@ -19,11 +20,34 @@ export function createUserColumns({ onEdit, onDelete, onPermissions }: { return [ { accessorKey: "id", - header: "ID", + header: ({ column }: { column: Column }) => { + return ( + + ); + }, + enableSorting: true, }, { accessorKey: "fullName", - header: "Name", + header: ({ column }: { column: Column }) => { + return ( + + ); + }, cell: (row: { row: { original: User } }) => ( ), + enableSorting: true, }, { accessorKey: "email", - header: "Email", + header: ({ column }: { column: Column }) => { + return ( + + ); + }, + enableSorting: true, }, { accessorKey: "username", - header: "Username", + header: ({ column }: { column: Column }) => { + return ( + + ); + }, + enableSorting: true, }, { id: "actions", diff --git a/src/database/db.json b/src/database/db.json index 8361ed9..794442a 100644 --- a/src/database/db.json +++ b/src/database/db.json @@ -223,26 +223,6 @@ "userId": 1, "permissionId": 15 }, - { - "id": 16, - "userId": 2, - "permissionId": 4 - }, - { - "id": 17, - "userId": 2, - "permissionId": 5 - }, - { - "id": 18, - "userId": 2, - "permissionId": 8 - }, - { - "id": 19, - "userId": 2, - "permissionId": 11 - }, { "id": 20, "userId": 3, @@ -437,6 +417,26 @@ "id": 58, "userId": 11, "permissionId": 12 + }, + { + "id": 59, + "userId": 2, + "permissionId": 4 + }, + { + "id": 60, + "userId": 2, + "permissionId": 5 + }, + { + "id": 61, + "userId": 2, + "permissionId": 8 + }, + { + "id": 62, + "userId": 2, + "permissionId": 11 } ], "permissions": [