data loading screen, fix fonts, misc animations
This commit is contained in:
parent
be77e86e02
commit
a4fa47eda4
6 changed files with 121 additions and 89 deletions
|
@ -13,7 +13,7 @@ function NavBar({ options }: NavProps) {
|
||||||
const [isActive, setActive] = useState(false);
|
const [isActive, setActive] = useState(false);
|
||||||
return (
|
return (
|
||||||
<m.div
|
<m.div
|
||||||
className="pointer-events-none fixed inline-grid w-screen grid-cols-2 bg-zinc-900 font-plusJakarta text-2xl lg:grid-cols-3"
|
className="pointer-events-none fixed inline-grid w-screen grid-cols-2 bg-zinc-900 font-plusJakarta text-xl sm:text-2xl lg:grid-cols-3"
|
||||||
variants={containerVariants}
|
variants={containerVariants}
|
||||||
initial="initial"
|
initial="initial"
|
||||||
animate="animate"
|
animate="animate"
|
||||||
|
@ -37,7 +37,7 @@ function NavBar({ options }: NavProps) {
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</m.div>
|
</m.div>
|
||||||
<div className="pointer-events-auto flex select-none flex-col items-start justify-center pr-5 font-plusJakarta text-white">
|
<div className="pointer-events-auto flex select-none flex-col items-start justify-center pr-2 font-plusJakarta text-white sm:pr-5">
|
||||||
<Link
|
<Link
|
||||||
key="InvestBot"
|
key="InvestBot"
|
||||||
href="/"
|
href="/"
|
||||||
|
@ -91,9 +91,7 @@ function NavBar({ options }: NavProps) {
|
||||||
className="ml-auto flex flex-row items-center justify-center p-2 sm:p-7"
|
className="ml-auto flex flex-row items-center justify-center p-2 sm:p-7"
|
||||||
variants={itemVariants}
|
variants={itemVariants}
|
||||||
>
|
>
|
||||||
<p className="pointer-events-auto select-none pr-5 text-white">
|
<p className="pointer-events-auto select-none pr-5 text-white">WIP</p>
|
||||||
Login WIP
|
|
||||||
</p>
|
|
||||||
<div className="h-10 w-10 rounded-full bg-white"></div>
|
<div className="h-10 w-10 rounded-full bg-white"></div>
|
||||||
</m.div>
|
</m.div>
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
|
|
|
@ -31,7 +31,10 @@ export default async function handler(
|
||||||
data = data.reverse();
|
data = data.reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fake loading time
|
||||||
|
await new Promise((resolve) =>
|
||||||
|
setTimeout(resolve, 250 + Math.random() * 1000)
|
||||||
|
);
|
||||||
res.status(200).json({ data });
|
res.status(200).json({ data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { m, Variants } from "framer-motion";
|
import { m, Variants } from "framer-motion";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { ReactElement, useEffect, useState } from "react";
|
import { ReactElement, useEffect, useState } from "react";
|
||||||
|
import Loading from "../../components/common/Loading";
|
||||||
import DashLayout from "../../layouts/DashLayout";
|
import DashLayout from "../../layouts/DashLayout";
|
||||||
import { fakeDataEntry } from "../api/fakeRanking";
|
import { fakeDataEntry } from "../api/fakeRanking";
|
||||||
|
|
||||||
|
@ -8,13 +9,16 @@ function Ranking() {
|
||||||
const [sortBy, setSortBy] = useState("netWorth");
|
const [sortBy, setSortBy] = useState("netWorth");
|
||||||
const [sortAsc, setSortAsc] = useState(false);
|
const [sortAsc, setSortAsc] = useState(false);
|
||||||
const [fakeData, setFakeData] = useState([]);
|
const [fakeData, setFakeData] = useState([]);
|
||||||
|
const [dataLoaded, setDataLoaded] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setDataLoaded(false);
|
||||||
// fetch data from api on change to sort method
|
// fetch data from api on change to sort method
|
||||||
fetch(`/api/fakeRanking?s=${sortBy}&a=${sortAsc}`)
|
fetch(`/api/fakeRanking?s=${sortBy}&a=${sortAsc}`)
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setFakeData(data.data);
|
setFakeData(data.data);
|
||||||
|
setDataLoaded(true);
|
||||||
});
|
});
|
||||||
}, [sortBy, sortAsc]);
|
}, [sortBy, sortAsc]);
|
||||||
|
|
||||||
|
@ -23,13 +27,9 @@ function Ranking() {
|
||||||
if (sortBy != props.sortType) {
|
if (sortBy != props.sortType) {
|
||||||
return (
|
return (
|
||||||
<m.svg
|
<m.svg
|
||||||
className="ml-2"
|
className="ml-2 h-[12px] w-[12px] md:h-[15px] md:w-[15px] "
|
||||||
origin="center"
|
origin="center"
|
||||||
width="15"
|
|
||||||
height="15"
|
|
||||||
viewBox="0 0 6 6"
|
viewBox="0 0 6 6"
|
||||||
x={0}
|
|
||||||
y={0}
|
|
||||||
>
|
>
|
||||||
<m.line
|
<m.line
|
||||||
x1="1"
|
x1="1"
|
||||||
|
@ -37,22 +37,18 @@ function Ranking() {
|
||||||
x2="5"
|
x2="5"
|
||||||
y2="3"
|
y2="3"
|
||||||
stroke="white"
|
stroke="white"
|
||||||
stroke-linecap="round"
|
strokeLinecap="round"
|
||||||
/>
|
/>
|
||||||
</m.svg>
|
</m.svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<m.svg
|
<m.svg
|
||||||
className="ml-2"
|
className="ml-2 h-[12px] w-[12px] sm:h-[15px] sm:w-[15px]"
|
||||||
origin="center"
|
origin="center"
|
||||||
width="15"
|
|
||||||
height="15"
|
|
||||||
viewBox="0 0 330 330"
|
viewBox="0 0 330 330"
|
||||||
x={0}
|
|
||||||
y={0}
|
|
||||||
// if asc, rotate 180
|
// if asc, rotate 180
|
||||||
animate={{ rotate: sortAsc ? 180 : 0 }}
|
transform={sortAsc ? "rotate(180)" : ""}
|
||||||
>
|
>
|
||||||
<m.path
|
<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"
|
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"
|
||||||
|
@ -82,12 +78,7 @@ function Ranking() {
|
||||||
<title>Ranking - InvestBot</title>
|
<title>Ranking - InvestBot</title>
|
||||||
</Head>
|
</Head>
|
||||||
<div className="flex w-full justify-center">
|
<div className="flex w-full justify-center">
|
||||||
<m.div
|
<div className="ml-3 flex w-full flex-col items-center justify-start font-robotoMono font-semibold lg:ml-0">
|
||||||
className="ml-3 flex w-full flex-col items-center justify-start font-spaceMono font-semibold lg:ml-0"
|
|
||||||
variants={containerVariants}
|
|
||||||
initial="initial"
|
|
||||||
animate="animate"
|
|
||||||
>
|
|
||||||
{/* hidden if smaller than lg */}
|
{/* hidden if smaller than lg */}
|
||||||
<m.h1
|
<m.h1
|
||||||
className="hidden bg-gradient-to-tr from-purple-500 to-purple-100 bg-clip-text py-10 text-center font-plusJakarta text-5xl font-bold text-white text-transparent lg:block lg:text-6xl"
|
className="hidden bg-gradient-to-tr from-purple-500 to-purple-100 bg-clip-text py-10 text-center font-plusJakarta text-5xl font-bold text-white text-transparent lg:block lg:text-6xl"
|
||||||
|
@ -97,10 +88,11 @@ function Ranking() {
|
||||||
</m.h1>
|
</m.h1>
|
||||||
{/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */}
|
{/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */}
|
||||||
<m.div
|
<m.div
|
||||||
className="text-md inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 sm:text-xl"
|
className="inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 text-sm sm:text-xl"
|
||||||
variants={rankingCardVariants}
|
|
||||||
initial="initial"
|
initial="initial"
|
||||||
animate="animate"
|
animate="animate"
|
||||||
|
exit="exit"
|
||||||
|
variants={rankingCardVariants}
|
||||||
>
|
>
|
||||||
{/* Column names and arrows */}
|
{/* 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]">
|
<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]">
|
||||||
|
@ -148,68 +140,69 @@ function Ranking() {
|
||||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||||
Daily
|
Daily
|
||||||
</h1>
|
</h1>
|
||||||
<SortSVG sortType="dailyChange" />
|
<SortSVG sortType="dailyChangePercent" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
// generate table rows
|
// if data is not loaded, loading div
|
||||||
fakeData.map((entry: fakeDataEntry, index) => {
|
!dataLoaded ? (
|
||||||
// if daily change is negative, make it red
|
<div className="mt-5 flex h-[100vh] w-full flex-col items-center justify-start">
|
||||||
let changeClass = " text-lime-500";
|
<Loading />
|
||||||
if (entry.dailyChangePercent < 0) {
|
<h1 className="my-5">This is fake delay :)</h1>
|
||||||
changeClass = " text-red-500";
|
</div>
|
||||||
}
|
) : (
|
||||||
return (
|
<m.div
|
||||||
<m.div key={entry.id}>
|
initial="initial"
|
||||||
<m.div className="inline-grid w-full grid-flow-col grid-cols-[1fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-700 px-5 py-2 text-right md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]">
|
animate="animate"
|
||||||
<m.h1 className="text-left md:text-center">
|
exit="exit"
|
||||||
{index + 1}
|
variants={rankingDataContainerVariants}
|
||||||
</m.h1>
|
>
|
||||||
<m.h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
{
|
||||||
{entry.name}
|
// generate table rows
|
||||||
</m.h1>
|
fakeData.map((entry: fakeDataEntry, index) => {
|
||||||
<m.h1>{entry.netWorth.toLocaleString("en-US")}</m.h1>
|
// if daily change is negative, make it red
|
||||||
<m.h1 className="hidden md:block">
|
let changeClass = " text-lime-500";
|
||||||
{entry.points.toLocaleString("en-US")}
|
if (entry.dailyChangePercent < 0) {
|
||||||
</m.h1>
|
changeClass = " text-red-500";
|
||||||
<m.h1 className="hidden md:block">
|
}
|
||||||
{entry.shares.toLocaleString("en-US")}
|
return (
|
||||||
</m.h1>
|
<m.div
|
||||||
<m.h1 className={changeClass}>
|
className="inline-grid w-full grid-flow-col grid-cols-[1fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-700 px-5 py-2 text-right md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]"
|
||||||
{(
|
key={entry.id}
|
||||||
Math.round(entry.dailyChangePercent * 1000) / 10
|
variants={rankingDataLineVariants}
|
||||||
).toFixed(1) + "%"}
|
>
|
||||||
</m.h1>
|
<h1 className="text-left md:text-center">
|
||||||
</m.div>
|
{index + 1}
|
||||||
</m.div>
|
</h1>
|
||||||
);
|
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||||
})
|
{entry.name}
|
||||||
|
</h1>
|
||||||
|
<h1>{entry.netWorth.toLocaleString("en-US")}</h1>
|
||||||
|
<h1 className="hidden md:block">
|
||||||
|
{entry.points.toLocaleString("en-US")}
|
||||||
|
</h1>
|
||||||
|
<h1 className="hidden md:block">
|
||||||
|
{entry.shares.toLocaleString("en-US")}
|
||||||
|
</h1>
|
||||||
|
<h1 className={changeClass}>
|
||||||
|
{(
|
||||||
|
Math.round(entry.dailyChangePercent * 1000) / 10
|
||||||
|
).toFixed(1) + "%"}
|
||||||
|
</h1>
|
||||||
|
</m.div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</m.div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</m.div>
|
</m.div>
|
||||||
</m.div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// entire container page animation
|
|
||||||
const containerVariants: Variants = {
|
|
||||||
initial: {
|
|
||||||
opacity: 1,
|
|
||||||
},
|
|
||||||
animate: {
|
|
||||||
opacity: 1,
|
|
||||||
transition: {
|
|
||||||
duration: 2,
|
|
||||||
delayChildren: 0.5,
|
|
||||||
staggerChildren: 0.25,
|
|
||||||
type: "spring",
|
|
||||||
bounce: 0.5,
|
|
||||||
stiffness: 80,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// header animation if needed
|
// header animation if needed
|
||||||
const headerVariants: Variants = {
|
const headerVariants: Variants = {
|
||||||
initial: {
|
initial: {
|
||||||
|
@ -241,12 +234,50 @@ const rankingCardVariants: Variants = {
|
||||||
transition: {
|
transition: {
|
||||||
duration: 3,
|
duration: 3,
|
||||||
delayChildren: 0.5,
|
delayChildren: 0.5,
|
||||||
staggerChildren: 0.25,
|
|
||||||
type: "spring",
|
type: "spring",
|
||||||
bounce: 0.5,
|
bounce: 0.5,
|
||||||
stiffness: 40,
|
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) {
|
Ranking.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
|
|
@ -81,25 +81,25 @@ const Home: NextPageWithLayout = () => {
|
||||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||||
<div className="inline-grid grid-cols-1 gap-10 text-white md:grid-cols-3">
|
<div className="inline-grid grid-cols-1 gap-10 text-white md:grid-cols-3">
|
||||||
<m.div
|
<m.div
|
||||||
className="flex flex-col font-plusJakarta font-semibold md:col-span-2"
|
className="flex flex-col font-plusJakarta text-7xl font-semibold sm:text-8xl md:col-span-2"
|
||||||
variants={sloganContainerVariants}
|
variants={sloganContainerVariants}
|
||||||
initial="initial"
|
initial="initial"
|
||||||
animate="animate"
|
animate="animate"
|
||||||
>
|
>
|
||||||
<m.div
|
<m.div
|
||||||
className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-2 text-transparent"
|
className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-3 text-transparent"
|
||||||
variants={sloganHeaderVariants}
|
variants={sloganHeaderVariants}
|
||||||
>
|
>
|
||||||
<h1 className="text-8xl">Buy high</h1>
|
<h1>Buy high</h1>
|
||||||
</m.div>
|
</m.div>
|
||||||
<m.div
|
<m.div
|
||||||
className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-2 text-transparent"
|
className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-3 text-transparent"
|
||||||
variants={sloganHeaderVariants}
|
variants={sloganHeaderVariants}
|
||||||
>
|
>
|
||||||
<h1 className="text-8xl">Sell low</h1>
|
<h1>Sell low</h1>
|
||||||
</m.div>
|
</m.div>
|
||||||
<m.h2
|
<m.h2
|
||||||
className="pt-2 font-medium italic text-gray-200"
|
className="pt-2 text-sm font-medium text-gray-200"
|
||||||
variants={sloganSecondaryVariants}
|
variants={sloganSecondaryVariants}
|
||||||
>
|
>
|
||||||
...or something like that
|
...or something like that
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap");
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono:300,400,500,700&display=swap");
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Plus+Jakarta+Sans:300,400,500,700&display=swap");
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap");
|
|
||||||
@import url("https://fonts.googleapis.com/css?family=Plus+Jakarta+Sans:300,400,500,700&display=swap");
|
|
||||||
@import url("https://fonts.googleapis.com/css?family=Space+Mono:300,400,500,700&display=swap");
|
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
roboto: ["Roboto", "sans-serif"],
|
roboto: ["Roboto", "sans-serif"],
|
||||||
plusJakarta: ["Plus Jakarta Sans", "sans-serif"],
|
plusJakarta: ["Plus Jakarta Sans", "sans-serif"],
|
||||||
spaceMono: ["Space Mono", "monospace"],
|
robotoMono: ["Roboto Mono", "monospace"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue