add devices list table
This commit is contained in:
		
							parent
							
								
									cf735f31bf
								
							
						
					
					
						commit
						00be81e18b
					
				
							
								
								
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
        "@tanstack/react-query": "^5.83.0",
 | 
			
		||||
        "@tanstack/react-router": "^1.121.2",
 | 
			
		||||
        "@tanstack/react-router-devtools": "^1.121.2",
 | 
			
		||||
        "@tanstack/react-table": "^8.21.3",
 | 
			
		||||
        "@tanstack/router-plugin": "^1.121.2",
 | 
			
		||||
        "axios": "^1.11.0",
 | 
			
		||||
        "class-variance-authority": "^0.7.1",
 | 
			
		||||
| 
						 | 
				
			
			@ -2496,6 +2497,25 @@
 | 
			
		|||
        "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@tanstack/react-table": {
 | 
			
		||||
      "version": "8.21.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz",
 | 
			
		||||
      "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@tanstack/table-core": "8.21.3"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=12"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "github",
 | 
			
		||||
        "url": "https://github.com/sponsors/tannerlinsley"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": ">=16.8",
 | 
			
		||||
        "react-dom": ">=16.8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@tanstack/router-core": {
 | 
			
		||||
      "version": "1.129.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.129.8.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2648,6 +2668,18 @@
 | 
			
		|||
        "url": "https://github.com/sponsors/tannerlinsley"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@tanstack/table-core": {
 | 
			
		||||
      "version": "8.21.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz",
 | 
			
		||||
      "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=12"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "github",
 | 
			
		||||
        "url": "https://github.com/sponsors/tannerlinsley"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@tanstack/virtual-file-routes": {
 | 
			
		||||
      "version": "1.129.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@tanstack/virtual-file-routes/-/virtual-file-routes-1.129.7.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
    "@tanstack/react-query": "^5.83.0",
 | 
			
		||||
    "@tanstack/react-router": "^1.121.2",
 | 
			
		||||
    "@tanstack/react-router-devtools": "^1.121.2",
 | 
			
		||||
    "@tanstack/react-table": "^8.21.3",
 | 
			
		||||
    "@tanstack/router-plugin": "^1.121.2",
 | 
			
		||||
    "axios": "^1.11.0",
 | 
			
		||||
    "class-variance-authority": "^0.7.1",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,4 +28,8 @@ export const API_ENDPOINTS = {
 | 
			
		|||
    GET_ROOM_LIST: `/DeviceComm/rooms`,
 | 
			
		||||
    GET_DEVICE_FROM_ROOM: (roomName: string) => `/DeviceComm/room/${roomName}`,
 | 
			
		||||
  },
 | 
			
		||||
  SSE_EVENTS: {
 | 
			
		||||
    DEVICE_ONLINE: `/Sse/events/onlineDevices`,
 | 
			
		||||
    DEVICE_OFFLINE: `/Sse/events/offlineDevices`,
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								src/hooks/useDeviceEvents.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/hooks/useDeviceEvents.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
import { useEffect } from "react";
 | 
			
		||||
import { BASE_URL, API_ENDPOINTS } from "@/config/api";
 | 
			
		||||
interface DeviceEventData {
 | 
			
		||||
  Message: string;
 | 
			
		||||
  DeviceId: string;
 | 
			
		||||
  Room: string;
 | 
			
		||||
  Timestamp?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface UseDeviceEventsOptions {
 | 
			
		||||
  onRoomDeviceOnline?: (room: string, deviceId: string) => void;
 | 
			
		||||
  onRoomDeviceOffline?: (room: string, deviceId: string) => void;
 | 
			
		||||
  onDeviceOnlineInRoom?: (deviceId: string, room: string) => void;
 | 
			
		||||
  onDeviceOfflineInRoom?: (deviceId: string, room: string) => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useDeviceEvents(options: UseDeviceEventsOptions) {
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const onlineES = new EventSource(`${BASE_URL}${API_ENDPOINTS.SSE_EVENTS.DEVICE_ONLINE}`);
 | 
			
		||||
    const offlineES = new EventSource(`${BASE_URL}${API_ENDPOINTS.SSE_EVENTS.DEVICE_OFFLINE}`);
 | 
			
		||||
 | 
			
		||||
    onlineES.addEventListener("online", (event) => {
 | 
			
		||||
      try {
 | 
			
		||||
        const data: DeviceEventData = JSON.parse(event.data);
 | 
			
		||||
        options.onRoomDeviceOnline?.(data.Room, data.DeviceId);
 | 
			
		||||
        options.onDeviceOnlineInRoom?.(data.DeviceId, data.Room);
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        console.error("Error parsing online event:", err);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    offlineES.addEventListener("offline", (event) => {
 | 
			
		||||
      try {
 | 
			
		||||
        const data: DeviceEventData = JSON.parse(event.data);
 | 
			
		||||
        options.onRoomDeviceOffline?.(data.Room, data.DeviceId);
 | 
			
		||||
        options.onDeviceOfflineInRoom?.(data.DeviceId, data.Room);
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        console.error("Error parsing offline event:", err);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    onlineES.onerror = (err) => {
 | 
			
		||||
      console.error("Online SSE connection error:", err);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    offlineES.onerror = (err) => {
 | 
			
		||||
      console.error("Offline SSE connection error:", err);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return () => {
 | 
			
		||||
      onlineES.close();
 | 
			
		||||
      offlineES.close();
 | 
			
		||||
    };
 | 
			
		||||
  }, [options]);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,158 @@
 | 
			
		|||
import { createFileRoute } from '@tanstack/react-router'
 | 
			
		||||
import { createFileRoute, useParams } from "@tanstack/react-router";
 | 
			
		||||
import { useQueryData } from "@/hooks/useQueryData";
 | 
			
		||||
import { API_ENDPOINTS, BASE_URL } from "@/config/api";
 | 
			
		||||
import {
 | 
			
		||||
  flexRender,
 | 
			
		||||
  getCoreRowModel,
 | 
			
		||||
  useReactTable,
 | 
			
		||||
  type ColumnDef,
 | 
			
		||||
} from "@tanstack/react-table";
 | 
			
		||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
 | 
			
		||||
import {
 | 
			
		||||
  Table,
 | 
			
		||||
  TableBody,
 | 
			
		||||
  TableCell,
 | 
			
		||||
  TableHead,
 | 
			
		||||
  TableHeader,
 | 
			
		||||
  TableRow,
 | 
			
		||||
} from "@/components/ui/table";
 | 
			
		||||
import { useQueryClient } from "@tanstack/react-query";
 | 
			
		||||
import { useDeviceEvents } from "@/hooks/useDeviceEvents";
 | 
			
		||||
 | 
			
		||||
export const Route = createFileRoute('/_authenticated/room/$roomName/')({
 | 
			
		||||
  component: RouteComponent,
 | 
			
		||||
})
 | 
			
		||||
export const Route = createFileRoute("/_authenticated/room/$roomName/")({
 | 
			
		||||
  head: ({ params }) => ({
 | 
			
		||||
    meta: [{ title: `Danh sách thiết bị phòng ${params.roomName}` }],
 | 
			
		||||
  }),
 | 
			
		||||
  component: RoomDetailComponent,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function RouteComponent() {
 | 
			
		||||
  return <div>Hello "/_authenticated/room/$roomName/"!</div>
 | 
			
		||||
function RoomDetailComponent() {
 | 
			
		||||
  const { roomName } = useParams({ from: "/_authenticated/room/$roomName/" });
 | 
			
		||||
  const queryClient = useQueryClient();
 | 
			
		||||
 | 
			
		||||
  const { data: devices = [], isLoading } = useQueryData({
 | 
			
		||||
    queryKey: ["devices", roomName],
 | 
			
		||||
    url: BASE_URL + API_ENDPOINTS.DEVICE_COMM.GET_DEVICE_FROM_ROOM(roomName),
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Lắng nghe SSE và update state
 | 
			
		||||
  useDeviceEvents({
 | 
			
		||||
    onDeviceOnlineInRoom: (deviceId, room) => {
 | 
			
		||||
      if (room === roomName) {
 | 
			
		||||
        queryClient.setQueryData(
 | 
			
		||||
          ["devices", roomName],
 | 
			
		||||
          (oldDevices: any[] = []) =>
 | 
			
		||||
            oldDevices.map((d) =>
 | 
			
		||||
              d.macAddress === deviceId ? { ...d, isOffline: false } : d
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    onDeviceOfflineInRoom: (deviceId, room) => {
 | 
			
		||||
      if (room === roomName) {
 | 
			
		||||
        queryClient.setQueryData(
 | 
			
		||||
          ["devices", roomName],
 | 
			
		||||
          (oldDevices: any[] = []) =>
 | 
			
		||||
            oldDevices.map((d) =>
 | 
			
		||||
              d.macAddress === deviceId ? { ...d, isOffline: true } : d
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const columns: ColumnDef<any>[] = [
 | 
			
		||||
    {
 | 
			
		||||
      header: "STT",
 | 
			
		||||
      cell: ({ row }) => row.index + 1,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "MAC Address",
 | 
			
		||||
      accessorKey: "macAddress",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Thời gian thiết bị",
 | 
			
		||||
      accessorKey: "deviceTime",
 | 
			
		||||
      cell: ({ getValue }) => {
 | 
			
		||||
        const date = new Date(getValue() as string);
 | 
			
		||||
        return date.toLocaleString();
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Phiên bản",
 | 
			
		||||
      accessorKey: "version",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Địa chỉ IP",
 | 
			
		||||
      accessorKey: "ipAddress",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Trạng thái",
 | 
			
		||||
      accessorKey: "isOffline",
 | 
			
		||||
      cell: ({ getValue }) =>
 | 
			
		||||
        getValue() ? (
 | 
			
		||||
          <span className="text-red-500 font-semibold">Offline</span>
 | 
			
		||||
        ) : (
 | 
			
		||||
          <span className="text-green-500 font-semibold">Online</span>
 | 
			
		||||
        ),
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  const table = useReactTable({
 | 
			
		||||
    data: devices,
 | 
			
		||||
    columns,
 | 
			
		||||
    getCoreRowModel: getCoreRowModel(),
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (isLoading) return <div>Đang tải thiết bị...</div>;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="w-full px-6 space-y-4">
 | 
			
		||||
      <div className="flex items-center justify-between">
 | 
			
		||||
        <div>
 | 
			
		||||
          <h1 className="text-3xl font-bold">Phòng: {roomName}</h1>
 | 
			
		||||
          <p className="text-muted-foreground mt-2">
 | 
			
		||||
            Danh sách thiết bị trong phòng
 | 
			
		||||
          </p>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <Card>
 | 
			
		||||
        <CardHeader>
 | 
			
		||||
          <CardTitle>Thiết bị</CardTitle>
 | 
			
		||||
        </CardHeader>
 | 
			
		||||
        <CardContent>
 | 
			
		||||
          <Table>
 | 
			
		||||
            <TableHeader>
 | 
			
		||||
              {table.getHeaderGroups().map((headerGroup) => (
 | 
			
		||||
                <TableRow key={headerGroup.id}>
 | 
			
		||||
                  {headerGroup.headers.map((header) => (
 | 
			
		||||
                    <TableHead key={header.id}>
 | 
			
		||||
                      {flexRender(
 | 
			
		||||
                        header.column.columnDef.header,
 | 
			
		||||
                        header.getContext()
 | 
			
		||||
                      )}
 | 
			
		||||
                    </TableHead>
 | 
			
		||||
                  ))}
 | 
			
		||||
                </TableRow>
 | 
			
		||||
              ))}
 | 
			
		||||
            </TableHeader>
 | 
			
		||||
            <TableBody>
 | 
			
		||||
              {table.getRowModel().rows.map((row) => (
 | 
			
		||||
                <TableRow key={row.id}>
 | 
			
		||||
                  {row.getVisibleCells().map((cell) => (
 | 
			
		||||
                    <TableCell key={cell.id}>
 | 
			
		||||
                      {flexRender(
 | 
			
		||||
                        cell.column.columnDef.cell,
 | 
			
		||||
                        cell.getContext()
 | 
			
		||||
                      )}
 | 
			
		||||
                    </TableCell>
 | 
			
		||||
                  ))}
 | 
			
		||||
                </TableRow>
 | 
			
		||||
              ))}
 | 
			
		||||
            </TableBody>
 | 
			
		||||
          </Table>
 | 
			
		||||
        </CardContent>
 | 
			
		||||
      </Card>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,161 @@
 | 
			
		|||
import { createFileRoute } from '@tanstack/react-router'
 | 
			
		||||
import { API_ENDPOINTS, BASE_URL } from "@/config/api";
 | 
			
		||||
import { useQueryData } from "@/hooks/useQueryData";
 | 
			
		||||
import { useDeviceEvents } from "@/hooks/useDeviceEvents";
 | 
			
		||||
import { useQueryClient } from "@tanstack/react-query";
 | 
			
		||||
import { createFileRoute, useNavigate } from "@tanstack/react-router";
 | 
			
		||||
import {
 | 
			
		||||
  flexRender,
 | 
			
		||||
  getCoreRowModel,
 | 
			
		||||
  getSortedRowModel,
 | 
			
		||||
  useReactTable,
 | 
			
		||||
  type ColumnDef,
 | 
			
		||||
  type SortingState,
 | 
			
		||||
} from "@tanstack/react-table";
 | 
			
		||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
 | 
			
		||||
import {
 | 
			
		||||
  Table,
 | 
			
		||||
  TableBody,
 | 
			
		||||
  TableCell,
 | 
			
		||||
  TableHead,
 | 
			
		||||
  TableHeader,
 | 
			
		||||
  TableRow,
 | 
			
		||||
} from "@/components/ui/table";
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
export const Route = createFileRoute('/_authenticated/room/')({
 | 
			
		||||
export const Route = createFileRoute("/_authenticated/room/")({
 | 
			
		||||
  head: () => ({
 | 
			
		||||
    meta: [{ title: "Danh sách phòng" }],
 | 
			
		||||
  }),
 | 
			
		||||
  component: RoomComponent,
 | 
			
		||||
})
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function RoomComponent() {
 | 
			
		||||
  return <div>Hello "/_authenticated/room/"!</div>
 | 
			
		||||
  const queryClient = useQueryClient();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const { data: roomData = [], isLoading } = useQueryData({
 | 
			
		||||
    queryKey: ["rooms"],
 | 
			
		||||
    url: BASE_URL + API_ENDPOINTS.DEVICE_COMM.GET_ROOM_LIST,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const [sorting, setSorting] = React.useState<SortingState>([]);
 | 
			
		||||
 | 
			
		||||
  useDeviceEvents({
 | 
			
		||||
    onRoomDeviceOnline: (room) => {
 | 
			
		||||
      queryClient.setQueryData(["rooms"], (oldRooms: any[] = []) =>
 | 
			
		||||
        oldRooms.map((r) =>
 | 
			
		||||
          r.name === room
 | 
			
		||||
            ? { ...r, offlineCount: Math.max((r.offlineCount || 0) - 1, 0) }
 | 
			
		||||
            : r
 | 
			
		||||
        )
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    onRoomDeviceOffline: (room) => {
 | 
			
		||||
      queryClient.setQueryData(["rooms"], (oldRooms: any[] = []) =>
 | 
			
		||||
        oldRooms.map((r) =>
 | 
			
		||||
          r.name === room
 | 
			
		||||
            ? { ...r, offlineCount: (r.offlineCount || 0) + 1 }
 | 
			
		||||
            : r
 | 
			
		||||
        )
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const columns: ColumnDef<any>[] = [
 | 
			
		||||
    {
 | 
			
		||||
      header: "STT",
 | 
			
		||||
      cell: ({ row }) => row.index + 1,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Tên phòng",
 | 
			
		||||
      accessorKey: "name",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Số lượng thiết bị",
 | 
			
		||||
      accessorKey: "numberOfDevices",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      header: "Thiết bị offline",
 | 
			
		||||
      accessorKey: "offlineCount",
 | 
			
		||||
      cell: ({ getValue }) => getValue() || 0,
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  const table = useReactTable({
 | 
			
		||||
    data: roomData,
 | 
			
		||||
    columns,
 | 
			
		||||
    state: { sorting },
 | 
			
		||||
    onSortingChange: setSorting,
 | 
			
		||||
    getCoreRowModel: getCoreRowModel(),
 | 
			
		||||
    getSortedRowModel: getSortedRowModel(),
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (isLoading) return <div>Đang tải...</div>;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="w-full px-6 space-y-4">
 | 
			
		||||
      <div className="flex items-center justify-between">
 | 
			
		||||
        <div>
 | 
			
		||||
          <h1 className="text-3xl font-bold">Quản lý phòng</h1>
 | 
			
		||||
          <p className="text-muted-foreground mt-2">
 | 
			
		||||
            Danh sách các phòng hiện có trong hệ thống
 | 
			
		||||
          </p>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <Card>
 | 
			
		||||
        <CardHeader>
 | 
			
		||||
          <CardTitle>Danh sách phòng</CardTitle>
 | 
			
		||||
        </CardHeader>
 | 
			
		||||
        <CardContent>
 | 
			
		||||
          <Table>
 | 
			
		||||
            <TableHeader>
 | 
			
		||||
              {table.getHeaderGroups().map((headerGroup) => (
 | 
			
		||||
                <TableRow key={headerGroup.id}>
 | 
			
		||||
                  {headerGroup.headers.map((header) => {
 | 
			
		||||
                    const isSorted = header.column.getIsSorted();
 | 
			
		||||
                    return (
 | 
			
		||||
                      <TableHead
 | 
			
		||||
                        key={header.id}
 | 
			
		||||
                        className="cursor-pointer select-none"
 | 
			
		||||
                        onClick={header.column.getToggleSortingHandler()}
 | 
			
		||||
                      >
 | 
			
		||||
                        {flexRender(
 | 
			
		||||
                          header.column.columnDef.header,
 | 
			
		||||
                          header.getContext()
 | 
			
		||||
                        )}
 | 
			
		||||
                        {isSorted ? (isSorted === "asc" ? " ▲" : " ▼") : ""}
 | 
			
		||||
                      </TableHead>
 | 
			
		||||
                    );
 | 
			
		||||
                  })}
 | 
			
		||||
                </TableRow>
 | 
			
		||||
              ))}
 | 
			
		||||
            </TableHeader>
 | 
			
		||||
            <TableBody>
 | 
			
		||||
              {table.getRowModel().rows.map((row) => (
 | 
			
		||||
                <TableRow
 | 
			
		||||
                  key={row.id}
 | 
			
		||||
                  className="cursor-pointer hover:bg-gray-100"
 | 
			
		||||
                  onClick={() =>
 | 
			
		||||
                    navigate({
 | 
			
		||||
                      to: "/room/$roomName",
 | 
			
		||||
                      params: { roomName: row.original.name },
 | 
			
		||||
                    })
 | 
			
		||||
                  }
 | 
			
		||||
                >
 | 
			
		||||
                  {row.getVisibleCells().map((cell) => (
 | 
			
		||||
                    <TableCell key={cell.id}>
 | 
			
		||||
                      {flexRender(
 | 
			
		||||
                        cell.column.columnDef.cell,
 | 
			
		||||
                        cell.getContext()
 | 
			
		||||
                      )}
 | 
			
		||||
                    </TableCell>
 | 
			
		||||
                  ))}
 | 
			
		||||
                </TableRow>
 | 
			
		||||
              ))}
 | 
			
		||||
            </TableBody>
 | 
			
		||||
          </Table>
 | 
			
		||||
        </CardContent>
 | 
			
		||||
      </Card>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user