From ed201936813d9a720b51e6cb40a05267b94e7314 Mon Sep 17 00:00:00 2001 From: Max Nanis Date: Thu, 10 Sep 2026 17:46:41 -0700 Subject: Typescript prettier Committing seperate so it's easier to see actual changes. --- jb-ui/src/store.ts | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'jb-ui/src/store.ts') diff --git a/jb-ui/src/store.ts b/jb-ui/src/store.ts index 7b4d3e3..07cac9e 100644 --- a/jb-ui/src/store.ts +++ b/jb-ui/src/store.ts @@ -1,32 +1,31 @@ -import appReducers from "@/models/appSlice" -import grlStatsReducers from "@/models/grlStatsSlice" -import grlEventsReducers from "@/models/grlEventsSlice" -import profilingQuestionsReducers from "@/models/profilingQuestionsSlice" -import type { Action, ThunkAction } from '@reduxjs/toolkit' -import { configureStore } from '@reduxjs/toolkit' - +import appReducers from "@/models/appSlice"; +import grlStatsReducers from "@/models/grlStatsSlice"; +import grlEventsReducers from "@/models/grlEventsSlice"; +import profilingQuestionsReducers from "@/models/profilingQuestionsSlice"; +import type { Action, ThunkAction } from "@reduxjs/toolkit"; +import { configureStore } from "@reduxjs/toolkit"; export const store = configureStore({ - reducer: { - app: appReducers, - stats: grlStatsReducers, - events: grlEventsReducers, - profilingQuestions: profilingQuestionsReducers, - } -}) + reducer: { + app: appReducers, + stats: grlStatsReducers, + events: grlEventsReducers, + profilingQuestions: profilingQuestionsReducers, + }, +}); // Infer the type of `store` -export type AppStore = typeof store +export type AppStore = typeof store; // Infer the `AppDispatch` type from the store itself -export type AppDispatch = typeof store.dispatch +export type AppDispatch = typeof store.dispatch; // Same for the `RootState` type -export type RootState = ReturnType +export type RootState = ReturnType; // Define a reusable type describing thunk functions export type AppThunk = ThunkAction< - ThunkReturnType, - RootState, - unknown, - Action -> + ThunkReturnType, + RootState, + unknown, + Action +>; -- cgit v1.2.3 From 11d63b171501b9c29398133b795c3bcc1ae85a1b Mon Sep 17 00:00:00 2001 From: Max Nanis Date: Fri, 11 Sep 2026 18:16:06 -0700 Subject: using RTK with session login. start of magic token request --- jb-ui/.vscode/settings.json | 2 +- jb-ui/src/AuthContext.tsx | 28 ++++++++++++ jb-ui/src/JBApp.tsx | 4 +- jb-ui/src/models/authAPI.ts | 23 ++++++++++ jb-ui/src/pages/Work.tsx | 103 ++++++++++++++++++++++++++++++++++++++++---- jb-ui/src/store.ts | 5 +++ jb/views/auth.py | 20 +++++---- 7 files changed, 164 insertions(+), 21 deletions(-) create mode 100644 jb-ui/src/AuthContext.tsx create mode 100644 jb-ui/src/models/authAPI.ts (limited to 'jb-ui/src/store.ts') diff --git a/jb-ui/.vscode/settings.json b/jb-ui/.vscode/settings.json index 4257030..9b8250c 100644 --- a/jb-ui/.vscode/settings.json +++ b/jb-ui/.vscode/settings.json @@ -10,6 +10,6 @@ "editor.formatOnSave": true }, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" } } \ No newline at end of file diff --git a/jb-ui/src/AuthContext.tsx b/jb-ui/src/AuthContext.tsx new file mode 100644 index 0000000..85bcdb0 --- /dev/null +++ b/jb-ui/src/AuthContext.tsx @@ -0,0 +1,28 @@ +// AuthContext.jsx +import { createContext, useContext, useEffect, useState } from "react"; + +const AuthContext = createContext(null); + +export function AuthProvider({ children }) { + const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch("/api/me", { credentials: "include" }) + .then((res) => (res.ok ? res.json() : null)) + .then(setUser) + .finally(() => setLoading(false)); + }, []); + + return ( + + {children} + + ); +} + +export function useAuth() { + return useContext(AuthContext); +} diff --git a/jb-ui/src/JBApp.tsx b/jb-ui/src/JBApp.tsx index 7c99315..fd0eeba 100644 --- a/jb-ui/src/JBApp.tsx +++ b/jb-ui/src/JBApp.tsx @@ -225,10 +225,10 @@ function JBApp() { return ( - } /> }> }> - } /> + } /> + } /> {/* } /> */} } /> diff --git a/jb-ui/src/models/authAPI.ts b/jb-ui/src/models/authAPI.ts new file mode 100644 index 0000000..1ac7886 --- /dev/null +++ b/jb-ui/src/models/authAPI.ts @@ -0,0 +1,23 @@ +import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; + +export const authApi = createApi({ + reducerPath: "authApi", + baseQuery: fetchBaseQuery({ + baseUrl: "/auth", + credentials: "include", // sends the httpOnly cookie + }), + tagTypes: ["User"], + endpoints: (builder) => ({ + getMe: builder.query({ + query: () => "/session", + providesTags: ["User"], + }), + // logout: builder.mutation({ + // query: () => ({ url: "/de-session", method: "POST" }), + // invalidatesTags: ["User"], + // }), + }), +}); + +// export const { useGetMeQuery, useLogoutMutation } = authApi; +export const { useGetMeQuery } = authApi; diff --git a/jb-ui/src/pages/Work.tsx b/jb-ui/src/pages/Work.tsx index 32dcc96..e33328e 100644 --- a/jb-ui/src/pages/Work.tsx +++ b/jb-ui/src/pages/Work.tsx @@ -1,3 +1,4 @@ +import { useGetMeQuery } from "@/models/authAPI"; import { BucketTask, OfferwallApi, @@ -828,17 +829,101 @@ const SurveyEnter = () => { ); }; +type RequestState = "idle" | "working" | "sent" | "failed"; + +const Login = () => { + const [email, setEmail] = useState(""); + const [state, setState] = useState("idle"); + const bpuid = useAppSelector((state) => state.app.bpuid); + + // const dispatch = useAppDispatch(); + const submit = async (event: FormEvent) => { + event.preventDefault(); + setState("working"); + + try { + const response = await fetch("/auth/magic-link/request", { + method: "POST", + credentials: "include", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + email: email, + }), + }); + + if (!response.ok) throw new Error("Account-link request failed"); + + const body = (await response.json()) as { magic_link?: string }; + console.log(body.magic_link ?? null); + } catch { + setState("failed"); + } + }; + + return ( +
+

+ Please Login +

+ +
+ setEmail(event.target.value)} + placeholder="hello@jamesbillings67.com" + /> + +
+ + {state === "sent" && ( +

+ Check your email to login. +

+ )} + + {state === "failed" &&

Unable to send the link. Please try again.

} +
+ ); +}; + const Work = () => { const entered = useAppSelector((state) => state.app.currentBucketEntered); - const assignment_id = useAppSelector((state) => state.app.assignment_id); - - if (!assignment_id) { - return ( -

- No Assignment ID found. Please access this page through the Amazon - Mechanical Turk platform. -

- ); + // const assignment_id = useAppSelector((state) => state.app.assignment_id); + // if (!assignment_id) { + // return ( + //

+ // No Assignment ID found. Please access this page through the Amazon + // Mechanical Turk platform. + //

+ // ); + // } + + const { data: user, isLoading, isError } = useGetMeQuery(); + // const location = useLocation(); + + if (isLoading) return
Loading...
; + + if (isError || !user) { + return ; } return <>{entered ? : }; diff --git a/jb-ui/src/store.ts b/jb-ui/src/store.ts index 07cac9e..baf13b7 100644 --- a/jb-ui/src/store.ts +++ b/jb-ui/src/store.ts @@ -1,6 +1,8 @@ import appReducers from "@/models/appSlice"; import grlStatsReducers from "@/models/grlStatsSlice"; import grlEventsReducers from "@/models/grlEventsSlice"; +import { authApi } from "@/models/authAPI"; + import profilingQuestionsReducers from "@/models/profilingQuestionsSlice"; import type { Action, ThunkAction } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit"; @@ -8,10 +10,13 @@ import { configureStore } from "@reduxjs/toolkit"; export const store = configureStore({ reducer: { app: appReducers, + // auth: authReducers, + [authApi.reducerPath]: authApi.reducer, stats: grlStatsReducers, events: grlEventsReducers, profilingQuestions: profilingQuestionsReducers, }, + middleware: (getDefault) => getDefault().concat(authApi.middleware), }); // Infer the type of `store` diff --git a/jb/views/auth.py b/jb/views/auth.py index bf39b51..ce9c1e0 100644 --- a/jb/views/auth.py +++ b/jb/views/auth.py @@ -2,7 +2,7 @@ from typing import Annotated from urllib.parse import urlencode from fastapi import APIRouter, Depends, HTTPException, Response, status -from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse +from fastapi.responses import HTMLResponse, RedirectResponse from jb.api.auth import ( SESSION_COOKIE_NAME, @@ -119,7 +119,7 @@ def link_amt_account(body: AmtAccountLink) -> dict[str, str]: return {} -@auth_router.get("/link-amt/", response_class=HTMLResponse, include_in_schema=False) +@auth_router.get("/debug/", response_class=HTMLResponse, include_in_schema=False) def link_amt_account_landing_page( gr_api: Annotated[GRApiManager, Depends(get_gr_api_manager)], token: str | None = None, @@ -129,13 +129,15 @@ def link_amt_account_landing_page( # TODO! Try catch any of this, and if it fails, show the user a # TODO! failed HTML page. As of now, it shows them a failed JSON response. - if token is None: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="token is required", - ) - _response = RedirectResponse(url="/", status_code=status.HTTP_303_SEE_OTHER) - _exchange_amt_account_link(token=token, response=_response, gr_api=gr_api) + if settings.debug: + if token is None: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="token is required", + ) + + _response = RedirectResponse(url="/", status_code=status.HTTP_303_SEE_OTHER) + _exchange_amt_account_link(token=token, response=_response, gr_api=gr_api) return HTMLResponse( BASE_HTML, -- cgit v1.2.3 From 83821dff9984fb950e53f23baf99d7a74fb88abd Mon Sep 17 00:00:00 2001 From: Max Nanis Date: Sun, 13 Sep 2026 10:41:49 -0700 Subject: refrences to HIT removed. Still can't test. Basic CashoutMethod retrival until backup updated. use of the new Wallets endpoint. --- jb-ui/src/JBApp.tsx | 69 +++++++++++++++++++++++++++------ jb-ui/src/components/Redemption.tsx | 67 ++++++++++++++++++++++++++++++++ jb-ui/src/components/Wallet.tsx | 20 ++++++---- jb-ui/src/models/app.ts | 8 ++++ jb-ui/src/models/appSlice.ts | 30 ++++++++++++++ jb-ui/src/models/cashoutMethodsSlice.ts | 37 ++++++++++++++++++ jb-ui/src/pages/Preview.tsx | 8 ++-- jb-ui/src/pages/Result.tsx | 18 +++------ jb-ui/src/pages/Work.tsx | 33 +++++++--------- jb-ui/src/store.ts | 2 + 10 files changed, 239 insertions(+), 53 deletions(-) create mode 100644 jb-ui/src/components/Redemption.tsx create mode 100644 jb-ui/src/models/cashoutMethodsSlice.ts (limited to 'jb-ui/src/store.ts') diff --git a/jb-ui/src/JBApp.tsx b/jb-ui/src/JBApp.tsx index 6c31164..4870e9b 100644 --- a/jb-ui/src/JBApp.tsx +++ b/jb-ui/src/JBApp.tsx @@ -11,7 +11,11 @@ import { TaskStatusResponse, UserWalletBalance, UserWalletBalanceResponse, + UserLedgerWallets, + UserLedgerWalletAccountTypeEnum, + UserDisplayedWalletBalance, WalletApi, + CashoutMethodsResponse, } from "@/api_fsb"; import Footer from "@/components/Footer"; import { useAppDispatch } from "@/hooks"; @@ -20,8 +24,13 @@ import { useGetMeQuery } from "@/models/authAPI"; import { setAssignmentID, setProductUserID, - setTurkSubmitTo, + setUserDisplayedWalletBalance, + setUserWallet, + setUserAttemptCreditWallet, } from "@/models/appSlice"; + +import { addCashoutMethods } from "@/models/cashoutMethodsSlice"; + import { addEvent } from "@/models/grlEventsSlice"; import { addStatsData } from "@/models/grlStatsSlice"; import Home from "@/pages/Home"; @@ -50,6 +59,7 @@ 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 @@ -76,17 +86,16 @@ function QueryParamProcessor() { const { data: user, isLoading, isError } = useGetMeQuery(); 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 (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 @@ -97,6 +106,43 @@ function QueryParamProcessor() { 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) { @@ -125,8 +171,8 @@ function QueryParamProcessor() { const Layout = () => { const location = useLocation(); - const isWork = useMatch("/work*"); - const isPreview = useMatch("/preview*"); + const isWork = useMatch("/work/*"); + const isPreview = useMatch("/preview/*"); const isSpecialSubview = Boolean(isWork || isPreview); return ( @@ -152,6 +198,7 @@ const Layout = () => { > + diff --git a/jb-ui/src/components/Redemption.tsx b/jb-ui/src/components/Redemption.tsx new file mode 100644 index 0000000..0a91ab3 --- /dev/null +++ b/jb-ui/src/components/Redemption.tsx @@ -0,0 +1,67 @@ +import { clsx } from "clsx"; +import { useAppDispatch, useAppSelector } from "@/hooks"; +import { UpkQuestionChoice } from "@/api_fsb"; +import { useGetMeQuery } from "@/models/authAPI"; +import { ChevronRightIcon } from "lucide-react"; +import { KeyboardEvent, MouseEvent, useEffect, useRef, useState } from "react"; +import { useSelector } from "react-redux"; +import { cashoutMethodsSelectors } from "@/models/cashoutMethodsSlice"; + +const RedemptionHeader = () => { + const cashout_methods = useSelector(cashoutMethodsSelectors.selectAll); + + return ( + <> +

+ {/* {cashout_methods.length} Redemption Methods */} + 30+ Redemption Methods +

+ + ); +}; + +const RedemptionModalBody = () => { + return ( +
+
+ Paypal, Visa, Giftcards will be available. Finishing processing the + transfer from Amazon. +
+
+ ); +}; + +const Redemption = () => { + const dispatch = useAppDispatch(); + const { data: user, isLoading, isError } = useGetMeQuery(); + const [showRedemption, setShowRedemption] = useState(false); + + return ( +
+
setShowRedemption(!showRedemption)} + > + + +

+ {/* (Click to {showRedemption ? "hide" : "show"}) */} + Details within 24hr. +

+
+ + {showRedemption && } +
+ ); +}; + +export default Redemption; diff --git a/jb-ui/src/components/Wallet.tsx b/jb-ui/src/components/Wallet.tsx index 3f5c6a4..3bb23a9 100644 --- a/jb-ui/src/components/Wallet.tsx +++ b/jb-ui/src/components/Wallet.tsx @@ -54,7 +54,13 @@ const getBackgroundColor = (balance: number | undefined): string => { const WalletHeader = () => { const amount = - useAppSelector((state) => state.app.userWalletBalance)?.amount ?? 0; + useAppSelector((state) => state.app.userDisplayedWalletBalance?.amount) ?? + 0; + + const amount_string = + useAppSelector( + (state) => state.app.userDisplayedWalletBalance?.amount_string, + ) ?? "$0.00"; const bgStyle = typeof getBackgroundColor(amount) === "string" && @@ -77,13 +83,9 @@ const WalletHeader = () => { User Wallet: {amount >= 0 ? ( - - {`${formatCentsToUSD(Math.abs(amount))}`} - + {`${amount_string}`} ) : ( - - {`(${formatCentsToUSD(Math.abs(amount))})`} - + {`(${amount_string})`} )} @@ -93,6 +95,10 @@ const WalletHeader = () => { const WalletSummary = () => { const summary = useAppSelector((state) => state.app.userLedgerSummary); + const userWallet = useAppSelector((state) => state.app.userWallet); + + userWallet; + const survey_completes = summary?.bp_payment?.entry_count ?? 0; const survey_completes_f = (survey_completes ?? 0).toLocaleString("en-US"); diff --git a/jb-ui/src/models/app.ts b/jb-ui/src/models/app.ts index 4c3e69e..db54e0d 100644 --- a/jb-ui/src/models/app.ts +++ b/jb-ui/src/models/app.ts @@ -5,6 +5,8 @@ import { UserLedgerTransactionTypesSummary, UserLedgerTransactionsResponseTransactionsInner, OfferwallReason, + UserLedgerWallet, + UserDisplayedWalletBalance, } from "@/api_fsb"; import { PaginationState } from "@tanstack/react-table"; @@ -33,6 +35,12 @@ export interface App { userLedgerTxCount?: number; userLedgerTxs: UserLedgerTransactionsResponseTransactionsInner[]; + // --- new approach + userDisplayedWalletBalance?: UserDisplayedWalletBalance; + userWallet?: UserLedgerWallet; + userAttemptCreditWallet?: UserLedgerWallet; + // --- + txPagination: PaginationState; txTotalItems?: number; txTotalPages?: number; diff --git a/jb-ui/src/models/appSlice.ts b/jb-ui/src/models/appSlice.ts index 46c6a2f..42a776e 100644 --- a/jb-ui/src/models/appSlice.ts +++ b/jb-ui/src/models/appSlice.ts @@ -4,6 +4,8 @@ import { UserLedgerTransactionsResponseTransactionsInner, UserLedgerTransactionTypesSummary, UserWalletBalance, + UserDisplayedWalletBalance, + UserLedgerWallet, OfferwallReason, } from "@/api_fsb"; import { App } from "@/models/app"; @@ -26,6 +28,12 @@ const initialState: App = { userLedgerTxCount: undefined, userLedgerTxs: [], + // --- new approach + userDisplayedWalletBalance: undefined, + userWallet: undefined, + userAttemptCreditWallet: undefined, + // --- + txPagination: { pageIndex: 0, pageSize: 10 }, txTotalItems: undefined, txTotalPages: undefined, @@ -91,6 +99,24 @@ const appSlice = createSlice({ state.userWalletBalance = action.payload; }, + // --- New approach --- + setUserDisplayedWalletBalance( + state, + action: PayloadAction, + ) { + state.userDisplayedWalletBalance = action.payload; + }, + + setUserWallet(state, action: PayloadAction) { + state.userWallet = action.payload; + }, + + setUserAttemptCreditWallet(state, action: PayloadAction) { + state.userAttemptCreditWallet = action.payload; + }, + + // --- --- + setUserLedgerSummary( state, action: PayloadAction, @@ -138,6 +164,10 @@ export const { setUserLedgerSummary, setUserLedgerTxs, + setUserDisplayedWalletBalance, + setUserWallet, + setUserAttemptCreditWallet, + setTxPagination, setTxTotalItems, setTxTotalPages, diff --git a/jb-ui/src/models/cashoutMethodsSlice.ts b/jb-ui/src/models/cashoutMethodsSlice.ts new file mode 100644 index 0000000..92c03da --- /dev/null +++ b/jb-ui/src/models/cashoutMethodsSlice.ts @@ -0,0 +1,37 @@ +import { CashoutMethodOut } from "@/api_fsb"; +import type { RootState } from "@/store"; +import { createSlice, createEntityAdapter } from "@reduxjs/toolkit"; + +// Entity adapter for normalized storage +const cashoutMethodsAdapter = createEntityAdapter({ + selectId: (model: CashoutMethodOut) => model.id!, + sortComparer: (a, b) => { + return (b.min_value ?? 0) - (a.min_value ?? 0); + }, +}); + +const cashoutMethodsSlice = createSlice({ + name: "cashoutMethods", + initialState: cashoutMethodsAdapter.getInitialState(), + + reducers: { + addCashoutMethod: cashoutMethodsAdapter.addOne, + addCashoutMethods: cashoutMethodsAdapter.addMany, + upsertCashoutMethod: cashoutMethodsAdapter.upsertOne, // Add or Update + }, +}); + +export const { addCashoutMethod, addCashoutMethods, upsertCashoutMethod } = + cashoutMethodsSlice.actions; + +export const cashoutMethodsSelectors = cashoutMethodsAdapter.getSelectors( + (state: RootState) => state.cashoutMethods, +); + +export const selectAllCashoutMethods = ( + state: RootState, +): CashoutMethodOut[] => { + return cashoutMethodsSelectors.selectAll(state) ?? []; +}; + +export default cashoutMethodsSlice.reducer; diff --git a/jb-ui/src/pages/Preview.tsx b/jb-ui/src/pages/Preview.tsx index 85e49f2..900621e 100644 --- a/jb-ui/src/pages/Preview.tsx +++ b/jb-ui/src/pages/Preview.tsx @@ -378,10 +378,10 @@ const Preview = () => { Get paid to take surveys. Our algorithm attempts to pair you with the highest paying survey available at the moment (right now, the highest paying survey is {survey_max_cpi_f}) that you are eligible - for, each attempt is a valid HIT. Try as many as you can, our system - will self regulate you: we want to ensure you have a high chance of - being paired with a survey based on what surveys are available, as - their availability constantly changes. + for. Try as many as you can, our system will self regulate you: we + want to ensure you have a high chance of being paired with a survey + based on what surveys are available, as their availability + constantly changes.

diff --git a/jb-ui/src/pages/Result.tsx b/jb-ui/src/pages/Result.tsx index 477f77e..6385bc7 100644 --- a/jb-ui/src/pages/Result.tsx +++ b/jb-ui/src/pages/Result.tsx @@ -21,9 +21,7 @@ export const Complete = () => {

{ts?.user_payout_string}

-

- You may close this tab and return to submit the HIT -

+

You may close this tab

); }; @@ -35,9 +33,7 @@ export const Enter = () => {

You're currently in the Survey

-

- You may close this tab and return to submit the HIT -

+

You may close this tab

); }; @@ -50,13 +46,11 @@ export const InComplete = () => { return ( <> -

HIT Complete

+

Attempt Complete

Survey terminated the attempt.

-

- You may close this tab and return to submit the HIT -

+

You may close this tab

); }; @@ -68,9 +62,7 @@ export const Unknown = () => {

You're not currently eligible for any Surveys

-

- You may close this tab and return to submit the HIT -

+

You may close this tab

); }; diff --git a/jb-ui/src/pages/Work.tsx b/jb-ui/src/pages/Work.tsx index dbe3601..50ed930 100644 --- a/jb-ui/src/pages/Work.tsx +++ b/jb-ui/src/pages/Work.tsx @@ -1,4 +1,5 @@ import { useGetMeQuery } from "@/models/authAPI"; +import { Link } from "react-router-dom"; import { BucketTask, OfferwallApi, @@ -183,7 +184,7 @@ const Report = ({ onClose }: { onClose: () => void }) => { hover:cursor-pointer hover:bg-rose-400 hover:text-rose-50" onClick={clicked_submit} > - Submit and Complete HIT + Submit and Complete Attempt @@ -306,7 +307,7 @@ const SurveyMonitor = () => { } // This is if they have finished a survey complete and it resulted in a - // COMPLETE or a INCOMPLETE (doesn't matter). They can now submit the HIT. + // COMPLETE or a INCOMPLETE (doesn't matter). They can now submit the Attempt. // // 2 - INCOMPLETE, 3 - COMPLETE return ( @@ -326,7 +327,7 @@ const SurveyMonitor = () => { py-2 text-zinc-500 text-md font-medium text-center" > - You may now submit the HIT. + You may now submit the attempt.

)} @@ -351,7 +352,9 @@ const SurveyMonitor = () => { pt-0 pb-4 text-red-950 text-sm font-semibold text-center" > - Please return the HIT to avoid having your assignment rejected. + + Click to Refresh and Try Again +

@@ -368,7 +371,7 @@ const SurveyMonitor = () => { hover:cursor-pointer hover:bg-emerald-400 hover:text-emerald-50" onClick={() => setShowComplete(true)} > - Submit HIT + Finish Attempt