Skip to content

Instantly share code, notes, and snippets.

@FilipIlievski
Last active May 8, 2022 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FilipIlievski/578e51e08c62c07c1375558cd8a1ca66 to your computer and use it in GitHub Desktop.
Save FilipIlievski/578e51e08c62c07c1375558cd8a1ca66 to your computer and use it in GitHub Desktop.
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
} from "chart.js";
import { subDays } from "date-fns";
import { useEffect, useState } from "react";
import { Bar } from "react-chartjs-2";
import { DataForChart, getData } from "./chartData";
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
export const options = {
responsive: true,
plugins: {
legend: {
position: "top" as const,
},
title: {
display: true,
text: "Chart.js Bar Chart",
},
},
};
export type TimeInterval = {
from: Date;
to: Date;
};
export enum TimeframeLabels {
LAST_SEVEN_DAYS = "Last seven days",
LAST_14_DAYS = "Last 14 days",
LAST_30_DAYS = "Last 30 days",
}
export const TimeframeDays = {
[TimeframeLabels.LAST_SEVEN_DAYS]: 7,
[TimeframeLabels.LAST_14_DAYS]: 14,
[TimeframeLabels.LAST_30_DAYS]: 30,
};
const now = new Date();
const TimeframeVariables: Record<TimeframeLabels, TimeInterval> = {
[TimeframeLabels.LAST_SEVEN_DAYS]: {
from: subDays(now, 7),
to: now,
},
[TimeframeLabels.LAST_14_DAYS]: {
from: subDays(now, 28),
to: now,
},
[TimeframeLabels.LAST_30_DAYS]: {
from: subDays(now, 90),
to: now,
},
};
export default function App() {
const [timeframe, setTimeframe] = useState<TimeframeLabels>(
TimeframeLabels.LAST_30_DAYS
);
const [data, setData] = useState<DataForChart>(
getData({
from: TimeframeVariables[timeframe].from,
to: TimeframeVariables[timeframe].to,
numberOfDays: TimeframeDays[timeframe],
})
);
useEffect(() => {
const payload = TimeframeVariables[timeframe];
setData(
getData({
from: payload.from,
to: payload.to,
numberOfDays: TimeframeDays[timeframe],
})
);
}, [timeframe]);
return (
<>
<div style={{ margin: "40px 0" }}>
<label htmlFor="timeframe-dropdown">Select timeframe:</label>{" "}
<select
name="dropdown"
id="timeframe-dropdown"
defaultValue={timeframe}
onChange={(e) => {
setTimeframe(e.target.value as TimeframeLabels);
}}
>
<option value={TimeframeLabels.LAST_SEVEN_DAYS}>
{TimeframeLabels.LAST_SEVEN_DAYS}
</option>
<option value={TimeframeLabels.LAST_14_DAYS}>
{TimeframeLabels.LAST_14_DAYS}
</option>
<option value={TimeframeLabels.LAST_30_DAYS}>
{TimeframeLabels.LAST_30_DAYS}
</option>
</select>
</div>
<Bar options={options} data={data} />
</>
);
}
import { addDays, format, isAfter, isBefore } from "date-fns";
type Album = {
id: number;
title: string;
dateCreated: string;
dateSold: string;
description: string;
type: string;
image: string;
price: number;
artist: string;
isPublished: boolean;
isAuctioning: boolean;
priceSold: number;
};
export type DataForChart = {
labels: string[];
datasets: {
label: string;
data: number[];
backgroundColor: string;
}[];
};
const items: Array<Album> = [
{
id: 1,
title: "Meet me where the wild things grow",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit ut aliquam, purus sit amet luctus venenatis, lectus magna fringilla urna, porttitor rhoncus dolor...",
type: "painting",
image:
"https://images.unsplash.com/photo-1617994422012-baad9c327e20?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=300&ixid=MnwxfDB8MXxyYW5kb218MHx8cGFpbnRpbmcsIGFydCwgY2FudmFzLCBkaWdpdGFsYXJ0LCBhcnRpc3R8fHx8fHwxNjM1NDY5MTI0&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=800",
price: 1315,
artist: "Leanne Graham",
dateCreated: "2021-10-09T02:00:48.989Z",
isPublished: false,
isAuctioning: false,
dateSold: "2022-05-01T02:00:48.989Z",
priceSold: 2030,
},
{
id: 2,
title: "I choose peace",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit ut aliquam, purus sit amet luctus venenatis, lectus magna fringilla urna, porttitor rhoncus dolor...",
type: "sculpture",
image:
"https://images.unsplash.com/photo-1617994422012-baad9c327e20?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=300&ixid=MnwxfDB8MXxyYW5kb218MHx8cGFpbnRpbmcsIGFydCwgY2FudmFzLCBkaWdpdGFsYXJ0LCBhcnRpc3R8fHx8fHwxNjM1NDY5MTI0&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=800",
price: 530,
artist: "Ervin Howell",
dateCreated: "2021-10-27T02:00:48.989Z",
isPublished: false,
isAuctioning: false,
dateSold: "2022-05-04T02:00:48.989Z",
priceSold: 350,
},
{
id: 3,
title: "Peace Underneath",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit ut aliquam, purus sit amet luctus venenatis, lectus magna fringilla urna, porttitor rhoncus dolor...",
type: "digital",
image:
"https://images.unsplash.com/photo-1617994422012-baad9c327e20?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=300&ixid=MnwxfDB8MXxyYW5kb218MHx8cGFpbnRpbmcsIGFydCwgY2FudmFzLCBkaWdpdGFsYXJ0LCBhcnRpc3R8fHx8fHwxNjM1NDY5MTI0&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=800",
price: 495,
artist: "Clementine Bauch",
dateCreated: "2021-10-17T02:00:48.989Z",
isPublished: true,
isAuctioning: false,
dateSold: "2022-05-04T02:00:48.989Z",
priceSold: 2810,
},
{
id: 4,
title: "ABC",
dateCreated: "2022-04-09T02:00:48.989Z",
dateSold: "2022-05-01T02:00:48.989Z",
description: "My man",
type: "digital",
image: "",
price: 2222,
artist: "Denzel",
isPublished: true,
isAuctioning: true,
priceSold: 200,
},
{
id: 5,
title: "FFGG",
dateCreated: "2022-04-27T02:00:48.989Z",
dateSold: "2022-05-04T02:00:48.989Z",
description: "Sampanjac",
type: "digital",
image: "",
price: 999,
artist: "Mile Kitic",
isPublished: true,
isAuctioning: true,
priceSold: 1100,
},
{
id: 6,
title: "Test AA",
dateCreated: "2022-04-17T02:00:48.989Z",
dateSold: "2022-05-04T02:00:48.989Z",
description: "My man",
type: "digital",
image: "",
price: 333,
artist: "Krume",
isPublished: true,
isAuctioning: true,
priceSold: 200,
},
];
export const getData = ({
from,
to,
numberOfDays,
}: {
from: Date;
to: Date;
numberOfDays: number;
}): DataForChart => {
const labels = Array.from({ length: numberOfDays }).map((_, idx) =>
format(addDays(from, idx), "dd.MM.yyyy")
);
const data = items
.map((item) => {
if (
isBefore(new Date(item.dateCreated), to) &&
isAfter(new Date(item.dateCreated), from)
) {
return item.priceSold;
}
return null;
})
.filter((i): i is number => !!i);
return {
labels,
datasets: [
{
label: "Albums",
data,
backgroundColor: "red",
},
],
};
};
{
"name": "chart_sandbox",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"@types/faker": "5.5.3",
"@types/jest": "^27.5.0",
"@types/node": "^16.11.33",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3",
"chart.js": "^3.7.1",
"date-fns": "^2.28.0",
"faker": "5.5.3",
"react": "^18.1.0",
"react-chartjs-2": "^4.1.0",
"react-dom": "^18.1.0",
"react-scripts": "5.0.1",
"typescript": "^4.6.4",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment