From 25a744bd8d70bb3945c7237e3eb69540501dc855 Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Fri, 21 Nov 2025 08:55:23 +0000 Subject: [PATCH 1/4] addind dashboard features will come back to finish --- index.html | 4 ++-- .../dashboard/components/CameraStatus.tsx | 19 +++++++++++++++++++ .../dashboard/components/DashboardGrid.tsx | 5 ++++- .../dashboard/components/SystemStatusCard.tsx | 2 +- src/types/types.ts | 2 ++ src/ui/CardHeader.tsx | 8 ++++++-- src/ui/StatusIndicators.tsx | 9 +++++++++ 7 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 src/ui/StatusIndicators.tsx diff --git a/index.html b/index.html index fd0bb43..aec7947 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - + - MAV | BayiQ + BayIQ
diff --git a/src/features/dashboard/components/CameraStatus.tsx b/src/features/dashboard/components/CameraStatus.tsx index e69de29..47cb2d6 100644 --- a/src/features/dashboard/components/CameraStatus.tsx +++ b/src/features/dashboard/components/CameraStatus.tsx @@ -0,0 +1,19 @@ +import Card from "../../../ui/Card"; +import CardHeader from "../../../ui/CardHeader"; + +type CameraStatusProps = { + title: string; + status?: string; + description: string; +}; + +const CameraStatus = ({ title, status, description }: CameraStatusProps) => { + return ( + + +

{description}

+
+ ); +}; + +export default CameraStatus; diff --git a/src/features/dashboard/components/DashboardGrid.tsx b/src/features/dashboard/components/DashboardGrid.tsx index 8cf481c..3e52ec0 100644 --- a/src/features/dashboard/components/DashboardGrid.tsx +++ b/src/features/dashboard/components/DashboardGrid.tsx @@ -1,9 +1,12 @@ +import CameraStatus from "./CameraStatus"; import SystemStatusCard from "./SystemStatusCard"; const DashboardGrid = () => { return ( -
+
+ +
); }; diff --git a/src/features/dashboard/components/SystemStatusCard.tsx b/src/features/dashboard/components/SystemStatusCard.tsx index b887e7e..7d842e9 100644 --- a/src/features/dashboard/components/SystemStatusCard.tsx +++ b/src/features/dashboard/components/SystemStatusCard.tsx @@ -11,7 +11,7 @@ const SystemStatusCard = () => { {stats ? ( <>
UTC: {stats["system-clock-utc"]}
- Local: {stats["system-clock-local"]} +
Local: {stats["system-clock-local"]}
CPU: {stats["memory-cpu-status"]} Threads: {stats["thread-count"]} diff --git a/src/types/types.ts b/src/types/types.ts index bc491f9..3c59478 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -10,3 +10,5 @@ export type InfoBarData = { "memory-cpu-status": string; "thread-count": string; }; + +export type StatusIndicator = "neutral-quaternary" | "dark" | "info" | "success" | "warning" | "danger"; diff --git a/src/ui/CardHeader.tsx b/src/ui/CardHeader.tsx index 027ecae..25da205 100644 --- a/src/ui/CardHeader.tsx +++ b/src/ui/CardHeader.tsx @@ -1,17 +1,21 @@ import clsx from "clsx"; +import StatusIndicators from "./StatusIndicators"; type CameraOverviewHeaderProps = { title?: string; + status?: string; }; -const CardHeader = ({ title }: CameraOverviewHeaderProps) => { +const CardHeader = ({ title, status }: CameraOverviewHeaderProps) => { + console.log(status); return (
-
+
{/* {icon && } */} + {status && }

{title}

diff --git a/src/ui/StatusIndicators.tsx b/src/ui/StatusIndicators.tsx new file mode 100644 index 0000000..5d4d529 --- /dev/null +++ b/src/ui/StatusIndicators.tsx @@ -0,0 +1,9 @@ +import clsx from "clsx"; + +type StatusIndicatorsProps = { status: string }; + +const StatusIndicators = ({ status }: StatusIndicatorsProps) => { + return ; +}; + +export default StatusIndicators; From c9dde6b992562400f2195166b9f6dd79708e677f Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Mon, 24 Nov 2025 14:54:05 +0000 Subject: [PATCH 2/4] - improved the system status ui --- .../dashboard/components/DashboardGrid.tsx | 4 ++- .../components/StatusItems/StatusItemCPU.tsx | 23 +++++++++++++ .../StatusItems/StatusItemLocal.tsx | 31 ++++++++++++++++++ .../StatusItems/StatusItemThreads.tsx | 24 ++++++++++++++ .../components/StatusItems/StatusItemUTC.tsx | 32 +++++++++++++++++++ .../dashboard/components/SystemOverview.tsx | 12 +++++++ .../dashboard/components/SystemStatusCard.tsx | 20 +++++++----- .../dashboard/hooks/useGetSystemHealth.ts | 15 +++++++++ 8 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 src/features/dashboard/components/StatusItems/StatusItemCPU.tsx create mode 100644 src/features/dashboard/components/StatusItems/StatusItemLocal.tsx create mode 100644 src/features/dashboard/components/StatusItems/StatusItemThreads.tsx create mode 100644 src/features/dashboard/components/StatusItems/StatusItemUTC.tsx create mode 100644 src/features/dashboard/components/SystemOverview.tsx create mode 100644 src/features/dashboard/hooks/useGetSystemHealth.ts diff --git a/src/features/dashboard/components/DashboardGrid.tsx b/src/features/dashboard/components/DashboardGrid.tsx index 3e52ec0..b76ea25 100644 --- a/src/features/dashboard/components/DashboardGrid.tsx +++ b/src/features/dashboard/components/DashboardGrid.tsx @@ -1,10 +1,12 @@ import CameraStatus from "./CameraStatus"; +import SystemOverview from "./SystemOverview"; import SystemStatusCard from "./SystemStatusCard"; const DashboardGrid = () => { return ( -
+
+
diff --git a/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx b/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx new file mode 100644 index 0000000..937e5c4 --- /dev/null +++ b/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx @@ -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 ( +
+
+ + + +

{statusInfoItem}

+
+

{description}

+
+ ); +}; + +export default StatusItemCPU; diff --git a/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx b/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx new file mode 100644 index 0000000..77dd4ba --- /dev/null +++ b/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx @@ -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 ( +
+
+ + + +

{description.toLowerCase().includes("local") && humanReadable(statusInfoItem)}

+
+ +

{description}

+
+ ); +}; + +export default StatusItemLocal; diff --git a/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx b/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx new file mode 100644 index 0000000..01e9239 --- /dev/null +++ b/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx @@ -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 ( +
+
+ + + +

{statusInfoItem}

+
+ +

{description}

+
+ ); +}; + +export default StatusItemThreads; diff --git a/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx b/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx new file mode 100644 index 0000000..0b7a5d0 --- /dev/null +++ b/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx @@ -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 ( +
+
+ + + + +

{description.toLowerCase().includes("utc") && humanReadable(statusInfoItem)}

+
+ +

{description}

+
+ ); +}; + +export default StatusItemUTC; diff --git a/src/features/dashboard/components/SystemOverview.tsx b/src/features/dashboard/components/SystemOverview.tsx new file mode 100644 index 0000000..de6e89b --- /dev/null +++ b/src/features/dashboard/components/SystemOverview.tsx @@ -0,0 +1,12 @@ +import Card from "../../../ui/Card"; +import CardHeader from "../../../ui/CardHeader"; + +const SystemOverview = () => { + return ( + + + + ); +}; + +export default SystemOverview; diff --git a/src/features/dashboard/components/SystemStatusCard.tsx b/src/features/dashboard/components/SystemStatusCard.tsx index d2ee725..e3307b4 100644 --- a/src/features/dashboard/components/SystemStatusCard.tsx +++ b/src/features/dashboard/components/SystemStatusCard.tsx @@ -1,20 +1,24 @@ import { useInfoSocket } from "../../../app/context/WebSocketContext"; import Card from "../../../ui/Card"; 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 { data: stats } = useInfoSocket(); return ( - - + + {stats ? ( - <> -
UTC: {stats["system-clock-utc"]}
-
Local: {stats["system-clock-local"]}
- CPU: {stats["memory-cpu-status"]} - Threads: {stats["thread-count"]} - +
+ + + + +
) : ( Loading system status… )} diff --git a/src/features/dashboard/hooks/useGetSystemHealth.ts b/src/features/dashboard/hooks/useGetSystemHealth.ts new file mode 100644 index 0000000..2c4bb3f --- /dev/null +++ b/src/features/dashboard/hooks/useGetSystemHealth.ts @@ -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 }; +}; From 31b6bd45f571fb77f88b426a21e88abc962c3a5a Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Mon, 24 Nov 2025 16:17:27 +0000 Subject: [PATCH 3/4] - improved Dashboard ui --- .../dashboard/components/CameraStatus.tsx | 2 +- .../dashboard/components/DashboardGrid.tsx | 7 ++-- .../components/StatusItems/StatusItemCPU.tsx | 2 +- .../StatusItems/StatusItemLocal.tsx | 2 +- .../StatusItems/StatusItemThreads.tsx | 2 +- .../components/StatusItems/StatusItemUTC.tsx | 2 +- .../dashboard/components/SystemHealth.tsx | 34 +++++++++++++++++++ .../dashboard/components/SystemOverview.tsx | 4 ++- src/routes/baywatch.tsx | 1 - src/routes/index.tsx | 1 - src/types/types.ts | 5 +++ src/ui/Badge.tsx | 24 +++++++++++++ src/utils/utils.ts | 3 ++ 13 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 src/features/dashboard/components/SystemHealth.tsx create mode 100644 src/ui/Badge.tsx create mode 100644 src/utils/utils.ts diff --git a/src/features/dashboard/components/CameraStatus.tsx b/src/features/dashboard/components/CameraStatus.tsx index 47cb2d6..9c28274 100644 --- a/src/features/dashboard/components/CameraStatus.tsx +++ b/src/features/dashboard/components/CameraStatus.tsx @@ -9,7 +9,7 @@ type CameraStatusProps = { const CameraStatus = ({ title, status, description }: CameraStatusProps) => { return ( - +

{description}

diff --git a/src/features/dashboard/components/DashboardGrid.tsx b/src/features/dashboard/components/DashboardGrid.tsx index b76ea25..b430106 100644 --- a/src/features/dashboard/components/DashboardGrid.tsx +++ b/src/features/dashboard/components/DashboardGrid.tsx @@ -7,8 +7,11 @@ const DashboardGrid = () => {
- - +
+ + + +
); }; diff --git a/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx b/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx index 937e5c4..3ae97f6 100644 --- a/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx +++ b/src/features/dashboard/components/StatusItems/StatusItemCPU.tsx @@ -8,7 +8,7 @@ type StatusItemProps = { const StatusItemCPU = ({ statusInfoItem, description }: StatusItemProps) => { return ( -
+
diff --git a/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx b/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx index 77dd4ba..f99cf40 100644 --- a/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx +++ b/src/features/dashboard/components/StatusItems/StatusItemLocal.tsx @@ -15,7 +15,7 @@ const StatusItemLocal = ({ statusInfoItem, description }: StatusItemProps) => { }; return ( -
+
diff --git a/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx b/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx index 01e9239..69ce8c8 100644 --- a/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx +++ b/src/features/dashboard/components/StatusItems/StatusItemThreads.tsx @@ -8,7 +8,7 @@ type StatusItemProps = { const StatusItemThreads = ({ statusInfoItem, description }: StatusItemProps) => { return ( -
+
diff --git a/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx b/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx index 0b7a5d0..b4adef8 100644 --- a/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx +++ b/src/features/dashboard/components/StatusItems/StatusItemUTC.tsx @@ -15,7 +15,7 @@ const StatusItemUTC = ({ statusInfoItem, description }: StatusItemProps) => { }; return ( -
+
diff --git a/src/features/dashboard/components/SystemHealth.tsx b/src/features/dashboard/components/SystemHealth.tsx new file mode 100644 index 0000000..c93d731 --- /dev/null +++ b/src/features/dashboard/components/SystemHealth.tsx @@ -0,0 +1,34 @@ +import type { SystemHealthStatus } from "../../../types/types"; +import Badge from "../../../ui/Badge"; +import { useGetSystemHealth } from "../hooks/useGetSystemHealth"; + +const SystemHealth = () => { + const { query } = useGetSystemHealth(); + + const startTime = query?.data?.StartTimeHumane; + const uptime = query?.data?.UptimeHumane; + const statuses = query?.data?.Status; + + return ( +
+
+
+

Start Time

{startTime} +
+
+

Up Time

{uptime} +
+
+ +
+ {statuses?.map((status: SystemHealthStatus) => ( +
+ {status.id} +
+ ))} +
+
+ ); +}; + +export default SystemHealth; diff --git a/src/features/dashboard/components/SystemOverview.tsx b/src/features/dashboard/components/SystemOverview.tsx index de6e89b..05d1f20 100644 --- a/src/features/dashboard/components/SystemOverview.tsx +++ b/src/features/dashboard/components/SystemOverview.tsx @@ -1,10 +1,12 @@ import Card from "../../../ui/Card"; import CardHeader from "../../../ui/CardHeader"; +import SystemHealth from "./SystemHealth"; const SystemOverview = () => { return ( - + + ); }; diff --git a/src/routes/baywatch.tsx b/src/routes/baywatch.tsx index f7401ab..0cb9718 100644 --- a/src/routes/baywatch.tsx +++ b/src/routes/baywatch.tsx @@ -9,7 +9,6 @@ export const Route = createFileRoute("/baywatch")({ function RouteComponent() { return (
-

Cameras

diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 8cd7e69..301f601 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -8,7 +8,6 @@ export const Route = createFileRoute("/")({ function HomePage() { return (
-

Dashboard

); diff --git a/src/types/types.ts b/src/types/types.ts index 127fad1..b130f22 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -16,3 +16,8 @@ export type Region = { name: string; brushColour: string; }; + +export type SystemHealthStatus = { + id: string; + tags: string[]; +}; diff --git a/src/ui/Badge.tsx b/src/ui/Badge.tsx new file mode 100644 index 0000000..7e088af --- /dev/null +++ b/src/ui/Badge.tsx @@ -0,0 +1,24 @@ +import type { Icon, IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { capitalize } from "../utils/utils"; + +type BadgeProps = { + icon?: Icon | IconDefinition; + text: string; +}; + +const Badge = ({ icon, text }: BadgeProps) => { + const lowerCaseWord = text.toLowerCase(); + return ( + + {icon && } + {capitalize(lowerCaseWord)} + + ); +}; + +export default Badge; diff --git a/src/utils/utils.ts b/src/utils/utils.ts new file mode 100644 index 0000000..23c5527 --- /dev/null +++ b/src/utils/utils.ts @@ -0,0 +1,3 @@ +export function capitalize(s?: string) { + return s ? s.charAt(0).toUpperCase() + s.slice(1) : ""; +} From 27d2c6a1b98925a89e84ef9ead9f136dd12d78bc Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Mon, 24 Nov 2025 20:32:52 +0000 Subject: [PATCH 4/4] - improved ui for dashboard - added refetch fn --- .../dashboard/components/SystemHealth.tsx | 16 ++++++++++------ .../dashboard/components/SystemOverview.tsx | 12 ++++++++++-- .../dashboard/hooks/useGetSystemHealth.ts | 2 +- src/ui/CardHeader.tsx | 17 +++++++++++------ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/features/dashboard/components/SystemHealth.tsx b/src/features/dashboard/components/SystemHealth.tsx index c93d731..6f1e12b 100644 --- a/src/features/dashboard/components/SystemHealth.tsx +++ b/src/features/dashboard/components/SystemHealth.tsx @@ -1,13 +1,17 @@ import type { SystemHealthStatus } from "../../../types/types"; import Badge from "../../../ui/Badge"; -import { useGetSystemHealth } from "../hooks/useGetSystemHealth"; -const SystemHealth = () => { - const { query } = useGetSystemHealth(); +type SystemHealthProps = { + startTime: string; + uptime: string; + statuses: SystemHealthStatus[]; + isLoading: boolean; +}; - const startTime = query?.data?.StartTimeHumane; - const uptime = query?.data?.UptimeHumane; - const statuses = query?.data?.Status; +const SystemHealth = ({ startTime, uptime, statuses, isLoading }: SystemHealthProps) => { + if (isLoading) { + return Loading system health…; + } return (
diff --git a/src/features/dashboard/components/SystemOverview.tsx b/src/features/dashboard/components/SystemOverview.tsx index 05d1f20..2a6559d 100644 --- a/src/features/dashboard/components/SystemOverview.tsx +++ b/src/features/dashboard/components/SystemOverview.tsx @@ -1,12 +1,20 @@ +import { faArrowsRotate } from "@fortawesome/free-solid-svg-icons"; import Card from "../../../ui/Card"; import CardHeader from "../../../ui/CardHeader"; +import { useGetSystemHealth } from "../hooks/useGetSystemHealth"; import SystemHealth from "./SystemHealth"; const SystemOverview = () => { + const { query } = useGetSystemHealth(); + + const startTime = query?.data?.StartTimeHumane; + const uptime = query?.data?.UptimeHumane; + const statuses = query?.data?.Status; + const isLoading = query?.isLoading; return ( - - + + ); }; diff --git a/src/features/dashboard/hooks/useGetSystemHealth.ts b/src/features/dashboard/hooks/useGetSystemHealth.ts index 2c4bb3f..d9599d6 100644 --- a/src/features/dashboard/hooks/useGetSystemHealth.ts +++ b/src/features/dashboard/hooks/useGetSystemHealth.ts @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query"; const fetchData = async () => { - const response = await fetch(`http://192.168.202.121/api/system-health`); + const response = await fetch(`http://100.115.148.59/api/system-health`); if (!response.ok) throw new Error("Cannot get System overview"); return response.json(); }; diff --git a/src/ui/CardHeader.tsx b/src/ui/CardHeader.tsx index 25da205..3d6c3b2 100644 --- a/src/ui/CardHeader.tsx +++ b/src/ui/CardHeader.tsx @@ -1,22 +1,27 @@ import clsx from "clsx"; import StatusIndicators from "./StatusIndicators"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import type { IconProp } from "@fortawesome/fontawesome-svg-core"; type CameraOverviewHeaderProps = { title?: string; status?: string; + refetch?: () => void; + icon?: IconProp; }; -const CardHeader = ({ title, status }: CameraOverviewHeaderProps) => { - console.log(status); +const CardHeader = ({ title, status, icon, refetch }: CameraOverviewHeaderProps) => { return (
-
- {/* {icon && } */} - {status && } -

{title}

+
+

+ {status && } + {title} +

+ {icon && }
);