import { Leaderboard, LeaderboardApi, LeaderboardCode, 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"; import { clsx } from "clsx"; import moment from "moment"; import { useEffect, useState } from "react"; const showSmartRank = ( item: LeaderboardRow, index: number, items: LeaderboardRow[] | undefined, ): boolean => { /** * Smart rank calculation - this determines if we should show the rank * value. It's confusing to show people that multiple individuals ranked * in the same place, so this will only display the next ranked value, eg: * * - 1st * - ___ * - 3rd * - ___ * - ___ * - 6th * * @returns number */ if (!items) return false; const thisRank = item.rank; if (index >= 1) { const prevRank = items[index - 1].rank; if (thisRank === prevRank) { return false; } } return true; }; interface FrequencyButtonsProps { selected: LeaderboardFrequency; onChange: (frequency: LeaderboardFrequency) => void; } const frequency_map = [ { label: "Day", value: LeaderboardFrequency.Daily }, { label: "Week", value: LeaderboardFrequency.Weekly }, { label: "Month", value: LeaderboardFrequency.Monthly }, ]; const ThreeButtonToggle = ({ selected, onChange }: FrequencyButtonsProps) => { return (
{frequency_map.map((button, idx) => ( ))}
); }; // Leaderboards Component export const Leaderboards = () => { /** * Leaderboards do not do any caching, or better state management. This is okay because * the API is handled to take it. However, it can easily handled better client * side rather than making the * **/ const [frequency, setFrequency] = useState( LeaderboardFrequency.Daily, ); const [payouts, setPayouts] = useState(null); const [completes, setCompletes] = useState(null); const bpuid = undefined; useEffect(() => { new LeaderboardApi() .timespanLeaderboardProductIdLeaderboardTimespanBoardCodeGet( bpid, LeaderboardCode.CompleteCount, frequency, "us", bpuid, undefined, // within_time 10, ) .then((res) => { setCompletes(res.data.leaderboard as Leaderboard); }); new LeaderboardApi() .timespanLeaderboardProductIdLeaderboardTimespanBoardCodeGet( bpid, LeaderboardCode.SumUserPayout, frequency, "us", bpuid, undefined, 10, ) .then((res) => { setPayouts(res.data.leaderboard as Leaderboard); }); }, [frequency]); let dateRange = " - "; if (completes) { const start = moment(completes?.start_timestamp * 1000).format( "MMM Do, ha", ); const end = moment(completes?.end_timestamp * 1000).format( "MMM Do, h:mm:ssa", ); //dateRange = `${start} – ${end} (${completes?.timezone_name})`; dateRange = `${start} – ${end}`; } const freq_label = frequency_map .find((f) => f.value === frequency) ?.label.toLocaleLowerCase(); return (
{/* Left spacer (hidden on small screens) */}
{/* Centered text */}

Leaderboards

{/* Right-aligned button group */}

{dateRange}

{payouts?.rows?.map((dataItem: LeaderboardRow) => ( ))}
Most earned in the past {freq_label}.
Rank Bonus User
{dataItem.rank} {formatCentsToUSD(dataItem.value)} {truncate(dataItem.bpuid, 6, "*****").toUpperCase()}
{completes?.rows?.map((dataItem: LeaderboardRow, index: number) => ( ))}
Top completes in the past {freq_label}.
Rank Completes User
{dataItem.rank ?? showSmartRank(dataItem, index, completes?.rows)} {dataItem.value} {truncate(dataItem.bpuid, 6, "*****").toUpperCase()}
); }; type RequestState = "idle" | "working" | "failed"; const LoginForm = function ({ onSubmitSuccess }) { const [email, setEmail] = useState(""); const [state, setState] = useState("idle"); // 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); onSubmitSuccess(); } catch { setState("failed"); } }; return ( <>
setEmail(event.target.value)} placeholder="hello@jamesbillings67.com" aria-label="Email address" />
{state === "failed" &&

Unable to send the link. Please try again.

} ); }; const LoginSent = function () { return (

Please check your email.

If you don't recieve anything, please check your spam folder, or try again shortly.

); }; const Login = () => { const [submitted, setSubmitted] = useState(false); return ( <> {submitted ? ( ) : ( setSubmitted(true)} /> )} ); }; // Preview Component const Preview = () => { /** * * @returns {JSX.Element} */ const users = useAppSelector((state) => activeUsers(state)); const users_f: string = users?.toLocaleString() ?? " – "; const surveys = useAppSelector((state) => activeSurveys(state)); const surveys_f: string = surveys?.toLocaleString() ?? " – "; const survey_max_cpi = useAppSelector((state) => maxPayout(state)); const formatter = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }); const survey_max_cpi_f: string = formatter.format( (survey_max_cpi ?? 0) / 100, ); return ( <>

{users_f} people are actively attempting {surveys_f} available surveys right now.

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. 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.

); }; export default Preview;