import { m, Variants } from "framer-motion"; import Link from "next/link"; import { ReactElement, useEffect, useState } from "react"; import Loading from "../../components/common/Loading"; import UserJSONEntry from "../../interfaces/UserJSONEntry"; import DashLayout from "../../layouts/DashLayout"; function Ranking() { const [sortBy, setSortBy] = useState("netWorth"); const [sortAsc, setSortAsc] = useState(false); const [fakeData, setFakeData] = useState([]); const [dataLoaded, setDataLoaded] = useState(false); useEffect(() => { setDataLoaded(false); // fetch data from api on change to sort method fetch(`/api/fakeUsers?s=${sortBy}&a=${sortAsc}`) .then((res) => res.json()) .then((data) => { setFakeData(data.data); setDataLoaded(true); }); }, [sortBy, sortAsc]); const SortSVG = (props: { sortType: string; children?: ReactElement }) => { // if not current sort, return a line, otherwise return an arrow corresponding to sortAsc if (sortBy != props.sortType) { return ( ); } return ( ); }; const setSortMethod = (sortType: string) => { // if same sort, toggle asc // a change in sort means asc should be false for intuitive behavior if (sortBy == sortType) { setSortAsc(!sortAsc); } else { setSortAsc(false); setSortBy(sortType); } }; return ( <>
{/* hidden if smaller than lg */} top investors {/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */} {/* Column names and arrows */}

#

setSortMethod("name")} >

Name

setSortMethod("netWorth")} >

Assets

setSortMethod("points")} >

Points

setSortMethod("shares")} >

Shares

setSortMethod("dailyChangePercent")} >

Daily

{ // if data is not loaded, loading div !dataLoaded ? (

This is fake delay :)

) : ( { // generate table rows fakeData.map((entry: UserJSONEntry, index: number) => { // if daily change is negative, make it red let changeClass = " text-lime-500"; if (entry.daily_change_percent < 0) { changeClass = " text-red-500"; } return (

{index + 1}

{entry.name}

{entry.net_worth.toLocaleString("en-US")}

{entry.points.toLocaleString("en-US")}

{entry.shares.toLocaleString("en-US")}

{( Math.round(entry.daily_change_percent * 1000) / 10 ).toFixed(1) + "%"}

); }) }
) }
); } // header animation if needed const headerVariants: Variants = { initial: { opacity: 0, y: -100, }, animate: { opacity: 1, y: 0, transition: { delay: 1.0, duration: 1.0, type: "spring", bounce: 0.5, stiffness: 60, }, }, }; // table container animation const rankingCardVariants: Variants = { initial: { opacity: 0, y: 300, }, animate: { opacity: 1, y: 0, transition: { duration: 3, delayChildren: 0.5, type: "spring", bounce: 0.5, stiffness: 40, }, }, exit: { opacity: 0, y: 175, transition: { duration: 0.5, }, }, }; const rankingDataContainerVariants: Variants = { initial: { opacity: 0, }, animate: { opacity: 1, transition: { duration: 1.0, staggerChildren: 0.045, }, }, exit: { opacity: 0, y: 150, transition: { duration: 0.5, }, }, }; const rankingDataLineVariants: Variants = { initial: { opacity: 0, }, animate: { opacity: 1, transition: { duration: 1.0, }, }, }; Ranking.getLayout = function getLayout(page: ReactElement) { const metaTags = { title: "Ranking - toffee", description: "Top investors on toffee", }; return ( {page} ); }; export default Ranking;