2026-04-01 16:46:33 +07:00
|
|
|
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
|
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
|
|
|
import type { RoomManagementResponse, RoomHealthStatus } from "@/types/dashboard";
|
|
|
|
|
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip } from "recharts";
|
|
|
|
|
|
|
|
|
|
function statusBadge(status?: string) {
|
|
|
|
|
if (!status) return <Badge>Unknown</Badge>;
|
|
|
|
|
if (status === "InSession") return <Badge className="bg-green-100 text-green-700">Đang sử dụng</Badge>;
|
|
|
|
|
if (status === "NotInUse") return <Badge className="bg-red-100 text-red-700">Không sử dụng</Badge>;
|
|
|
|
|
return <Badge className="bg-yellow-100 text-yellow-700">Có thể có lớp học</Badge>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function RoomManagementCard({
|
|
|
|
|
data,
|
|
|
|
|
isLoading = false,
|
|
|
|
|
}: {
|
|
|
|
|
data?: RoomManagementResponse | null;
|
|
|
|
|
isLoading?: boolean;
|
|
|
|
|
}) {
|
|
|
|
|
const chartData = (data?.rooms ?? []).map((r) => ({ room: r.roomName, health: r.healthPercentage ?? 0 }));
|
|
|
|
|
return (
|
|
|
|
|
<Card className="bg-white/80 backdrop-blur border-muted/60 shadow-sm">
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle>Quản lý phòng</CardTitle>
|
2026-04-03 17:01:33 +07:00
|
|
|
<CardDescription>Thông tin tổng quan và các phòng đang không sử dụng</CardDescription>
|
2026-04-01 16:46:33 +07:00
|
|
|
</CardHeader>
|
|
|
|
|
|
|
|
|
|
<CardContent>
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
<div>
|
|
|
|
|
<div className="text-xs text-muted-foreground">Tổng phòng</div>
|
|
|
|
|
<div className="text-2xl font-bold">{data?.totalRooms ?? 0}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="mt-4">
|
|
|
|
|
<div className="text-sm font-medium mb-2">Tỉ lệ thiết bị online</div>
|
|
|
|
|
<div className="h-48">
|
|
|
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
|
|
|
<BarChart data={chartData} layout="vertical">
|
|
|
|
|
<CartesianGrid strokeDasharray="3 3" />
|
|
|
|
|
<XAxis type="number" domain={[0, 100]} />
|
|
|
|
|
<YAxis dataKey="room" type="category" width={110} />
|
|
|
|
|
<Tooltip />
|
|
|
|
|
<Bar dataKey="health" fill="#0ea5e9" radius={[4, 4, 4, 4]} />
|
|
|
|
|
</BarChart>
|
|
|
|
|
</ResponsiveContainer>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-4">
|
2026-04-03 17:01:33 +07:00
|
|
|
<div className="text-sm font-medium">Phòng không dùng</div>
|
2026-04-01 16:46:33 +07:00
|
|
|
<div className="mt-2 space-y-2">
|
|
|
|
|
{data?.roomsNeedAttention && data.roomsNeedAttention.length > 0 ? (
|
|
|
|
|
data.roomsNeedAttention.map((r: RoomHealthStatus) => (
|
|
|
|
|
<div key={r.roomName} className="flex items-center justify-between">
|
|
|
|
|
<div>
|
|
|
|
|
<div className="font-medium">{r.roomName}</div>
|
|
|
|
|
<div className="text-xs text-muted-foreground">{r.totalDevices} thiết bị</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<div className="text-sm font-medium">{r.healthPercentage?.toFixed(1) ?? "-"}%</div>
|
|
|
|
|
{statusBadge(r.healthStatus)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
))
|
|
|
|
|
) : (
|
|
|
|
|
<div className="text-sm text-muted-foreground">Không có phòng cần chú ý</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
|
|
|
|
}
|