aboutsummaryrefslogtreecommitdiff
path: root/jb-ui/src/pages/Preview.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'jb-ui/src/pages/Preview.tsx')
-rw-r--r--jb-ui/src/pages/Preview.tsx142
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;