Compare commits
10 Commits
a95e6cbef2
...
b35066835b
| Author | SHA1 | Date | |
|---|---|---|---|
| b35066835b | |||
| bd70451320 | |||
| 1865cf4efd | |||
| ae1a45fe57 | |||
| 76ca36ca1b | |||
| 815de2932b | |||
| e8f76f395a | |||
| 99607fb75b | |||
| 1b00f472a2 | |||
| ddc122c0a5 |
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -40,7 +40,6 @@ export default function UserPermissionPage() {
|
||||
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [permissions, setPermissions] = useState<Permission[]>([]);
|
||||
const [userPermissions, setUserPermissions] = useState<UserPermission[]>([]);
|
||||
const [selectedPermissions, setSelectedPermissions] = useState<Set<number>>(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<number> = new Set<number>(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<UserPermission[]>(`/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 {
|
||||
|
||||
@@ -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<SortingState>(
|
||||
query.sortBy ? [{ id: query.sortBy, desc: query.sortOrder === "desc" }] : []
|
||||
);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ export const createCustomerColumns = ({
|
||||
const customer = row.original;
|
||||
return (
|
||||
<div
|
||||
className="font-medium cursor-pointer hover:text-blue-600 hover:underline"
|
||||
className="text-blue-600 hover:text-blue-800 hover:underline cursor-pointer font-medium"
|
||||
onClick={() => onEdit(customer.id)}
|
||||
>
|
||||
{customer.firstNameEn} {customer.lastNameEn}
|
||||
|
||||
@@ -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<TData, TValue> {
|
||||
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<TData, TValue>({
|
||||
|
||||
@@ -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<User, unknown> }) => {
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||
className="h-8 p-0 font-medium"
|
||||
>
|
||||
ID
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
accessorKey: "fullName",
|
||||
header: "Name",
|
||||
header: ({ column }: { column: Column<User, unknown> }) => {
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||
className="h-8 p-0 font-medium"
|
||||
>
|
||||
Name
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
cell: (row: { row: { original: User } }) => (
|
||||
<button
|
||||
onClick={() => onEdit?.(row.row.original.id)}
|
||||
@@ -32,14 +56,39 @@ export function createUserColumns({ onEdit, onDelete, onPermissions }: {
|
||||
{`${row.row.original.firstName} ${row.row.original.lastName}`}
|
||||
</button>
|
||||
),
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
accessorKey: "email",
|
||||
header: "Email",
|
||||
header: ({ column }: { column: Column<User, unknown> }) => {
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||
className="h-8 p-0 font-medium"
|
||||
>
|
||||
Email
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
accessorKey: "username",
|
||||
header: "Username",
|
||||
header: ({ column }: { column: Column<User, unknown> }) => {
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||
className="h-8 p-0 font-medium"
|
||||
>
|
||||
Username
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
|
||||
@@ -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": [
|
||||
|
||||
Reference in New Issue
Block a user