chart.js and rank chart init

This commit is contained in:
3zachm 2023-01-28 20:14:42 -08:00
parent 8057678c76
commit 4049c0a70b
5 changed files with 167 additions and 26 deletions

View file

@ -0,0 +1,69 @@
import RankHistoryJson from "../../interfaces/ChartRankHistoryJSON";
import { Line } from "react-chartjs-2";
import {
Chart,
ChartData,
ChartOptions,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Tooltip,
} from "chart.js";
interface RankChartProps {
rankHistory: RankHistoryJson;
}
Chart.register(CategoryScale, LinearScale, PointElement, LineElement, Tooltip);
function RankChart(props: RankChartProps) {
const options: ChartOptions<"line"> = {
plugins: {
tooltip: {
mode: "index",
intersect: false,
displayColors: false,
callbacks: {
label: (context) => {
const daysAgo = context.dataset.data.length - context.dataIndex - 1;
if (daysAgo === 0) {
return `Today`;
}
return `${daysAgo} days ago`;
},
},
},
},
scales: {
x: {
display: false,
},
y: {
display: false,
reverse: true,
},
},
responsive: true,
maintainAspectRatio: false,
};
const data: ChartData<"line"> = {
// make labels size dynamic
labels: props.rankHistory.rank.map((rank, i) => {
return "Rank " + rank;
}),
datasets: [
{
label: "Rank",
data: props.rankHistory.rank,
fill: false,
borderColor: "rgb(244, 114, 182)",
pointBackgroundColor: "rgb(244, 114, 182)",
tension: 0,
},
],
};
return <Line options={options} data={data} />;
}
export default RankChart;

View file

@ -0,0 +1,3 @@
export default interface RankHistoryJson {
rank: number[];
}

46
package-lock.json generated
View file

@ -8,12 +8,14 @@
"name": "investweb",
"version": "0.1.0",
"dependencies": {
"chart.js": "^4.2.0",
"eslint": "8.28.0",
"eslint-config-next": "13.0.4",
"framer-motion": "^7.6.19",
"ioredis": "^5.2.5",
"next": "13.0.4",
"react": "18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "18.2.0",
"sharp": "^0.31.2",
"typescript": "4.9.3"
@ -127,6 +129,11 @@
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
},
"node_modules/@kurkle/color": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
},
"node_modules/@motionone/animation": {
"version": "10.15.1",
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz",
@ -1074,6 +1081,17 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chart.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.2.0.tgz",
"integrity": "sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": "^7.0.0"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@ -3964,6 +3982,15 @@
"node": ">=0.10.0"
}
},
"node_modules/react-chartjs-2": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz",
"integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==",
"peerDependencies": {
"chart.js": "^4.1.1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@ -5065,6 +5092,11 @@
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
},
"@kurkle/color": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
},
"@motionone/animation": {
"version": "10.15.1",
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz",
@ -5664,6 +5696,14 @@
"supports-color": "^7.1.0"
}
},
"chart.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.2.0.tgz",
"integrity": "sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==",
"requires": {
"@kurkle/color": "^0.3.0"
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@ -7670,6 +7710,12 @@
"loose-envify": "^1.1.0"
}
},
"react-chartjs-2": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz",
"integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==",
"requires": {}
},
"react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",

View file

@ -10,12 +10,14 @@
"prepare": "husky install"
},
"dependencies": {
"chart.js": "^4.2.0",
"eslint": "8.28.0",
"eslint-config-next": "13.0.4",
"framer-motion": "^7.6.19",
"ioredis": "^5.2.5",
"next": "13.0.4",
"react": "18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "18.2.0",
"sharp": "^0.31.2",
"typescript": "4.9.3"

View file

@ -7,6 +7,7 @@ import Loading from "../../../components/common/Loading";
import { GetServerSideProps } from "next";
import UserJSONEntry from "../../../interfaces/UserJSONEntry";
import APIError from "../../../interfaces/APIError";
import RankChart from "../../../components/userpage/RankChart";
interface EmoteURLs {
"7tv": { [key: string]: string };
@ -189,6 +190,7 @@ function UserPage(props: UserPageProps) {
</div>
</div>
</div>
{/* User's net worth (Desktop) */}
<div className="hidden md:block">
<h1>
<span className="text-4xl font-semibold text-zinc-400">
@ -208,35 +210,54 @@ function UserPage(props: UserPageProps) {
>
{/* User's Rank/Graph */}
<div className="col-span-7 rounded-2xl bg-zinc-800 bg-opacity-70">
<div className="flex flex-row items-center justify-between p-5">
<div className="flex-col px-2">
<h1 className="mb-1 whitespace-nowrap text-center text-xl font-medium text-white underline">
Global Rank
</h1>
<div className="flex items-center text-3xl font-bold">
<span className="text-zinc-400">#</span>
<span className="text-white">
{props.userData.rank.toLocaleString("en-US")}
</span>
<div className="inline-grid w-full grid-cols-5 p-5">
<div className="col-span-1 flex items-center justify-start">
<div className="flex-col px-2">
<h1 className="mb-1 whitespace-nowrap text-center text-xl font-medium text-white underline">
Global Rank
</h1>
<div className="flex items-center text-3xl font-bold">
<span className="text-zinc-400">#</span>
<span className="text-white">
{props.userData.rank.toLocaleString("en-US")}
</span>
</div>
</div>
</div>
<div className="hidden md:block">
<Image
src="/img/well_drawn_rank_chart.webp"
alt="Rank chart"
width={497}
height={100}
/>
{/* User's Rank Graph (Desktop) */}
<div className="col-span-4 hidden w-full items-center justify-center pr-4 md:flex lg:justify-end">
<div className="relative h-20 w-[90%] max-w-lg">
<RankChart
rankHistory={{
rank: [1432, 1470, 1004, 1200, 600, 843, 1304],
}}
/>
</div>
</div>
<div className="md:hidden">
<h1>
<span className="text-3xl font-semibold text-zinc-400 sm:text-4xl">
$
</span>
<span className="text-3xl text-white sm:text-4xl">
{props.userData.net_worth.toLocaleString("en-US")}
</span>
</h1>
{/* User's net worth (Mobile) */}
<div className="col-span-4 md:hidden">
<div className="flex h-full w-full items-center justify-end">
<h1>
<span className="text-3xl font-semibold text-zinc-400 sm:text-4xl">
$
</span>
<span className="text-3xl text-white sm:text-4xl">
{props.userData.net_worth.toLocaleString("en-US")}
</span>
</h1>
</div>
</div>
</div>
</div>
{/* User's Graph (Mobile) */}
<div className="col-span-7 rounded-2xl bg-zinc-800 bg-opacity-70 p-5 md:hidden">
<div className="flex items-center justify-center">
<div className="relative h-20 w-full">
<RankChart
rankHistory={{
rank: [1432, 1470, 1004, 1200, 600, 843, 1304],
}}
/>
</div>
</div>
</div>