diff options
| author | Max Nanis | 2026-09-12 14:30:31 -0700 |
|---|---|---|
| committer | Max Nanis | 2026-09-12 14:30:31 -0700 |
| commit | b2261f9101480afb31322cf620f028cdade0671c (patch) | |
| tree | 0bcba3696b0566138145d80a8fcb9230b172f2c5 /jb-ui/src/pages/Preview.tsx | |
| parent | f82ac61b6a044467ab37c0645c3fe99b40bedfc5 (diff) | |
| download | amt-jb-b2261f9101480afb31322cf620f028cdade0671c.tar.gz amt-jb-b2261f9101480afb31322cf620f028cdade0671c.zip | |
new landing page that combines leaderboard + login. fixing worker_id assignment, it'll still be needed until transfer is finished
Diffstat (limited to 'jb-ui/src/pages/Preview.tsx')
| -rw-r--r-- | jb-ui/src/pages/Preview.tsx | 142 |
1 files changed, 117 insertions, 25 deletions
diff --git a/jb-ui/src/pages/Preview.tsx b/jb-ui/src/pages/Preview.tsx index 1926975..85e49f2 100644 --- a/jb-ui/src/pages/Preview.tsx +++ b/jb-ui/src/pages/Preview.tsx @@ -5,6 +5,7 @@ import { LeaderboardFrequency, LeaderboardRow, } from "@/api_fsb"; +import { Button } from "@/components/ui/button"; import { useAppSelector } from "@/hooks"; import { bpid, formatCentsToUSD, truncate } from "@/lib/utils"; import { activeSurveys, activeUsers, maxPayout } from "@/models/grlStatsSlice"; @@ -244,6 +245,98 @@ export const Leaderboards = () => { ); }; +type RequestState = "idle" | "working" | "failed"; + +const LoginForm = function ({ onSubmitSuccess }) { + const [email, setEmail] = useState(""); + const [state, setState] = useState<RequestState>("idle"); + + // const dispatch = useAppDispatch(); + const submit = async (event: FormEvent<HTMLFormElement>) => { + 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); + onSubmitSuccess(); + } catch { + setState("failed"); + } + }; + + return ( + <> + <form className="w-full" onSubmit={submit}> + <div className="flex items-center border-b-4 border-blue-700 py-2"> + <input + className="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none font-semibold" + type="email" + autoComplete="email" + required + value={email} + onChange={(event) => setEmail(event.target.value)} + placeholder="hello@jamesbillings67.com" + aria-label="Email address" + /> + + <button + className="flex-shrink-0 bg-blue-700 hover:bg-blue-800 text-white py-1 px-2 rounded cursor-pointer font-semibold" + type="submit" + disabled={state === "working"} + > + {state === "working" ? "Sending…" : "Login / Signup"} + </button> + </div> + </form> + + {state === "failed" && <p>Unable to send the link. Please try again.</p>} + </> + ); +}; + +const LoginSent = function () { + return ( + <div className="my-1"> + <h2 + className=" + bg-emerald-400 rounded py-2 + text-white text-l font-semibold text-center" + > + Please check your email. + </h2> + <p className="text-slate-800 text-xs font-semibold text-center my-1 py-2"> + If you don't recieve anything, please check your spam folder, or try + again shortly. + </p> + </div> + ); +}; + +const Login = () => { + const [submitted, setSubmitted] = useState(false); + + return ( + <> + {submitted ? ( + <LoginSent /> + ) : ( + <LoginForm onSubmitSuccess={() => setSubmitted(true)} /> + )} + </> + ); +}; + // Preview Component const Preview = () => { /** @@ -267,33 +360,32 @@ const Preview = () => { ); return ( - <div className="max-h-[calc(100vh-10rem)] overflow-y-auto"> - <div className="bg-zinc-100 rounded py-2 m-0"> - <p className="text-center text-sm italic text-zinc-600"> - {users_f} people are actively attempting {surveys_f} available surveys - right now. - </p> - </div> + <> + <Login /> + + <div className="max-h-[calc(100vh-10rem)] overflow-y-auto"> + <div className="bg-zinc-100 rounded py-2 m-0"> + <p className="text-center text-sm italic text-zinc-600"> + {users_f} people are actively attempting {surveys_f} available + surveys right now. + </p> + </div> - <Leaderboards /> - - <div className="bg-zinc-100 rounded py-2 px-6 m-0 text-xs text-center"> - <p className="py-1"> - 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. - </p> - <p className="py-1"> - Each HIT is paid when you attempt to take a survey and if you complete - the survey, you will be awarded a bonus equal to that in which the - survey pays out. - </p> + <Leaderboards /> + + <div className="bg-zinc-100 rounded py-2 px-6 m-0 text-xs text-center"> + <p className="py-1"> + 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. + </p> + </div> </div> - </div> + </> ); }; export default Preview; |
