import { Leaderboard, LeaderboardApi, LeaderboardCode, LeaderboardFrequency, LeaderboardRow, } from "@/api_fsb"; 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 ThreeButtonToggle = ({ selected, onChange }: FrequencyButtonsProps) => { const buttons = [ { label: 'Day', value: LeaderboardFrequency.Daily }, { label: 'Week', value: LeaderboardFrequency.Weekly }, { label: 'Month', value: LeaderboardFrequency.Monthly }, ]; // rounded-l return (
{buttons.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 = useAppSelector(state => state.app.bpuid) const bpuid = undefined useEffect(() => { new LeaderboardApi().timespanLeaderboardProductIdLeaderboardTimespanBoardCodeGet( bpid, LeaderboardCode.CompleteCount, frequency, "us", bpuid, // 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}`; } 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 week.
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 week.
Rank Completes User
{dataItem.rank ?? showSmartRank(dataItem, index, completes?.rows)} {dataItem.value} {truncate(dataItem.bpuid, 6, "*****").toUpperCase()}
); }; // 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, 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.

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.

); }; export default Preview;