import { EventMessage, EventType, PingMessage, PongMessage, PongMessageKindEnum, StatsMessage, StatusApi, SubscribeMessage, SubscribeMessageKindEnum, TaskStatusResponse, UserWalletBalance, UserWalletBalanceResponse, UserLedgerWallets, UserLedgerWalletAccountTypeEnum, WalletApi, CashoutMethodsResponse, } from "@/api_fsb"; import Footer from "@/components/Footer"; import { useAppDispatch } from "@/hooks"; import { bpid, routeBasename, tagManager } from "@/lib/utils"; import { useGetMeQuery } from "@/models/authAPI"; import { setAssignmentID, setProductUserID, setUserDisplayedWalletBalance, setUserWallet, setUserAttemptCreditWallet, } from "@/models/appSlice"; import { addCashoutMethods } from "@/models/cashoutMethodsSlice"; import { addEvent } from "@/models/grlEventsSlice"; import { addStatsData } from "@/models/grlStatsSlice"; import MagicLink from "@/pages/MagicLink"; import Result from "@/pages/Result"; import clsx from "clsx"; import Work from "@/pages/Work"; import Transfer from "@/pages/Transfer"; import { BrowserRouter, Outlet, useMatch, Route, Routes, useSearchParams, } from "react-router-dom"; import useWebSocket from "react-use-websocket"; import NewsTicker from "./components/EventMarquee"; import { useEffect } from "react"; import Wallet from "@/components/Wallet"; import "@/index.css"; import { setTaskStatus, setUserWalletBalance } from "@/models/appSlice"; import { Profiling } from "./components/Profiling"; import Redemption from "./components/Redemption"; type Message = | PingMessage | PongMessage | SubscribeMessage | EventMessage | StatsMessage; function isStatsMessage(msg: Message): msg is StatsMessage { return msg.kind === "stats"; } function isEventMessage(msg: Message): msg is EventMessage { return msg.kind === "event"; } function isPingMessage(msg: Message): msg is PingMessage { return msg.kind === "ping"; } function QueryParamProcessor() { const dispatch = useAppDispatch(); const [searchParams] = useSearchParams(); const { data: user } = useGetMeQuery(); useEffect(() => { if (user?.product_user_id) { dispatch(setProductUserID(user.product_user_id)); new WalletApi() .getCashoutMethodsProductIdCashoutMethodsGet(bpid, user.product_user_id) .then((res) => { const response = res.data as CashoutMethodsResponse; dispatch(addCashoutMethods(response.cashout_methods)); }); new WalletApi() .getUserWalletBalanceProductIdWalletGet( bpid, // productId user.product_user_id, ) .then((res) => { const response = res.data as UserWalletBalanceResponse; const balance = response.wallet as UserWalletBalance; dispatch(setUserWalletBalance(balance)); }); new WalletApi() .getUserWalletsProductIdWalletsGet(bpid, user.product_user_id) .then((res) => { const response = res.data as UserLedgerWallets; if (response.displayed_balances) { setUserDisplayedWalletBalance(response.displayed_balances[0]); } const userWallet = response.wallets?.find( (w) => w.account_type === UserLedgerWalletAccountTypeEnum.UserWallet, ); if (userWallet) { setUserWallet(userWallet); } const userAttemptCreditWallet = response.wallets?.find( (w) => w.account_type === UserLedgerWalletAccountTypeEnum.UserAttemptCredit, ); if (userAttemptCreditWallet) { setUserAttemptCreditWallet(userAttemptCreditWallet); } }); } }, [user]); useEffect(() => { const assignment_id = searchParams.get("assignmentId"); const tsid = searchParams.get("tsid"); const worker_id = searchParams.get("workerId"); if (worker_id) { dispatch(setProductUserID(worker_id)); } 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 ; } const Layout = () => { const isWork = useMatch("/work/*"); const isPreview = useMatch("/preview/*"); const isSpecialSubview = Boolean(isWork || isPreview); return (

Letter to Cint: supplier quality issues, and malware-linked panels.

); }; 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 (isEventMessage(msg)) { // For simplicity, we just log the event messages here. // You can extend this to update the UI or trigger notifications as needed. switch (msg.data.event_type) { case EventType.TaskEnter: case EventType.TaskFinish: case EventType.UserCreated: dispatch(addEvent(msg.data)); break; default: // do nothing for now break; } } 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 ( }> }> } /> } /> } /> } /> } /> ); } export default JBApp;