Merge pull request #6 from Invest-Bot/dev
Merge Dev: Finalize Fake Data Sorting
This commit is contained in:
commit
7763757c8e
7 changed files with 234 additions and 121 deletions
|
@ -6,7 +6,7 @@ function NavBar() {
|
|||
return (
|
||||
<div className="m-3">
|
||||
<m.div
|
||||
className="flex min-h-[5rem] w-full flex-row items-center justify-between rounded-2xl bg-zinc-800 p-1 lg:h-full lg:w-24 lg:flex-col"
|
||||
className="flex min-h-[5rem] w-full flex-row items-center justify-between rounded-2xl bg-zinc-800 bg-opacity-70 p-1 lg:h-full lg:w-24 lg:flex-col"
|
||||
variants={navContainerVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
|
|
|
@ -18,7 +18,13 @@ function DashLayout(props: DashLayoutProps) {
|
|||
// get the current route for animation purposes
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<m.div
|
||||
className="bg-gradient-to-t from-zinc-900 to-[#202737b6]"
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
variants={containerVariants}
|
||||
>
|
||||
<Head>
|
||||
<title>Dashboard - InvestBot</title>
|
||||
<meta name="description" content="Dashboard statistics for InvestBot" />
|
||||
|
@ -57,7 +63,7 @@ function DashLayout(props: DashLayoutProps) {
|
|||
</AnimatePresence>
|
||||
</LazyMotion>
|
||||
</div>
|
||||
</>
|
||||
</m.div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,12 @@ function HomeLayout(props: HomeLayoutProps) {
|
|||
// get the current route for animation purposes
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<m.div
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
variants={containerVariants}
|
||||
>
|
||||
<Head>
|
||||
<title>InvestBot</title>
|
||||
<meta name="description" content="Serving anny's community est. 2022" />
|
||||
|
@ -59,7 +64,7 @@ function HomeLayout(props: HomeLayoutProps) {
|
|||
</m.div>
|
||||
</AnimatePresence>
|
||||
</LazyMotion>
|
||||
</>
|
||||
</m.div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import "../styles/globals.css";
|
|||
import type { ReactElement, ReactNode } from "react";
|
||||
import type { NextPage } from "next";
|
||||
import type { AppProps } from "next/app";
|
||||
import { AnimatePresence, domAnimation, LazyMotion } from "framer-motion";
|
||||
|
||||
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
||||
getLayout?: (page: ReactElement) => ReactNode;
|
||||
|
@ -15,5 +16,11 @@ export default function App({ Component, pageProps }: AppPropsWithLayout) {
|
|||
// Use the layout defined at the page level, if available
|
||||
const getLayout = Component.getLayout ?? ((page) => page);
|
||||
|
||||
return getLayout(<Component {...pageProps} />);
|
||||
return (
|
||||
<LazyMotion features={domAnimation}>
|
||||
<AnimatePresence mode="wait" initial={false}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</AnimatePresence>
|
||||
</LazyMotion>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ export default async function handler(
|
|||
res: NextApiResponse<Data>
|
||||
) {
|
||||
const sortBy = req.query.s ? (req.query.s as string) : undefined;
|
||||
const sortAsc = req.query.a ? (req.query.a as string) : undefined;
|
||||
|
||||
let data = fakeData;
|
||||
if (sortBy) {
|
||||
|
@ -25,6 +26,10 @@ export default async function handler(
|
|||
} else if (sortBy === "name") {
|
||||
data = data.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
if (sortAsc === "true") {
|
||||
// slow but only needed for temporary fake data anyway
|
||||
data = data.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ data });
|
||||
|
@ -48,7 +53,7 @@ const fakeData: fakeDataEntry[] = [
|
|||
points: 70, /// uninvested points
|
||||
shares: 20,
|
||||
dailyChange: -500,
|
||||
dailyChangePercent: -0.523,
|
||||
dailyChangePercent: -0.0498504486540378863409770687936,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
|
@ -57,7 +62,7 @@ const fakeData: fakeDataEntry[] = [
|
|||
points: 10020,
|
||||
shares: 200,
|
||||
dailyChange: 5420,
|
||||
dailyChangePercent: 0.14,
|
||||
dailyChangePercent: 0.0379259673920649359736897347981,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
@ -70,138 +75,138 @@ const fakeData: fakeDataEntry[] = [
|
|||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "SecondSock",
|
||||
name: "SecondSockSan",
|
||||
netWorth: 153495,
|
||||
points: 15020,
|
||||
shares: 20,
|
||||
dailyChange: 5432,
|
||||
dailyChangePercent: 0.104,
|
||||
dailyChange: -10432,
|
||||
dailyChangePercent: -0.06796312583471774324896576435715,
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
name: "Ente",
|
||||
name: "e__n__t__e",
|
||||
netWorth: 429481824,
|
||||
points: 1002022,
|
||||
shares: 94214,
|
||||
dailyChange: 3294444224,
|
||||
dailyChangePercent: 0.94,
|
||||
dailyChange: 329444422,
|
||||
dailyChangePercent: 4.2932124926634939999741296760186,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "ObnoxiouslyLongNameWICKED",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "luckytohavefoundyou14252",
|
||||
netWorth: 8024,
|
||||
points: 423,
|
||||
shares: 4,
|
||||
dailyChange: 9,
|
||||
dailyChangePercent: 0.00112163509471585244267198404786,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "ZeroxZerich",
|
||||
netWorth: 842190,
|
||||
points: 88542,
|
||||
shares: 532,
|
||||
dailyChange: -10219,
|
||||
dailyChangePercent: -0.01213384153219582279533121979601,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "joeeyo",
|
||||
netWorth: 10000000,
|
||||
points: 9999979,
|
||||
shares: 1,
|
||||
dailyChange: 1,
|
||||
dailyChangePercent: 0.0000001,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "dd_maru",
|
||||
netWorth: 10328421,
|
||||
points: 328421,
|
||||
shares: 252,
|
||||
dailyChange: 85192,
|
||||
dailyChangePercent: 0.00824830823607984221402284047097,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "Goldeneye128",
|
||||
netWorth: 58292,
|
||||
points: 6521,
|
||||
shares: 63,
|
||||
dailyChange: -1942,
|
||||
dailyChangePercent: -0.03331503465312564331297605160228,
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "lilpastatv",
|
||||
netWorth: 7328919,
|
||||
points: 40,
|
||||
shares: 93,
|
||||
dailyChange: 921821,
|
||||
dailyChangePercent: 0.12577857662228222197571019682439,
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "domiswitch",
|
||||
netWorth: 43290,
|
||||
points: 5002,
|
||||
shares: 15,
|
||||
dailyChange: 2429,
|
||||
dailyChangePercent: 0.05610995610995610995610995610996,
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "minosura",
|
||||
netWorth: 904328,
|
||||
points: 32901,
|
||||
shares: 83,
|
||||
dailyChange: 94821,
|
||||
dailyChangePercent: 0.10485244291894091524314186887943,
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "scienceteam_member",
|
||||
netWorth: 34894,
|
||||
points: 958,
|
||||
shares: 5,
|
||||
dailyChange: -7964,
|
||||
dailyChangePercent: -0.22823408035765461110792686421734,
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "witchdev",
|
||||
netWorth: 94382912,
|
||||
points: 8532,
|
||||
shares: 329,
|
||||
dailyChange: -421,
|
||||
dailyChangePercent: -0.0000044605531984433792422085896,
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "justone123879",
|
||||
netWorth: 8889123,
|
||||
points: 86333,
|
||||
shares: 153,
|
||||
dailyChange: 53289,
|
||||
dailyChangePercent: 0.00599485461051669551653183334284,
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "marcelr_",
|
||||
netWorth: 400329,
|
||||
points: 39291,
|
||||
shares: 52,
|
||||
dailyChange: 1329,
|
||||
dailyChangePercent: 0.00331976948959480827019776234047,
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
name: "User",
|
||||
netWorth: 0,
|
||||
points: 100,
|
||||
shares: 0,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
name: "fossabot",
|
||||
netWorth: 20005,
|
||||
points: 0,
|
||||
shares: 1,
|
||||
dailyChange: -31042,
|
||||
dailyChangePercent: -1.5517120719820044988752811797051,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -17,31 +17,31 @@ function Dashboard() {
|
|||
animate="animate"
|
||||
>
|
||||
<m.div
|
||||
className="col-span-1 m-2 rounded-2xl bg-zinc-800 p-3"
|
||||
className="col-span-1 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3"
|
||||
variants={gridItemVariants}
|
||||
>
|
||||
1
|
||||
</m.div>
|
||||
<m.div
|
||||
className="col-span-1 row-span-3 m-2 rounded-2xl bg-zinc-800 p-3 lg:col-span-3 lg:row-span-1"
|
||||
className="col-span-1 row-span-3 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3 lg:col-span-3 lg:row-span-1"
|
||||
variants={gridItemVariants}
|
||||
>
|
||||
2
|
||||
</m.div>
|
||||
<m.div
|
||||
className="col-span-1 m-2 rounded-2xl bg-zinc-800 p-3"
|
||||
className="col-span-1 m-2 rounded-2xl bg-zinc-800 bg-opacity-80 p-3"
|
||||
variants={gridItemVariants}
|
||||
>
|
||||
3
|
||||
</m.div>
|
||||
<m.div
|
||||
className="col-span-1 row-span-4 m-2 rounded-2xl bg-zinc-800 p-3 lg:col-span-4 lg:row-span-1"
|
||||
className="col-span-1 row-span-4 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3 lg:col-span-4 lg:row-span-1"
|
||||
variants={gridItemVariants}
|
||||
>
|
||||
4
|
||||
</m.div>
|
||||
<m.div
|
||||
className="col-span-1 m-2 rounded-2xl bg-zinc-800 p-3"
|
||||
className="col-span-1 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3"
|
||||
variants={gridItemVariants}
|
||||
>
|
||||
5
|
||||
|
|
|
@ -6,15 +6,75 @@ import { fakeDataEntry } from "../api/fakeRanking";
|
|||
|
||||
function Ranking() {
|
||||
const [sortBy, setSortBy] = useState("netWorth");
|
||||
const [sortAsc, setSortAsc] = useState(false);
|
||||
const [fakeData, setFakeData] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch(`/api/fakeRanking?s=${sortBy}`)
|
||||
// fetch data from api on change to sort method
|
||||
fetch(`/api/fakeRanking?s=${sortBy}&a=${sortAsc}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setFakeData(data.data);
|
||||
});
|
||||
}, [sortBy]);
|
||||
}, [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 (
|
||||
<m.svg
|
||||
className="ml-2"
|
||||
origin="center"
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 6 6"
|
||||
x={0}
|
||||
y={0}
|
||||
>
|
||||
<m.line
|
||||
x1="1"
|
||||
y1="3"
|
||||
x2="5"
|
||||
y2="3"
|
||||
stroke="white"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</m.svg>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<m.svg
|
||||
className="ml-2"
|
||||
origin="center"
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 330 330"
|
||||
x={0}
|
||||
y={0}
|
||||
// if asc, rotate 180
|
||||
animate={{ rotate: sortAsc ? 180 : 0 }}
|
||||
>
|
||||
<m.path
|
||||
d="M325.607,79.393c-5.857-5.857-15.355-5.858-21.213,0.001l-139.39,139.393L25.607,79.393 c-5.857-5.857-15.355-5.858-21.213,0.001c-5.858,5.858-5.858,15.355,0,21.213l150.004,150c2.813,2.813,6.628,4.393,10.606,4.393 s7.794-1.581,10.606-4.394l149.996-150C331.465,94.749,331.465,85.251,325.607,79.393z"
|
||||
fill="white"
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</m.svg>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<>
|
||||
|
@ -37,37 +97,64 @@ function Ranking() {
|
|||
</m.h1>
|
||||
{/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */}
|
||||
<m.div
|
||||
className="text-md inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 backdrop-blur sm:text-xl"
|
||||
className="text-md inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 sm:text-xl"
|
||||
variants={rankingCardVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
>
|
||||
<m.div className="inline-grid w-full grid-flow-col grid-cols-[0.75fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-400 px-5 pb-3 text-right text-gray-300 md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]">
|
||||
<m.h1 className="text-left md:text-center">#</m.h1>
|
||||
<m.h1
|
||||
className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left"
|
||||
onClick={() => setSortBy("name")}
|
||||
{/* Column names and arrows */}
|
||||
<div className="inline-grid w-full grid-flow-col grid-cols-[0.75fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-400 px-5 pb-3 text-right text-gray-300 md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]">
|
||||
<h1 className="text-left md:text-center">#</h1>
|
||||
<div
|
||||
className="pointer-events-auto flex cursor-pointer flex-row items-center justify-start"
|
||||
onClick={() => setSortMethod("name")}
|
||||
>
|
||||
Name
|
||||
</m.h1>
|
||||
<m.h1 onClick={() => setSortBy("netWorth")}>Assets</m.h1>
|
||||
<m.h1
|
||||
className="hidden md:block"
|
||||
onClick={() => setSortBy("points")}
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
Name
|
||||
</h1>
|
||||
<SortSVG sortType="name" />
|
||||
</div>
|
||||
<div
|
||||
className="pointer-events-auto flex cursor-pointer flex-row items-center justify-end"
|
||||
onClick={() => setSortMethod("netWorth")}
|
||||
>
|
||||
Points
|
||||
</m.h1>
|
||||
<m.h1
|
||||
className="hidden md:block"
|
||||
onClick={() => setSortBy("shares")}
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
Assets
|
||||
</h1>
|
||||
<SortSVG sortType="netWorth" />
|
||||
</div>
|
||||
<div
|
||||
className="pointer-events-auto hidden cursor-pointer flex-row items-center justify-end md:flex"
|
||||
onClick={() => setSortMethod("points")}
|
||||
>
|
||||
Shares
|
||||
</m.h1>
|
||||
<m.h1 onClick={() => setSortBy("dailyChange")}>Daily</m.h1>
|
||||
</m.div>
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
Points
|
||||
</h1>
|
||||
<SortSVG sortType="points" />
|
||||
</div>
|
||||
<div
|
||||
className="pointer-events-auto hidden cursor-pointer flex-row items-center justify-end md:flex"
|
||||
onClick={() => setSortMethod("shares")}
|
||||
>
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
Shares
|
||||
</h1>
|
||||
<SortSVG sortType="shares" />
|
||||
</div>
|
||||
<div
|
||||
className="pointer-events-auto flex cursor-pointer flex-row items-center justify-end"
|
||||
onClick={() => setSortMethod("dailyChange")}
|
||||
>
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
Daily
|
||||
</h1>
|
||||
<SortSVG sortType="dailyChange" />
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
// TODO: add arrow to show which column is being sorted by and which direction
|
||||
// generate table rows
|
||||
fakeData.map((entry: fakeDataEntry, index) => {
|
||||
// if daily change is negative, make it red
|
||||
let changeClass = " text-lime-500";
|
||||
if (entry.dailyChangePercent < 0) {
|
||||
changeClass = " text-red-500";
|
||||
|
@ -105,6 +192,7 @@ function Ranking() {
|
|||
);
|
||||
}
|
||||
|
||||
// entire container page animation
|
||||
const containerVariants: Variants = {
|
||||
initial: {
|
||||
opacity: 1,
|
||||
|
@ -122,6 +210,7 @@ const containerVariants: Variants = {
|
|||
},
|
||||
};
|
||||
|
||||
// header animation if needed
|
||||
const headerVariants: Variants = {
|
||||
initial: {
|
||||
opacity: 0,
|
||||
|
@ -140,6 +229,7 @@ const headerVariants: Variants = {
|
|||
},
|
||||
};
|
||||
|
||||
// table container animation
|
||||
const rankingCardVariants: Variants = {
|
||||
initial: {
|
||||
opacity: 0,
|
||||
|
|
Loading…
Reference in a new issue