forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
1import { LabelMedium } from "baseui/typography";
2import dayjs from "dayjs";
3import numeral from "numeral";
4import { useEffect, useState } from "react";
5import { useLocation, useParams } from "react-router";
6import { Area, AreaChart, Tooltip, TooltipProps, XAxis } from "recharts";
7import useChart from "../../hooks/useChart";
8
9const CustomTooltip = ({
10 active,
11 payload,
12 label,
13}: TooltipProps<number, string>) => {
14 if (active && payload && payload.length) {
15 return (
16 <div
17 style={{
18 backgroundColor: "white",
19 padding: "5px",
20 border: "1px solid #ccc",
21 }}
22 >
23 <span style={{ color: "#808080" }}>
24 {dayjs(label).format("dddd DD MMMM YYYY")}:
25 </span>
26 <span> {numeral(payload[0].value).format("0,0")}</span>
27 </div>
28 );
29 }
30
31 return null;
32};
33const formatXAxis = (tickItem: string) => dayjs(tickItem).format("MMM D");
34
35function ScrobblesAreaChart() {
36 const {
37 getScrobblesChart,
38 getAlbumChart,
39 getArtistChart,
40 getSongChart,
41 getProfileChart,
42 } = useChart();
43 const { pathname } = useLocation();
44 const { did, rkey } = useParams<{ did: string; rkey: string }>();
45 const [data, setData] = useState<
46 {
47 date: string;
48 count: number;
49 }[]
50 >([]);
51
52 useEffect(() => {
53 const fetchScrobblesChart = async () => {
54 if (pathname === "/") {
55 return;
56 }
57
58 if (pathname.startsWith("/profile")) {
59 const charts = await getProfileChart(did!);
60 setData(charts);
61 return;
62 }
63
64 if (pathname.includes("app.rocksky.artist")) {
65 const charts = await getArtistChart(
66 `at://${did}/app.rocksky.artist/${rkey}`
67 );
68 setData(charts);
69 return;
70 }
71
72 if (pathname.includes("app.rocksky.album")) {
73 const charts = await getAlbumChart(
74 `at://${did}/app.rocksky.album/${rkey}`
75 );
76 setData(charts);
77 return;
78 }
79
80 if (pathname.includes("app.rocksky.song")) {
81 const charts = await getSongChart(
82 `at://${did}/app.rocksky.song/${rkey}`
83 );
84 setData(charts);
85 return;
86 }
87
88 if (pathname.includes("app.rocksky.scrobble")) {
89 const charts = await getSongChart(
90 `at://${did}/app.rocksky.scrobble/${rkey}`
91 );
92 setData(charts);
93 return;
94 }
95 };
96 fetchScrobblesChart();
97 // eslint-disable-next-line react-hooks/exhaustive-deps
98 }, [pathname]);
99
100 return (
101 <>
102 <LabelMedium marginBottom={"20px"}>Scrobble Stats</LabelMedium>
103 <AreaChart
104 width={300}
105 height={120}
106 data={pathname === "/" ? getScrobblesChart() : data}
107 margin={{
108 top: 5,
109 right: 0,
110 left: 0,
111 bottom: 5,
112 }}
113 >
114 <XAxis
115 dataKey="date"
116 axisLine={{ stroke: "#ccc", strokeWidth: 1 }}
117 tick={{ fontSize: 10 }}
118 tickFormatter={formatXAxis}
119 />
120 <Tooltip
121 content={<CustomTooltip />}
122 labelFormatter={(label) => dayjs(label).format("YYYY-MM-DD")}
123 />
124 <Area
125 type="monotone"
126 dataKey="count"
127 stroke="#710de4"
128 fill="#9754e463"
129 />
130 </AreaChart>
131 </>
132 );
133}
134
135export default ScrobblesAreaChart;