TTMT.ManageWebGUI/src/routes/_auth/room/$roomName/index.tsx

139 lines
4.8 KiB
TypeScript
Raw Normal View History

2025-08-14 12:16:32 +07:00
import { createFileRoute, useParams } from "@tanstack/react-router";
2025-10-20 16:46:17 +07:00
import { useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
2025-12-03 18:26:36 +07:00
import { LayoutGrid, TableIcon, Monitor, FolderCheck, Loader2 } from "lucide-react";
2025-10-20 16:46:17 +07:00
import { Button } from "@/components/ui/button";
2025-12-22 14:53:19 +07:00
import { useGetDeviceFromRoom } from "@/hooks/queries";
2025-12-03 18:26:36 +07:00
import { useDeviceEvents } from "@/hooks/useDeviceEvents";
import { useClientFolderStatus } from "@/hooks/useClientFolderStatus";
2025-11-19 14:55:14 +07:00
import { DeviceGrid } from "@/components/grids/device-grid";
import { DeviceTable } from "@/components/tables/device-table";
import { useMachineNumber } from "@/hooks/useMachineNumber";
2025-12-03 18:26:36 +07:00
import { toast } from "sonner";
2025-08-11 23:21:36 +07:00
2025-12-22 14:53:19 +07:00
export const Route = createFileRoute("/_auth/room/$roomName/")({
2025-08-14 12:16:32 +07:00
head: ({ params }) => ({
meta: [{ title: `Danh sách thiết bị phòng ${params.roomName}` }],
}),
2025-10-20 16:46:17 +07:00
component: RoomDetailPage,
2025-08-14 12:16:32 +07:00
});
2025-08-11 23:21:36 +07:00
2025-10-20 16:46:17 +07:00
function RoomDetailPage() {
2025-12-22 14:53:19 +07:00
const { roomName } = useParams({ from: "/_auth/room/$roomName/" });
2025-10-31 16:52:56 +07:00
const [viewMode, setViewMode] = useState<"grid" | "table">("grid");
2025-12-03 18:26:36 +07:00
const [isCheckingFolder, setIsCheckingFolder] = useState(false);
// SSE real-time updates
useDeviceEvents(roomName);
// Folder status from SSE
const folderStatuses = useClientFolderStatus(roomName);
2025-12-22 14:53:19 +07:00
const { data: devices = [] } = useGetDeviceFromRoom(roomName);
2025-08-14 12:16:32 +07:00
2025-11-19 14:55:14 +07:00
const parseMachineNumber = useMachineNumber();
2025-12-03 18:26:36 +07:00
const handleCheckFolderStatus = async () => {
try {
setIsCheckingFolder(true);
2025-12-22 14:53:19 +07:00
// Trigger folder status check via the service
2025-12-03 18:26:36 +07:00
const response = await fetch(
2025-12-22 14:53:19 +07:00
`/api/device-comm/request-get-client-folder-status?roomName=${encodeURIComponent(roomName)}`,
2025-12-03 18:26:36 +07:00
{
method: "POST",
}
);
if (!response.ok) {
throw new Error("Failed to request folder status");
}
toast.success("Đang kiểm tra thư mục Setup...");
} catch (error) {
console.error("Check folder error:", error);
toast.error("Lỗi khi kiểm tra thư mục!");
2025-12-22 14:53:19 +07:00
} finally {
2025-12-03 18:26:36 +07:00
setIsCheckingFolder(false);
}
};
2025-11-19 14:55:14 +07:00
const sortedDevices = [...devices].sort((a, b) => {
return parseMachineNumber(a.id) - parseMachineNumber(b.id);
});
2025-08-14 12:16:32 +07:00
return (
2025-09-26 17:56:55 +07:00
<div className="w-full px-6 space-y-6">
<Card className="shadow-sm">
2025-10-20 16:46:17 +07:00
<CardHeader className="bg-muted/50 flex items-center justify-between">
2025-09-26 17:56:55 +07:00
<CardTitle className="flex items-center gap-2">
<Monitor className="h-5 w-5" />
2025-10-20 16:46:17 +07:00
Danh sách thiết bị phòng {roomName}
2025-09-26 17:56:55 +07:00
</CardTitle>
2025-10-20 16:46:17 +07:00
2025-12-03 18:26:36 +07:00
<div className="flex items-center gap-3">
2025-10-20 16:46:17 +07:00
<Button
2025-12-03 18:26:36 +07:00
onClick={handleCheckFolderStatus}
disabled={isCheckingFolder}
variant="outline"
2025-10-20 16:46:17 +07:00
size="sm"
className="flex items-center gap-2"
>
2025-12-03 18:26:36 +07:00
{isCheckingFolder ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<FolderCheck className="h-4 w-4" />
)}
{isCheckingFolder ? "Đang kiểm tra..." : "Kiểm tra thư mục Setup"}
2025-10-20 16:46:17 +07:00
</Button>
2025-12-03 18:26:36 +07:00
<div className="flex items-center gap-2 bg-background rounded-lg p-1 border">
<Button
variant={viewMode === "grid" ? "default" : "ghost"}
size="sm"
onClick={() => setViewMode("grid")}
className="flex items-center gap-2"
>
<LayoutGrid className="h-4 w-4" />
đ
</Button>
<Button
variant={viewMode === "table" ? "default" : "ghost"}
size="sm"
onClick={() => setViewMode("table")}
className="flex items-center gap-2"
>
<TableIcon className="h-4 w-4" />
Bảng
</Button>
</div>
2025-10-20 16:46:17 +07:00
</div>
2025-08-14 12:16:32 +07:00
</CardHeader>
2025-10-20 16:46:17 +07:00
2025-09-26 17:56:55 +07:00
<CardContent className="p-0">
{devices.length === 0 ? (
<div className="flex flex-col items-center justify-center py-12">
<Monitor className="h-12 w-12 text-muted-foreground mb-4" />
<h3 className="text-lg font-semibold mb-2">Không thiết bị</h3>
<p className="text-muted-foreground text-center max-w-sm">
Phòng này chưa thiết bị nào đưc kết nối.
</p>
</div>
2025-10-20 16:46:17 +07:00
) : viewMode === "grid" ? (
2025-12-03 18:26:36 +07:00
<DeviceGrid
devices={sortedDevices}
folderStatuses={folderStatuses}
isCheckingFolder={isCheckingFolder}
/>
2025-09-26 17:56:55 +07:00
) : (
2025-12-03 18:26:36 +07:00
<DeviceTable
devices={sortedDevices}
folderStatuses={folderStatuses}
isCheckingFolder={isCheckingFolder}
/>
2025-09-26 17:56:55 +07:00
)}
2025-08-14 12:16:32 +07:00
</CardContent>
</Card>
</div>
);
2025-08-11 23:21:36 +07:00
}