feature/dashboardPage #3
@@ -1,10 +1,12 @@
|
|||||||
import CameraStatus from "./CameraStatus";
|
import CameraStatus from "./CameraStatus";
|
||||||
|
import SystemOverview from "./SystemOverview";
|
||||||
import SystemStatusCard from "./SystemStatusCard";
|
import SystemStatusCard from "./SystemStatusCard";
|
||||||
|
|
||||||
const DashboardGrid = () => {
|
const DashboardGrid = () => {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-rows-2">
|
<div className="grid grid-cols-1 md:grid-rows-2 md:grid-cols-2">
|
||||||
<SystemStatusCard />
|
<SystemStatusCard />
|
||||||
|
<SystemOverview />
|
||||||
<CameraStatus title="Camera 1" status={"bg-red-500"} description={"Camera not responding"} />
|
<CameraStatus title="Camera 1" status={"bg-red-500"} description={"Camera not responding"} />
|
||||||
<CameraStatus title="Camera 2" status={"bg-gray-500"} description={"Camera Offline"} />
|
<CameraStatus title="Camera 2" status={"bg-gray-500"} description={"Camera Offline"} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { faHardDrive } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
type StatusItemProps = {
|
||||||
|
statusInfoItem: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusItemCPU = ({ statusInfoItem, description }: StatusItemProps) => {
|
||||||
|
return (
|
||||||
|
<div className="p-3 border border-gray-700 rounded-lg">
|
||||||
|
<div className="flex flex-row gap-2 items-center">
|
||||||
|
<span className="font-bold text-xl bg-slate-700 p-1 px-2 rounded-md">
|
||||||
|
<FontAwesomeIcon icon={faHardDrive} />
|
||||||
|
</span>
|
||||||
|
<p className="text-lg">{statusInfoItem}</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-slate-400">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusItemCPU;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { faClock } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
type StatusItemProps = {
|
||||||
|
statusInfoItem: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusItemLocal = ({ statusInfoItem, description }: StatusItemProps) => {
|
||||||
|
const humanReadable = (string: string) => {
|
||||||
|
if (description.toLowerCase().includes("local")) {
|
||||||
|
const text = string.slice(0, statusInfoItem.length - 5);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-3 border border-gray-700 rounded-lg">
|
||||||
|
<div className="flex flex-row gap-2 items-center">
|
||||||
|
<span className="font-bold text-xl bg-slate-700 p-1 px-2 rounded-md">
|
||||||
|
<FontAwesomeIcon icon={faClock} />
|
||||||
|
</span>
|
||||||
|
<p className="text-lg">{description.toLowerCase().includes("local") && humanReadable(statusInfoItem)}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-slate-400">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusItemLocal;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { faMicrochip } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
type StatusItemProps = {
|
||||||
|
statusInfoItem: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusItemThreads = ({ statusInfoItem, description }: StatusItemProps) => {
|
||||||
|
return (
|
||||||
|
<div className="p-3 border border-gray-700 rounded-lg">
|
||||||
|
<div className="flex flex-row gap-2 items-center">
|
||||||
|
<span className="font-bold text-xl bg-slate-700 p-1 px-2 rounded-md">
|
||||||
|
<FontAwesomeIcon icon={faMicrochip} />
|
||||||
|
</span>
|
||||||
|
<p className="text-lg">{statusInfoItem}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-slate-400">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusItemThreads;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { faClock } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
type StatusItemProps = {
|
||||||
|
statusInfoItem: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusItemUTC = ({ statusInfoItem, description }: StatusItemProps) => {
|
||||||
|
const humanReadable = (string: string) => {
|
||||||
|
if (description.includes("UTC")) {
|
||||||
|
const text = string.slice(0, statusInfoItem.length - 3);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-3 border border-gray-700 rounded-lg">
|
||||||
|
<div className="flex flex-row gap-2 items-center">
|
||||||
|
<span className="font-bold text-xl bg-slate-700 p-1 px-2 rounded-md">
|
||||||
|
<FontAwesomeIcon icon={faClock} />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<p className="text-lg">{description.toLowerCase().includes("utc") && humanReadable(statusInfoItem)}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-slate-400">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusItemUTC;
|
||||||
12
src/features/dashboard/components/SystemOverview.tsx
Normal file
12
src/features/dashboard/components/SystemOverview.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Card from "../../../ui/Card";
|
||||||
|
import CardHeader from "../../../ui/CardHeader";
|
||||||
|
|
||||||
|
const SystemOverview = () => {
|
||||||
|
return (
|
||||||
|
<Card className="p-4">
|
||||||
|
<CardHeader title="System Overview" />
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SystemOverview;
|
||||||
@@ -1,20 +1,24 @@
|
|||||||
import { useInfoSocket } from "../../../app/context/WebSocketContext";
|
import { useInfoSocket } from "../../../app/context/WebSocketContext";
|
||||||
import Card from "../../../ui/Card";
|
import Card from "../../../ui/Card";
|
||||||
import CardHeader from "../../../ui/CardHeader";
|
import CardHeader from "../../../ui/CardHeader";
|
||||||
|
import StatusItemCPU from "./StatusItems/StatusItemCPU";
|
||||||
|
import StatusItemLocal from "./StatusItems/StatusItemLocal";
|
||||||
|
import StatusItemThreads from "./StatusItems/StatusItemThreads";
|
||||||
|
import StatusItemUTC from "./StatusItems/StatusItemUTC";
|
||||||
|
|
||||||
const SystemStatusCard = () => {
|
const SystemStatusCard = () => {
|
||||||
const { data: stats } = useInfoSocket();
|
const { data: stats } = useInfoSocket();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="p-4 w-[40%]">
|
<Card className="p-4">
|
||||||
<CardHeader title="Overview" />
|
<CardHeader title="System Status" />
|
||||||
{stats ? (
|
{stats ? (
|
||||||
<>
|
<div className="grid grid-cols-2 grid-rows-2 gap-4 col-span-2">
|
||||||
<div>UTC: {stats["system-clock-utc"]}</div>
|
<StatusItemUTC statusInfoItem={stats["system-clock-utc"]} description={"UTC Time"} />
|
||||||
<div>Local: {stats["system-clock-local"]}</div>
|
<StatusItemLocal statusInfoItem={stats["system-clock-local"]} description={"Local Time"} />
|
||||||
<span>CPU: {stats["memory-cpu-status"]}</span>
|
<StatusItemCPU statusInfoItem={stats["memory-cpu-status"]} description={"CPU"} />
|
||||||
<span>Threads: {stats["thread-count"]}</span>
|
<StatusItemThreads statusInfoItem={stats["thread-count"]} description={"Threads"} />
|
||||||
</>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-slate-500">Loading system status…</span>
|
<span className="text-slate-500">Loading system status…</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
15
src/features/dashboard/hooks/useGetSystemHealth.ts
Normal file
15
src/features/dashboard/hooks/useGetSystemHealth.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
const response = await fetch(`http://192.168.202.121/api/system-health`);
|
||||||
|
if (!response.ok) throw new Error("Cannot get System overview");
|
||||||
|
return response.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetSystemHealth = () => {
|
||||||
|
const query = useQuery({
|
||||||
|
queryKey: ["fetchSystemData"],
|
||||||
|
queryFn: fetchData,
|
||||||
|
});
|
||||||
|
return { query };
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user