diff options
| author | Max Nanis | 2026-02-18 20:42:03 -0500 |
|---|---|---|
| committer | Max Nanis | 2026-02-18 20:42:03 -0500 |
| commit | 3eaa56f0306ead818f64c3d99fc6d230d9b970a4 (patch) | |
| tree | 9fecc2f1456e6321572e0e65f57106916df173e2 /jb-ui/src/JBApp.tsx | |
| download | amt-jb-3eaa56f0306ead818f64c3d99fc6d230d9b970a4.tar.gz amt-jb-3eaa56f0306ead818f64c3d99fc6d230d9b970a4.zip | |
HERE WE GO, HERE WE GO, HERE WE GO
Diffstat (limited to 'jb-ui/src/JBApp.tsx')
| -rw-r--r-- | jb-ui/src/JBApp.tsx | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/jb-ui/src/JBApp.tsx b/jb-ui/src/JBApp.tsx new file mode 100644 index 0000000..5c99e61 --- /dev/null +++ b/jb-ui/src/JBApp.tsx @@ -0,0 +1,178 @@ +import { + EventMessage, + PingMessage, + PongMessage, + PongMessageKindEnum, + StatsMessage, + StatusApi, + SubscribeMessage, SubscribeMessageKindEnum, + TaskStatusResponse, + UserWalletBalance, + UserWalletBalanceResponse, + WalletApi +} from "@/api_fsb"; +import Footer from "@/components/Footer"; +import { useAppDispatch } from "@/hooks"; +import { bpid, routeBasename, tagManager } from "@/lib/utils"; +import { setAssignmentID, setProductUserID, setTurkSubmitTo } from "@/models/appSlice"; +import { addStatsData } from "@/models/grlStatsSlice"; +import Home from "@/pages/Home"; +import Preview from "@/pages/Preview"; +import Result from "@/pages/Result"; +import Work from "@/pages/Work"; +import { BrowserRouter, Outlet, Route, Routes, useSearchParams } from "react-router-dom"; +import useWebSocket from 'react-use-websocket'; + +import { useEffect } from "react"; + +import Wallet from "@/components/Wallet"; +import "@/index.css"; +import { setTaskStatus, setUserWalletBalance } from "@/models/appSlice"; +import { Profiling } from "./components/Profiling"; + +type Message = PingMessage | PongMessage | SubscribeMessage | EventMessage | StatsMessage; + +function isStatsMessage(msg: Message): msg is StatsMessage { + return msg.kind === 'stats'; +} + +function isPingMessage(msg: Message): msg is PingMessage { + return msg.kind === 'ping'; +} + +function QueryParamProcessor() { + const dispatch = useAppDispatch() + const [searchParams] = useSearchParams(); + + useEffect(() => { + const worker_id = searchParams.get('workerId'); + const assignment_id = searchParams.get('assignmentId'); + const tsid = searchParams.get('tsid'); + const turkSubmitTo = searchParams.get('turkSubmitTo'); + + if (turkSubmitTo) { + dispatch(setTurkSubmitTo(turkSubmitTo)) + } + + if (worker_id) { + dispatch(setProductUserID(worker_id)) + + new WalletApi().getUserWalletBalanceProductIdWalletGet( + bpid, // productId + worker_id, // bpuid + ).then(res => { + const response = res.data as UserWalletBalanceResponse; + const balance = response.wallet as UserWalletBalance; + dispatch(setUserWalletBalance(balance)); + }); + } + + if (assignment_id) { + dispatch(setAssignmentID(assignment_id)) + } + + if (tsid) { + new StatusApi().getTaskStatusProductIdStatusTsidGet( + bpid, // productId + tsid).then(res => { + const response: TaskStatusResponse = res.data; + dispatch(setTaskStatus(response)) + }).catch((error) => { + console.error("Error fetching task status:", error); + }); + } + + }, [searchParams]); + + return <Outlet />; +} + +const Layout = () => { + return ( + <div className="flex flex-col min-h-screen"> + + <main className="flex flex-1 bg-zinc-200"> + <div className="flex flex-col items-center justify-center flex-1"> + <div className=" + w-full max-w-full + p-2 bg-white shadow-lg + text-center space-y-4 + md:max-w-5/8 md:rounded-lg + rounded-none + "> + <Wallet /> + <Profiling /> + <Outlet /> + </div> + </div> + </main > + + <footer className="bg-slate-700 text-zinc-200 p-2 text-center font-mono"> + <Footer /> + </footer> + + </div > + ); +}; + +function JBApp() { + const dispatch = useAppDispatch() + + const { sendJsonMessage, lastMessage } = useWebSocket( + "wss://fsb.generalresearch.com/ws/events/", { + onOpen: () => { + const subscribe: SubscribeMessage = { + "kind": SubscribeMessageKindEnum.Subscribe, + "product_id": bpid + } + sendJsonMessage(subscribe) + } + } + ); + + useEffect(() => { + if (lastMessage !== null) { + let msg: Message = JSON.parse(lastMessage.data); + + if (isStatsMessage(msg)) { + dispatch(addStatsData(msg.data)) + + } else if (isPingMessage(msg)) { + const pong: PongMessage = { + "kind": PongMessageKindEnum.Pong, + } + sendJsonMessage(pong) + } + } + }, [lastMessage]); + + useEffect(() => { + if (!tagManager) return; + + var _mtm = window._mtm = window._mtm || []; + _mtm.push({ 'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start' }); + var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0]; + g.async = true; + g.src = tagManager; + if (s.parentNode) { + s.parentNode.insertBefore(g, s); + } + }, [tagManager]) + + return ( + <BrowserRouter basename={routeBasename}> + <Routes> + <Route element={<QueryParamProcessor />}> + <Route element={<Layout />}> + <Route path="/" element={<Home />} /> + <Route path="/preview/" element={<Preview />} /> + <Route path="/work/" element={<Work />} /> + <Route path="/result/" element={<Result />} /> + </Route> + </Route> + </Routes> + </BrowserRouter> + ) +} + +export default JBApp;
\ No newline at end of file |
