diff options
| author | stuppie | 2026-09-07 08:53:34 -0600 |
|---|---|---|
| committer | stuppie | 2026-09-07 08:53:34 -0600 |
| commit | 27c2e8fee5c604d64cd06a37afc62db0252f8370 (patch) | |
| tree | 2e3b4529738e2c1d24dd444a22d04eaa8db1bc31 /jb-ui | |
| parent | 81cf8de5dbcb530718eb8687b5bfab44517a6757 (diff) | |
| download | amt-jb-27c2e8fee5c604d64cd06a37afc62db0252f8370.tar.gz amt-jb-27c2e8fee5c604d64cd06a37afc62db0252f8370.zip | |
add LinkAmtAccount.tsx
Diffstat (limited to 'jb-ui')
| -rw-r--r-- | jb-ui/src/pages/LinkAmtAccount.tsx | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/jb-ui/src/pages/LinkAmtAccount.tsx b/jb-ui/src/pages/LinkAmtAccount.tsx new file mode 100644 index 0000000..0c9dab3 --- /dev/null +++ b/jb-ui/src/pages/LinkAmtAccount.tsx @@ -0,0 +1,73 @@ +import { type FormEvent, useState } from "react"; + +import { Button } from "@/components/ui/button"; + +type RequestState = "idle" | "working" | "sent" | "failed" | "missing-worker"; + +const LinkAmtAccount = function () { + const [email, setEmail] = useState(""); + const [state, setState] = useState<RequestState>("idle"); + const [mockLink, setMockLink] = useState<string | null>(null); + const amtWorkerId = new URLSearchParams(window.location.search).get("workerId"); + + const submit = async (event: FormEvent<HTMLFormElement>) => { + event.preventDefault(); + if (!amtWorkerId) { + setState("missing-worker"); + return; + } + + setState("working"); + setMockLink(null); + try { + const response = await fetch("/auth/link-amt/request", { + method: "POST", + credentials: "include", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ + "email": email, + "amt_worker_id": amtWorkerId, + }), + }); + if (!response.ok) throw new Error("Account-link request failed"); + const body = await response.json() as {magic_link?: string}; + setMockLink(body.magic_link ?? null); + setState("sent"); + } catch { + setState("failed"); + } + }; + + return ( + <main className="flex min-h-screen items-center justify-center bg-zinc-200 p-4"> + <section className="w-full max-w-md space-y-4 rounded-lg bg-white p-6 shadow-lg"> + <h1 className="text-xl font-semibold">Link your MTurk account</h1> + <p>Enter the email address you want to use for James Billings.</p> + <form className="space-y-4" onSubmit={submit}> + <input + className="w-full rounded-md border px-3 py-2" + type="email" + autoComplete="email" + required + value={email} + onChange={(event) => setEmail(event.target.value)} + placeholder="you@example.com" + /> + <Button type="submit" disabled={state === "working"}> + {state === "working" ? "Sending…" : "Send link"} + </Button> + </form> + {state === "sent" && <p>Check your email to finish linking your account.</p>} + {state === "failed" && <p>Unable to send the link. Please try again.</p>} + {state === "missing-worker" && <p>This page is missing your MTurk worker ID.</p>} + {mockLink && ( + <p> + Development link: <a className="underline" href={mockLink}>continue</a> + </p> + )} + </section> + </main> + ); +}; + +export default LinkAmtAccount; |
