Skip to content

Commit 21d95a0

Browse files
committed
feat: Add react-toastify dependency and implement toast notifications
- Add "react-toastify" dependency to the client's package.json file - Import and use the "ToastContainer" component from "react-toastify" in the Home component to display toast notifications - Add CSS styling for the toast notifications in the global CSS file Related to #123
1 parent 408b466 commit 21d95a0

File tree

8 files changed

+138
-64
lines changed

8 files changed

+138
-64
lines changed

client/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"mongoose": "^8.5.2",
1414
"next": "14.2.5",
1515
"react": "^18",
16-
"react-dom": "^18"
16+
"react-dom": "^18",
17+
"react-toastify": "^10.0.5"
1718
},
1819
"devDependencies": {
1920
"@types/node": "^20",

client/src/app/components/GenerateStats.tsx

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
"use client";
2-
import React, { useState } from "react";
2+
import React, { useContext, useState } from "react";
33
import Card from "./Card";
44
import Image from "next/image";
55
import { data as defaultData } from "./Card";
6+
import { toast, ToastContainer } from "react-toastify";
7+
import { DataContext } from "../context/DataContext";
68

79
const GenerateStats = ({ showStats, setShowStats }: any) => {
10+
const { datas, setDatas } = useContext(DataContext);
811
const [username, setUsername] = useState("");
912
const [data, setData] = useState<any>(defaultData);
1013

@@ -20,7 +23,7 @@ const GenerateStats = ({ showStats, setShowStats }: any) => {
2023
.then((res) => res.json())
2124
.then((data) => {
2225
setData(data);
23-
console.log(data);
26+
toast("🫡Stats generated successfully");
2427
});
2528
} catch (error) {
2629
console.error("An error occurred. Please try again later");
@@ -38,7 +41,11 @@ const GenerateStats = ({ showStats, setShowStats }: any) => {
3841
});
3942
const result = await response.json();
4043
if (result.success) {
41-
console.log("Data added to the hall of fame");
44+
setDatas([...datas, data]);
45+
toast("🥷Data added to the hall of fame");
46+
setShowStats(false);
47+
setData(defaultData);
48+
setUsername("");
4249
} else {
4350
console.error("Error adding data to the hall of fame");
4451
}
@@ -48,59 +55,63 @@ const GenerateStats = ({ showStats, setShowStats }: any) => {
4855
};
4956

5057
return (
51-
<div
52-
onClick={() => setShowStats(false)}
53-
className={`fixed z-10 top-0 font-sourcecodepro left-0 backdrop-blur-md flex items-center justify-center h-full w-full ${
54-
showStats ? "" : "hidden"
55-
}`}
56-
>
58+
<>
5759
<div
58-
onClick={(e) => e.stopPropagation()}
59-
className="px-4 flex items-center justify-center flex-col gap-4"
60+
onClick={() => (
61+
setShowStats(false), setData(defaultData), setUsername("")
62+
)}
63+
className={`fixed z-10 top-0 font-sourcecodepro left-0 backdrop-blur-md flex items-center justify-center h-full w-full ${
64+
showStats ? "" : "hidden"
65+
}`}
6066
>
61-
<Card userData={data} />
62-
63-
<form
64-
onSubmit={generateStats}
65-
className="flex items-center justify-center flex-col"
67+
<div
68+
onClick={(e) => e.stopPropagation()}
69+
className="px-4 flex items-center justify-center flex-col gap-4"
6670
>
67-
<div className="relative ">
68-
<input
69-
value={username}
70-
onChange={(e) => setUsername(e.target.value)}
71-
type="text"
72-
placeholder="Enter your username"
73-
className="bg-[#1f1f1f] pl-10 w-[300px] h-[40px] text-white rounded px-4 py-6 md:text-lg text-base focus:outline-none"
74-
/>
75-
<Image
76-
src="/assets/icons/user.svg"
77-
alt="Search Icon"
78-
width={24}
79-
height={24}
80-
className="absolute left-2 -translate-y-1/2 top-1/2 "
81-
/>
82-
</div>
71+
<Card userData={data} />
72+
73+
<form
74+
onSubmit={generateStats}
75+
className="flex items-center justify-center flex-col"
76+
>
77+
<div className="relative ">
78+
<input
79+
value={username}
80+
onChange={(e) => setUsername(e.target.value)}
81+
type="text"
82+
placeholder="Enter your username"
83+
className="bg-[#1f1f1f] pl-10 w-[300px] h-[40px] text-white rounded px-4 py-6 md:text-lg text-base focus:outline-none"
84+
/>
85+
<Image
86+
src="/assets/icons/user.svg"
87+
alt="Search Icon"
88+
width={24}
89+
height={24}
90+
className="absolute left-2 -translate-y-1/2 top-1/2 "
91+
/>
92+
</div>
8393

84-
<div className="flex gap-2 ">
85-
<button
86-
type="submit"
87-
disabled={!username}
88-
onClick={generateStats}
89-
className={`border bg-[#010101] px-4 h-[40px] rounded-md text-white font-semibold text-lg mt-4 `}
90-
>
91-
Generate <span className="hidden sm:inline-block">Stats</span>
92-
</button>
93-
<button
94-
type="button"
95-
onClick={addToLeetboard}
96-
className=" border bg-[#010101] px-4 h-[40px] rounded-md text-white font-semibold text-lg mt-4"
97-
>
98-
Add to <span className="">Leetboard</span>
99-
</button>
100-
</div>
101-
</form>
94+
<div className="flex gap-2 ">
95+
<button
96+
type="submit"
97+
disabled={!username}
98+
onClick={generateStats}
99+
className={`border bg-[#010101] px-4 h-[40px] rounded-md text-white font-semibold text-lg mt-4 `}
100+
>
101+
Generate <span className="hidden sm:inline-block">Stats</span>
102+
</button>
103+
<button
104+
type="button"
105+
onClick={addToLeetboard}
106+
className=" border bg-[#010101] px-4 h-[40px] rounded-md text-white font-semibold text-lg mt-4"
107+
>
108+
Add to <span className="">Leetboard</span>
109+
</button>
110+
</div>
111+
</form>
112+
</div>
102113
</div>
103-
</div>
114+
</>
104115
);
105116
};
106117

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use client";
2+
3+
import { createContext, useState } from "react";
4+
5+
export const DataContext = createContext({
6+
datas: [],
7+
setDatas: (datas: any) => {},
8+
});
9+
10+
export const DataProvider = ({ children }: any) => {
11+
const [datas, setDatas] = useState<any>();
12+
return (
13+
<DataContext.Provider
14+
value={{
15+
datas,
16+
setDatas,
17+
}}
18+
>
19+
{children}
20+
</DataContext.Provider>
21+
);
22+
};

client/src/app/layout.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import type { Metadata } from "next";
22
import { Inter, Source_Code_Pro } from "next/font/google";
33
import "./globals.css";
4+
import { DataProvider } from "./context/DataContext";
45

56
const sourcecodepro = Source_Code_Pro({
67
subsets: ["latin"],
78
variable: "--font-sourcecodepro",
89
});
910

1011
export const metadata: Metadata = {
11-
title: "Create Next App",
12-
description: "Generated by create next app",
12+
title: "Leetcode Profiles",
13+
description: "Generate your Leetcode Stats",
1314
};
1415

1516
export default function RootLayout({
@@ -19,7 +20,9 @@ export default function RootLayout({
1920
}>) {
2021
return (
2122
<html lang="en">
22-
<body className={sourcecodepro.variable}>{children}</body>
23+
<body className={sourcecodepro.variable}>
24+
<DataProvider>{children}</DataProvider>
25+
</body>
2326
</html>
2427
);
2528
}

client/src/app/page.tsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@ import Navbar from "./components/Navbar";
55
import Card from "./components/Card";
66
import Footer from "./components/Footer";
77
import GenerateStats from "./components/GenerateStats";
8-
import { useEffect, useState } from "react";
8+
import { useContext, useEffect, useState } from "react";
99
import PromotionCard from "./components/PromotionCard";
10+
import { DataContext } from "./context/DataContext";
11+
import { ToastContainer } from "react-toastify";
12+
import "react-toastify/dist/ReactToastify.css";
1013

1114
export default function Home() {
12-
const [data, setData] = useState<any>();
15+
const { datas, setDatas } = useContext(DataContext);
1316
const [loading, setLoading] = useState(true);
1417
const fetchData = async () => {
1518
try {
1619
const res = await fetch("/api/fetchdata");
1720
const data = await res.json();
18-
setData(data.data);
21+
setDatas(data.data);
1922
console.log(data.data);
2023
setLoading(false);
2124
} catch (error) {
@@ -25,7 +28,7 @@ export default function Home() {
2528

2629
useEffect(() => {
2730
fetchData();
28-
}, []);
31+
}, [datas]);
2932

3033
const [showStats, setShowStats] = useState(false);
3134
return (
@@ -48,13 +51,32 @@ export default function Home() {
4851

4952
<div className="mt-32 max-w-7xl mx-auto place-items-center grid grid-cols-1 md:grid-cols-2 gap-y-8 xl:grid-cols-3 font-sourcecodepro gap-x-4">
5053
<PromotionCard />
51-
{data &&
52-
data.map((userData: any, index: number) => (
53-
<Card userData={userData} index={index} key={index} />
54-
))}
54+
{datas &&
55+
datas
56+
.sort(
57+
(a: any, b: any) =>
58+
new Date(b.timeStamp).getTime() -
59+
new Date(a.timeStamp).getTime()
60+
)
61+
.map((userData: any, index: number) => (
62+
<Card userData={userData} index={index} key={index} />
63+
))}
5564
</div>
5665

5766
<Footer />
67+
68+
<ToastContainer
69+
position="bottom-right"
70+
autoClose={5000}
71+
hideProgressBar={false}
72+
newestOnTop={false}
73+
closeOnClick
74+
rtl={false}
75+
pauseOnFocusLoss
76+
draggable
77+
pauseOnHover
78+
theme="dark"
79+
/>
5880
</section>
5981
);
6082
}

client/src/models/userdata.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { timeStamp } from "console";
12
import mongoose from "mongoose";
23

34
const userDataSchema = new mongoose.Schema({
@@ -33,6 +34,7 @@ const userDataSchema = new mongoose.Schema({
3334
mediumTotal: Number,
3435
hardSolved: Number,
3536
hardTotal: Number,
37+
timeStamp: Date,
3638
});
3739

3840
export default mongoose.models.userdatas ||

client/src/pages/api/add.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export default async function handler(req: any, res: any) {
1010
switch (method) {
1111
case "POST":
1212
try {
13+
const timeStamp = new Date();
1314
const { username } = req.body.profileData;
1415

1516
// Check if the user already exists
@@ -24,7 +25,7 @@ export default async function handler(req: any, res: any) {
2425
}
2526

2627
// Create new user if username doesn't exist
27-
const message = await UserData.create(req.body);
28+
const message = await UserData.create({ ...req.body, timeStamp });
2829
res.status(201).json({ success: true, data: message });
2930
} catch (error) {
3031
res.status(400).json({ success: false, error });

client/yarn.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,11 @@ client-only@0.0.1:
607607
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
608608
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
609609

610+
clsx@^2.1.0:
611+
version "2.1.1"
612+
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
613+
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
614+
610615
color-convert@^2.0.1:
611616
version "2.0.1"
612617
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
@@ -2271,6 +2276,13 @@ react-is@^16.13.1:
22712276
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
22722277
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
22732278

2279+
react-toastify@^10.0.5:
2280+
version "10.0.5"
2281+
resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-10.0.5.tgz#6b8f8386060c5c856239f3036d1e76874ce3bd1e"
2282+
integrity sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==
2283+
dependencies:
2284+
clsx "^2.1.0"
2285+
22742286
react@^18:
22752287
version "18.3.1"
22762288
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"

0 commit comments

Comments
 (0)