From 4f13ed104d879fe17f949bd61d65e3570c206acb Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Fri, 21 Nov 2025 11:41:42 +0000 Subject: [PATCH] - added new websocket implementation --- package.json | 3 +- src/app/context/WebSocketContext.ts | 23 +++++++++++ src/app/providers/AppProviders.tsx | 10 +++-- src/app/providers/WebSocketProvider.tsx | 38 +++++++++++++++++++ .../dashboard/components/SystemStatusCard.tsx | 4 +- yarn.lock | 5 +++ 6 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 src/app/context/WebSocketContext.ts create mode 100644 src/app/providers/WebSocketProvider.tsx diff --git a/package.json b/package.json index cb4c39e..11627c2 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "@tanstack/react-router-devtools": "^1.136.18", "clsx": "^2.1.1", "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "react-use-websocket": "3.0.0" }, "devDependencies": { "@eslint/js": "^9.39.1", diff --git a/src/app/context/WebSocketContext.ts b/src/app/context/WebSocketContext.ts new file mode 100644 index 0000000..65799c0 --- /dev/null +++ b/src/app/context/WebSocketContext.ts @@ -0,0 +1,23 @@ +import { createContext, useContext } from "react"; +import { ReadyState } from "react-use-websocket"; +import type { InfoBarData } from "../../types/types"; + +type InfoSocketState = { + data: InfoBarData | null; + readyState: ReadyState; + sendJson: (msg: unknown) => void; +}; + +export type WebSocketConextValue = { + info: InfoSocketState; +}; + +export const WebsocketContext = createContext(null); + +const useWebSocketContext = () => { + const ctx = useContext(WebsocketContext); + if (!ctx) throw new Error("useWebSocketContext must be used inside "); + return ctx; +}; + +export const useInfoSocket = () => useWebSocketContext().info; diff --git a/src/app/providers/AppProviders.tsx b/src/app/providers/AppProviders.tsx index a07b51a..7a73155 100644 --- a/src/app/providers/AppProviders.tsx +++ b/src/app/providers/AppProviders.tsx @@ -1,7 +1,11 @@ -import { QueryClientProvider } from "@tanstack/react-query"; -import { queryClient } from "../config/queryClient"; import type { PropsWithChildren } from "react"; +import { QueryProvider } from "./QueryProviders"; +import { WebSocketProvider } from "./WebSocketProvider"; export const AppProviders = ({ children }: PropsWithChildren) => { - return {children}; + return ( + + {children} + + ); }; diff --git a/src/app/providers/WebSocketProvider.tsx b/src/app/providers/WebSocketProvider.tsx new file mode 100644 index 0000000..42ff194 --- /dev/null +++ b/src/app/providers/WebSocketProvider.tsx @@ -0,0 +1,38 @@ +import { useEffect, useMemo, useState, type ReactNode } from "react"; +import { WebsocketContext, type WebSocketConextValue } from "../context/WebSocketContext"; +import useWebSocket from "react-use-websocket"; +import { wsConfig } from "../config/wsconfig"; +import type { InfoBarData } from "../../types/types"; + +type WebSocketProviderProps = { + children: ReactNode; +}; + +export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { + const [systemData, setSystemData] = useState(null); + const infoSocket = useWebSocket(wsConfig.infoBar, { share: true, shouldReconnect: () => true }); + + useEffect(() => { + async function parseData() { + if (infoSocket.lastMessage) { + const text = await infoSocket.lastMessage.data.text(); + const data = JSON.parse(text); + setSystemData(data); + } + } + parseData(); + }, [infoSocket.lastMessage]); + + const value = useMemo( + () => ({ + info: { + data: systemData, + readyState: infoSocket.readyState, + sendJson: infoSocket.sendJsonMessage, + }, + }), + [infoSocket.readyState, infoSocket.sendJsonMessage, systemData], + ); + + return {children}; +}; diff --git a/src/features/dashboard/components/SystemStatusCard.tsx b/src/features/dashboard/components/SystemStatusCard.tsx index b887e7e..e7d6c09 100644 --- a/src/features/dashboard/components/SystemStatusCard.tsx +++ b/src/features/dashboard/components/SystemStatusCard.tsx @@ -1,9 +1,9 @@ -import { useInfoSocket } from "../../../hooks/useInfoWebSocket"; +import { useInfoSocket } from "../../../app/context/WebSocketContext"; import Card from "../../../ui/Card"; import CardHeader from "../../../ui/CardHeader"; const SystemStatusCard = () => { - const { stats } = useInfoSocket(); + const { data: stats } = useInfoSocket(); return ( diff --git a/yarn.lock b/yarn.lock index f9e9fcd..1101e46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2049,6 +2049,11 @@ react-refresh@^0.18.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.18.0.tgz#2dce97f4fe932a4d8142fa1630e475c1729c8062" integrity sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw== +react-use-websocket@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/react-use-websocket/-/react-use-websocket-3.0.0.tgz#754cb8eea76f55d31c5676d4abe3e573bc2cea04" + integrity sha512-BInlbhXYrODBPKIplDAmI0J1VPM+1KhCLN09o+dzgQ8qMyrYs4t5kEYmCrTqyRuMTmpahylHFZWQXpfYyDkqOw== + react@^19.2.0: version "19.2.0" resolved "https://registry.yarnpkg.com/react/-/react-19.2.0.tgz#d33dd1721698f4376ae57a54098cb47fc75d93a5"