Skip to content

Commit 219ba50

Browse files
committed
[Feat] Dashboard page
1 parent f7d178c commit 219ba50

File tree

18 files changed

+536
-499
lines changed

18 files changed

+536
-499
lines changed

package-lock.json

Lines changed: 76 additions & 476 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@
1414
"@radix-ui/react-dropdown-menu": "^2.0.6",
1515
"@radix-ui/react-icons": "^1.3.0",
1616
"@radix-ui/react-label": "^2.0.2",
17+
"@radix-ui/react-popover": "^1.0.7",
1718
"@radix-ui/react-slot": "^1.0.2",
1819
"@reduxjs/toolkit": "^2.2.2",
1920
"axios": "^1.6.8",
21+
"chartjs": "^0.3.24",
2022
"class-variance-authority": "^0.7.0",
2123
"clsx": "^2.1.0",
22-
"jest-environment-jsdom": "^29.6.2",
2324
"js-cookie": "^3.0.5",
2425
"lucide-react": "^0.350.0",
2526
"react": "^18.2.0",
27+
"react-chartjs-2": "^5.2.0",
2628
"react-dom": "^18.2.0",
2729
"react-hook-form": "^7.51.2",
2830
"react-redux": "^9.1.0",

src/App.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { useDispatch } from "react-redux";
88
import { getUserInfo } from "./redux-store/slices/authSlice";
99
import { AppDispatch } from "./redux-store/store";
1010
function App() {
11-
const dispatch:AppDispatch=useDispatch();
12-
useEffect(()=>{
13-
dispatch(getUserInfo())
14-
},[dispatch])
11+
const dispatch: AppDispatch = useDispatch();
12+
useEffect(() => {
13+
dispatch(getUserInfo());
14+
}, [dispatch]);
1515
return (
1616
<div className="min-h-screen w-full ">
1717
<Navbar />

src/components/ChartView.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React, { useEffect, useState } from "react";
2+
import {
3+
Chart as ChartJS,
4+
CategoryScale,
5+
LinearScale,
6+
PointElement,
7+
LineElement,
8+
Title,
9+
Tooltip,
10+
Legend,
11+
} from "chart.js";
12+
import { Line } from "react-chartjs-2";
13+
import { useResultStatus } from "@/hooks/useAuthStatus";
14+
import { generateChartData } from "@/lib/helpers/generateChartData";
15+
16+
ChartJS.register(
17+
CategoryScale,
18+
LinearScale,
19+
PointElement,
20+
LineElement,
21+
Title,
22+
Tooltip,
23+
Legend
24+
);
25+
26+
interface ChartProps {
27+
labels: string[];
28+
scoresval: number[];
29+
accuracyval: number[];
30+
}
31+
export default function App({ type }: { type: string }) {
32+
const { results } = useResultStatus();
33+
const [chartdata, setchartdata] = useState<ChartProps>({
34+
labels: [],
35+
scoresval: [],
36+
accuracyval: [],
37+
});
38+
useEffect(() => {
39+
if (results) {
40+
setchartdata(generateChartData(results));
41+
}
42+
}, [results]);
43+
const data = {
44+
labels: chartdata.labels,
45+
datasets: [
46+
{
47+
label: type,
48+
data: type === "Score" ? chartdata.scoresval : chartdata.accuracyval,
49+
borderColor:
50+
type === "Score" ? "rgb(54, 162, 235)" : "rgb(255, 159, 64)",
51+
backgroundColor:
52+
type === "Score" ? "rgb(54, 162, 235)" : "rgb(255, 159, 64)",
53+
borderWidth: 1,
54+
},
55+
],
56+
};
57+
const options = {
58+
responsive: true,
59+
plugins: {
60+
legend: {
61+
position: "top" as const,
62+
},
63+
title: {
64+
display: true,
65+
text: type,
66+
},
67+
},
68+
};
69+
return <Line options={options} data={data} />;
70+
}

src/components/theme-provider.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createContext, useEffect, useState } from "react";
1+
import React, { createContext, useEffect, useState } from "react";
22

33
type Theme = "dark" | "light" | "system";
44

@@ -27,10 +27,7 @@ export function ThemeProvider({
2727
storageKey = "vite-ui-theme",
2828
...props
2929
}: ThemeProviderProps) {
30-
const [theme, setTheme] = useState<Theme>(
31-
() => (localStorage.getItem(storageKey) as Theme) || defaultTheme
32-
);
33-
30+
const [theme, setTheme] = useState<Theme>(localStorage.getItem(storageKey) as Theme || defaultTheme);
3431
useEffect(() => {
3532
const root = window.document.documentElement;
3633

src/components/ui/card.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import * as React from "react"
2+
3+
import { cn } from "@/lib/utils"
4+
5+
const Card = React.forwardRef<
6+
HTMLDivElement,
7+
React.HTMLAttributes<HTMLDivElement>
8+
>(({ className, ...props }, ref) => (
9+
<div
10+
ref={ref}
11+
className={cn(
12+
"rounded-xl border bg-card text-card-foreground shadow",
13+
className
14+
)}
15+
{...props}
16+
/>
17+
))
18+
Card.displayName = "Card"
19+
20+
const CardHeader = React.forwardRef<
21+
HTMLDivElement,
22+
React.HTMLAttributes<HTMLDivElement>
23+
>(({ className, ...props }, ref) => (
24+
<div
25+
ref={ref}
26+
className={cn("flex flex-col space-y-1.5 p-6", className)}
27+
{...props}
28+
/>
29+
))
30+
CardHeader.displayName = "CardHeader"
31+
32+
const CardTitle = React.forwardRef<
33+
HTMLParagraphElement,
34+
React.HTMLAttributes<HTMLHeadingElement>
35+
>(({ className, ...props }, ref) => (
36+
<h3
37+
ref={ref}
38+
className={cn("font-semibold leading-none tracking-tight", className)}
39+
{...props}
40+
/>
41+
))
42+
CardTitle.displayName = "CardTitle"
43+
44+
const CardDescription = React.forwardRef<
45+
HTMLParagraphElement,
46+
React.HTMLAttributes<HTMLParagraphElement>
47+
>(({ className, ...props }, ref) => (
48+
<p
49+
ref={ref}
50+
className={cn("text-sm text-muted-foreground", className)}
51+
{...props}
52+
/>
53+
))
54+
CardDescription.displayName = "CardDescription"
55+
56+
const CardContent = React.forwardRef<
57+
HTMLDivElement,
58+
React.HTMLAttributes<HTMLDivElement>
59+
>(({ className, ...props }, ref) => (
60+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
61+
))
62+
CardContent.displayName = "CardContent"
63+
64+
const CardFooter = React.forwardRef<
65+
HTMLDivElement,
66+
React.HTMLAttributes<HTMLDivElement>
67+
>(({ className, ...props }, ref) => (
68+
<div
69+
ref={ref}
70+
className={cn("flex items-center p-6 pt-0", className)}
71+
{...props}
72+
/>
73+
))
74+
CardFooter.displayName = "CardFooter"
75+
76+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

src/components/ui/popover.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as React from "react"
2+
import * as PopoverPrimitive from "@radix-ui/react-popover"
3+
4+
import { cn } from "@/lib/utils"
5+
6+
const Popover = PopoverPrimitive.Root
7+
8+
const PopoverTrigger = PopoverPrimitive.Trigger
9+
10+
const PopoverAnchor = PopoverPrimitive.Anchor
11+
12+
const PopoverContent = React.forwardRef<
13+
React.ElementRef<typeof PopoverPrimitive.Content>,
14+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
15+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16+
<PopoverPrimitive.Portal>
17+
<PopoverPrimitive.Content
18+
ref={ref}
19+
align={align}
20+
sideOffset={sideOffset}
21+
className={cn(
22+
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
23+
className
24+
)}
25+
{...props}
26+
/>
27+
</PopoverPrimitive.Portal>
28+
))
29+
PopoverContent.displayName = PopoverPrimitive.Content.displayName
30+
31+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }

src/hooks/useAuthStatus.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ const useAuthStatus = () => {
55
const { status, user } = useSelector((state: AuthState) => state.auth);
66
return { status, user };
77
}
8-
export { useAuthStatus };
8+
const useResultStatus=()=>{
9+
const {results}=useSelector((state:AuthState)=>state.result);
10+
return {results};
11+
}
12+
export { useAuthStatus,useResultStatus };
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ResultData } from "@/redux-store/slices/resultslice";
2+
3+
const calculateAverage = function (Results: ResultData[]) {
4+
const n=Results.length;
5+
const res=Results.reduce((acc,curr)=>{
6+
acc.averageScore+=curr.score/n;
7+
acc.averageAccuracy+=curr.accuracy/n;
8+
return acc;
9+
},{
10+
averageScore:0,
11+
averageAccuracy:0
12+
});
13+
return res;
14+
};
15+
16+
export { calculateAverage };

src/lib/helpers/generateChartData.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ResultData } from "@/redux-store/slices/resultslice";
2+
const month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3+
const generateChartData = (results: ResultData[]) => {
4+
const labels = results.map((test) => {
5+
const d = new Date(test.createdAt);
6+
return `${d.getDate() + month[d.getMonth()]}`
7+
})
8+
const scoresval = results.map((v) => v.score);
9+
const accuracyval = results.map((v) => v.accuracy);
10+
return { labels, scoresval, accuracyval };
11+
}
12+
export { generateChartData };

0 commit comments

Comments
 (0)