From 79f42f16ad53a08e1e1c8ede065aa6201f864e64 Mon Sep 17 00:00:00 2001 From: Mayur Pal Date: Tue, 22 Jul 2025 16:52:43 +0530 Subject: [PATCH 1/7] feat: add toast otifications for github token errors and fetch success --- backend/{.env.example => .env.sample} | 2 +- backend/package.json | 3 +- backend/server.js | 45 ++++---- package.json | 1 + src/Routes/Login/Login.tsx | 149 -------------------------- src/components/Navbar.tsx | 8 ++ src/hooks/useGitHubAuth.ts | 4 +- src/hooks/useGitHubData.ts | 29 +++-- src/pages/Home/Home.tsx | 108 ++++++++++--------- 9 files changed, 123 insertions(+), 226 deletions(-) rename backend/{.env.example => .env.sample} (65%) delete mode 100644 src/Routes/Login/Login.tsx diff --git a/backend/.env.example b/backend/.env.sample similarity index 65% rename from backend/.env.example rename to backend/.env.sample index 98f9688..269e5b8 100644 --- a/backend/.env.example +++ b/backend/.env.sample @@ -1,3 +1,3 @@ PORT=5000 MONGO_URI=mongodb://localhost:27017/githubTracker -SESSION_SECRET=your-secret-key +SESSION_SECRET=your-secret-key \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index 53bd64b..473d028 100644 --- a/backend/package.json +++ b/backend/package.json @@ -3,7 +3,8 @@ "version": "1.0.0", "main": "server.js", "scripts": { - "start": "nodemon server.js", + "start": "nodemon server.js", + "dev": "nodemon server.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], diff --git a/backend/server.js b/backend/server.js index 3f19f00..5da9e07 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,39 +1,46 @@ -const express = require('express'); -const mongoose = require('mongoose'); -const session = require('express-session'); -const passport = require('passport'); -const bodyParser = require('body-parser'); -require('dotenv').config(); -const cors = require('cors'); +const express = require("express"); +const mongoose = require("mongoose"); +const session = require("express-session"); +const passport = require("passport"); +const bodyParser = require("body-parser"); +require("dotenv").config(); +const cors = require("cors"); // Passport configuration -require('./config/passportConfig'); +require("./config/passportConfig"); const app = express(); // CORS configuration -app.use(cors('*')); +app.use(cors("*")); // Middleware app.use(bodyParser.json()); -app.use(session({ +console.log("process.env.SESSION_SECRET: ", process.env.SESSION_SECRET); +app.use( + session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, -})); + }) +); app.use(passport.initialize()); app.use(passport.session()); // Routes -const authRoutes = require('./routes/auth'); -app.use('/api/auth', authRoutes); +const authRoutes = require("./routes/auth"); +app.use("/api/auth", authRoutes); +console.log("process.env.MONGO_URI: ", process.env.MONGO_URI); // Connect to MongoDB -mongoose.connect(process.env.MONGO_URI, {}).then(() => { - console.log('Connected to MongoDB'); +mongoose + .connect(process.env.MONGO_URI, {}) + .then(() => { + console.log("Connected to MongoDB"); app.listen(process.env.PORT, () => { - console.log(`Server running on port ${process.env.PORT}`); + console.log(`Server running on port ${process.env.PORT}`); }); -}).catch((err) => { - console.log('MongoDB connection error:', err); -}); + }) + .catch((err) => { + console.log("MongoDB connection error:", err); + }); diff --git a/package.json b/package.json index 7b1e40b..d41c21d 100644 --- a/package.json +++ b/package.json @@ -49,4 +49,5 @@ "tailwindcss": "^3.4.14", "vite": "^5.4.10" } + } diff --git a/src/Routes/Login/Login.tsx b/src/Routes/Login/Login.tsx deleted file mode 100644 index ba66cf5..0000000 --- a/src/Routes/Login/Login.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import React, { useState, ChangeEvent, FormEvent, useContext } from "react"; -import axios from "axios"; -import { useNavigate } from "react-router-dom"; -import { ThemeContext } from "../../ThemeContext"; -import type { ThemeContextType } from "../../ThemeContext"; - -const backendUrl = import.meta.env.VITE_BACKEND_URL; - -interface LoginFormData { - email: string; - password: string; -} - -const Login: React.FC = () => { - const [formData, setFormData] = useState({ email: "", password: "" }); - const [message, setMessage] = useState(""); - const [isLoading, setIsLoading] = useState(false); - - const navigate = useNavigate(); - const themeContext = useContext(ThemeContext) as ThemeContextType; - const { mode } = themeContext; - - const handleChange = (e: ChangeEvent) => { - const { name, value } = e.target; - setFormData({ ...formData, [name]: value }); - }; - - const handleSubmit = async (e: FormEvent) => { - e.preventDefault(); - setIsLoading(true); - - try { - const response = await axios.post(`${backendUrl}/api/auth/login`, formData); - setMessage(response.data.message); - - if (response.data.message === "Login successful") { - navigate("/home"); - } - } catch (error: any) { - setMessage(error.response?.data?.message || "Something went wrong"); - } finally { - setIsLoading(false); - } - }; - - return ( -
- {/* Background blobs */} -
-
-
-
-
- - {/* Login Card */} -
-
-
- Logo -
-

- GitHubTracker -

-

Track your GitHub journey

-
- - {/* Form */} -
-

Welcome Back

- -
- - - - - -
- - {message && ( -
- {message} -
- )} -
- - {/* Footer Text */} -
-

- Don't have an account? - - Sign up here - -

-
-
- - {/* Lower gradient */} -
-
- ); -}; - -export default Login; \ No newline at end of file diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index bf67ba3..aa7c58c 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -59,6 +59,14 @@ const Navbar: React.FC = () => { > {mode === "dark" ? "🌞 Light" : "🌙 Dark"} + {/* Uncomment if Signup needed + + Signup + + */}
{/* Mobile Menu Button */} diff --git a/src/hooks/useGitHubAuth.ts b/src/hooks/useGitHubAuth.ts index 4ac6139..5d6c0e7 100644 --- a/src/hooks/useGitHubAuth.ts +++ b/src/hooks/useGitHubAuth.ts @@ -1,5 +1,6 @@ import { useState } from 'react'; import { Octokit } from '@octokit/core'; +import toast from 'react-hot-toast'; export const useGitHubAuth = () => { const [username, setUsername] = useState(''); @@ -7,7 +8,8 @@ export const useGitHubAuth = () => { const [error, setError] = useState(''); const getOctokit = () => { - if (!username || !token) return null; + + if (!username || !token) return; return new Octokit({ auth: token }); }; diff --git a/src/hooks/useGitHubData.ts b/src/hooks/useGitHubData.ts index 9add583..72c60b7 100644 --- a/src/hooks/useGitHubData.ts +++ b/src/hooks/useGitHubData.ts @@ -1,4 +1,5 @@ import { useState, useCallback } from 'react'; +import toast from 'react-hot-toast'; export const useGitHubData = (octokit) => { const [issues, setIssues] = useState([]); @@ -22,8 +23,9 @@ export const useGitHubData = (octokit) => { }; const fetchData = useCallback(async (username) => { - if (!octokit || !username) return; - + if (!octokit || !username) { + toast.error("PAT not found"); return + } setLoading(true); setError(''); @@ -42,11 +44,26 @@ export const useGitHubData = (octokit) => { per_page: 100, }), ]); - setIssues(issuesResponse); setPrs(prsResponse); - } catch (err) { - setError(err.message); + + if (issuesResponse?.length || prsResponse?.length) toast.success( + `Fetched ${issuesResponse.length} issues and ${prsResponse.length} PRs successfully.` + ); + + else toast("⚠️ No issues or PRs found", { icon: "🕵️‍♂️" }); + + + + } catch (err: any) { + if (err.status === 401 || err.status === 403) { + toast.error("Please provide a valid GitHub token "); + } + else if (err.status === 422) toast.error("User not found") + else { + toast.error("something went wrong while fetching data") + } + // setError("Failed to fetched github date") } finally { setLoading(false); } @@ -56,7 +73,7 @@ export const useGitHubData = (octokit) => { issues, prs, loading, - error, + // error, fetchData, }; }; \ No newline at end of file diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 613a32e..855e7c4 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -78,7 +78,7 @@ const Home: React.FC = () => { const filterData = (data: GitHubItem[], filterType: string): GitHubItem[] => { let filtered = [...data]; - if (["open", "closed", "merged"].includes(filterType)) { + if (filterType === "open" || filterType === "closed" || filterType === "merged") { filtered = filtered.filter((item) => filterType === "merged" ? !!item.pull_request?.merged_at @@ -149,7 +149,11 @@ const Home: React.FC = () => { required sx={{ flex: 1 }} /> - @@ -197,7 +201,11 @@ const Home: React.FC = () => { mb: 3, }} > - setTab(newValue)} sx={{ flex: 1 }}> + setTab(newValue)} + sx={{ flex: 1 }} + > @@ -240,53 +248,55 @@ const Home: React.FC = () => { ) : ( - - - - - - Title - Repository - State - Created - - - - {displayData.map((item: GitHubItem) => ( - - - - {item.title} - - - - {item.repository_url.split("/").slice(-1)[0]} - - - {item.pull_request?.merged_at ? "merged" : item.state} - - - {formatDate(item.created_at)} - + + + +
+ + + Title + Repository + State + Created - ))} - -
- -
+ + + {displayData.map((item: GitHubItem) => ( + + + + {item.title} + + + + {item.repository_url.split("/").slice(-1)[0]} + + + {item.pull_request?.merged_at ? "merged" : item.state} + + + {formatDate(item.created_at)} + + + ))} + + + + +
)} From 8885a8b6e864d33ef93970ab202acde6f1185bdd Mon Sep 17 00:00:00 2001 From: Mayur Pal Date: Tue, 22 Jul 2025 17:39:52 +0530 Subject: [PATCH 2/7] remove stuff from admin's advice --- backend/package.json | 1 - backend/server.js | 3 --- src/components/Navbar.tsx | 4 ++-- src/pages/Home/Home.tsx | 16 +++++++++++----- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/backend/package.json b/backend/package.json index 473d028..4b929b3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,7 +4,6 @@ "main": "server.js", "scripts": { "start": "nodemon server.js", - "dev": "nodemon server.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], diff --git a/backend/server.js b/backend/server.js index 5da9e07..9df6ef2 100644 --- a/backend/server.js +++ b/backend/server.js @@ -5,7 +5,6 @@ const passport = require("passport"); const bodyParser = require("body-parser"); require("dotenv").config(); const cors = require("cors"); - // Passport configuration require("./config/passportConfig"); @@ -16,7 +15,6 @@ app.use(cors("*")); // Middleware app.use(bodyParser.json()); -console.log("process.env.SESSION_SECRET: ", process.env.SESSION_SECRET); app.use( session({ secret: process.env.SESSION_SECRET, @@ -31,7 +29,6 @@ app.use(passport.session()); const authRoutes = require("./routes/auth"); app.use("/api/auth", authRoutes); -console.log("process.env.MONGO_URI: ", process.env.MONGO_URI); // Connect to MongoDB mongoose .connect(process.env.MONGO_URI, {}) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index aa7c58c..11a8596 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -22,7 +22,7 @@ const Navbar: React.FC = () => { {/* Desktop Links */} -
+
{
setIsOpen(false)} > diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 855e7c4..55446ae 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -12,7 +12,7 @@ import { TableHead, TableRow, TablePagination, - Link, + Link as MuiLink, CircularProgress, Alert, Tabs, @@ -112,6 +112,12 @@ const Home: React.FC = () => { tab === 0 ? filterData(issues, issueFilter) : filterData(prs, prFilter); const displayData = paginateData(currentData); + // helper to extract "owner/repo" from repository_url + const getRepoName = (url: string) => { + const parts = url.split("/"); + return parts.slice(-2).join("/"); + }; + return ( { {displayData.map((item: GitHubItem) => ( - { sx={{ color: theme.palette.primary.main }} > {item.title} - + - {item.repository_url.split("/").slice(-1)[0]} + {getRepoName(item.repository_url)} {item.pull_request?.merged_at ? "merged" : item.state} @@ -293,7 +299,7 @@ const Home: React.FC = () => { page={page} onPageChange={handleChangePage} rowsPerPage={itemsPerPage} - rowsPerPageOptions={[5]} + rowsPerPageOptions={[10, 25, 50]} /> From 2c0381c0cb19e0da7a073b2c3e3e08b41fb2dada Mon Sep 17 00:00:00 2001 From: Mayur Pal Date: Tue, 22 Jul 2025 17:53:56 +0530 Subject: [PATCH 3/7] remove double quote from server file --- backend/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/server.js b/backend/server.js index 9df6ef2..4aa453d 100644 --- a/backend/server.js +++ b/backend/server.js @@ -5,6 +5,7 @@ const passport = require("passport"); const bodyParser = require("body-parser"); require("dotenv").config(); const cors = require("cors"); + // Passport configuration require("./config/passportConfig"); From ce7871cf850182f737d64ebc2959e59129c4b324 Mon Sep 17 00:00:00 2001 From: Mehul Date: Tue, 29 Jul 2025 12:03:36 +0530 Subject: [PATCH 4/7] revert changes --- backend/server.js | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/backend/server.js b/backend/server.js index 4aa453d..3f19f00 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,44 +1,39 @@ -const express = require("express"); -const mongoose = require("mongoose"); -const session = require("express-session"); -const passport = require("passport"); -const bodyParser = require("body-parser"); -require("dotenv").config(); -const cors = require("cors"); +const express = require('express'); +const mongoose = require('mongoose'); +const session = require('express-session'); +const passport = require('passport'); +const bodyParser = require('body-parser'); +require('dotenv').config(); +const cors = require('cors'); // Passport configuration -require("./config/passportConfig"); +require('./config/passportConfig'); const app = express(); // CORS configuration -app.use(cors("*")); +app.use(cors('*')); // Middleware app.use(bodyParser.json()); -app.use( - session({ +app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, - }) -); +})); app.use(passport.initialize()); app.use(passport.session()); // Routes -const authRoutes = require("./routes/auth"); -app.use("/api/auth", authRoutes); +const authRoutes = require('./routes/auth'); +app.use('/api/auth', authRoutes); // Connect to MongoDB -mongoose - .connect(process.env.MONGO_URI, {}) - .then(() => { - console.log("Connected to MongoDB"); +mongoose.connect(process.env.MONGO_URI, {}).then(() => { + console.log('Connected to MongoDB'); app.listen(process.env.PORT, () => { - console.log(`Server running on port ${process.env.PORT}`); + console.log(`Server running on port ${process.env.PORT}`); }); - }) - .catch((err) => { - console.log("MongoDB connection error:", err); - }); +}).catch((err) => { + console.log('MongoDB connection error:', err); +}); From 9fb01d18944356754126c139fce978b3dc776aa5 Mon Sep 17 00:00:00 2001 From: Mehul Date: Tue, 29 Jul 2025 12:04:42 +0530 Subject: [PATCH 5/7] revert changes backend --- backend/.env.sample | 2 +- backend/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/.env.sample b/backend/.env.sample index 269e5b8..98f9688 100644 --- a/backend/.env.sample +++ b/backend/.env.sample @@ -1,3 +1,3 @@ PORT=5000 MONGO_URI=mongodb://localhost:27017/githubTracker -SESSION_SECRET=your-secret-key \ No newline at end of file +SESSION_SECRET=your-secret-key diff --git a/backend/package.json b/backend/package.json index 4b929b3..53bd64b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "main": "server.js", "scripts": { - "start": "nodemon server.js", + "start": "nodemon server.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], From 2566e44912e2ab032b62570c078603016470669f Mon Sep 17 00:00:00 2001 From: Mehul Date: Tue, 29 Jul 2025 12:12:25 +0530 Subject: [PATCH 6/7] revert all pages --- src/hooks/useGitHubAuth.ts | 6 +- src/hooks/useGitHubData.ts | 31 +++------- src/pages/Home/Home.tsx | 116 ++++++++++++++++--------------------- 3 files changed, 59 insertions(+), 94 deletions(-) diff --git a/src/hooks/useGitHubAuth.ts b/src/hooks/useGitHubAuth.ts index 5d6c0e7..ad3ce52 100644 --- a/src/hooks/useGitHubAuth.ts +++ b/src/hooks/useGitHubAuth.ts @@ -1,6 +1,5 @@ import { useState } from 'react'; import { Octokit } from '@octokit/core'; -import toast from 'react-hot-toast'; export const useGitHubAuth = () => { const [username, setUsername] = useState(''); @@ -8,8 +7,7 @@ export const useGitHubAuth = () => { const [error, setError] = useState(''); const getOctokit = () => { - - if (!username || !token) return; + if (!username || !token) return null; return new Octokit({ auth: token }); }; @@ -22,4 +20,4 @@ export const useGitHubAuth = () => { setError, getOctokit, }; -}; \ No newline at end of file +}; diff --git a/src/hooks/useGitHubData.ts b/src/hooks/useGitHubData.ts index 72c60b7..d4d1161 100644 --- a/src/hooks/useGitHubData.ts +++ b/src/hooks/useGitHubData.ts @@ -1,5 +1,4 @@ import { useState, useCallback } from 'react'; -import toast from 'react-hot-toast'; export const useGitHubData = (octokit) => { const [issues, setIssues] = useState([]); @@ -23,9 +22,8 @@ export const useGitHubData = (octokit) => { }; const fetchData = useCallback(async (username) => { - if (!octokit || !username) { - toast.error("PAT not found"); return - } + if (!octokit || !username) return; + setLoading(true); setError(''); @@ -44,26 +42,11 @@ export const useGitHubData = (octokit) => { per_page: 100, }), ]); + setIssues(issuesResponse); setPrs(prsResponse); - - if (issuesResponse?.length || prsResponse?.length) toast.success( - `Fetched ${issuesResponse.length} issues and ${prsResponse.length} PRs successfully.` - ); - - else toast("⚠️ No issues or PRs found", { icon: "🕵️‍♂️" }); - - - - } catch (err: any) { - if (err.status === 401 || err.status === 403) { - toast.error("Please provide a valid GitHub token "); - } - else if (err.status === 422) toast.error("User not found") - else { - toast.error("something went wrong while fetching data") - } - // setError("Failed to fetched github date") + } catch (err) { + setError(err.message); } finally { setLoading(false); } @@ -73,7 +56,7 @@ export const useGitHubData = (octokit) => { issues, prs, loading, - // error, + error, fetchData, }; -}; \ No newline at end of file +}; diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 55446ae..613a32e 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -12,7 +12,7 @@ import { TableHead, TableRow, TablePagination, - Link as MuiLink, + Link, CircularProgress, Alert, Tabs, @@ -78,7 +78,7 @@ const Home: React.FC = () => { const filterData = (data: GitHubItem[], filterType: string): GitHubItem[] => { let filtered = [...data]; - if (filterType === "open" || filterType === "closed" || filterType === "merged") { + if (["open", "closed", "merged"].includes(filterType)) { filtered = filtered.filter((item) => filterType === "merged" ? !!item.pull_request?.merged_at @@ -112,12 +112,6 @@ const Home: React.FC = () => { tab === 0 ? filterData(issues, issueFilter) : filterData(prs, prFilter); const displayData = paginateData(currentData); - // helper to extract "owner/repo" from repository_url - const getRepoName = (url: string) => { - const parts = url.split("/"); - return parts.slice(-2).join("/"); - }; - return ( { required sx={{ flex: 1 }} /> - @@ -207,11 +197,7 @@ const Home: React.FC = () => { mb: 3, }} > - setTab(newValue)} - sx={{ flex: 1 }} - > + setTab(newValue)} sx={{ flex: 1 }}> @@ -254,55 +240,53 @@ const Home: React.FC = () => { ) : ( - - - - - - - Title - Repository - State - Created + + +
+ + + Title + Repository + State + Created + + + + {displayData.map((item: GitHubItem) => ( + + + + {item.title} + + + + {item.repository_url.split("/").slice(-1)[0]} + + + {item.pull_request?.merged_at ? "merged" : item.state} + + + {formatDate(item.created_at)} + - - - {displayData.map((item: GitHubItem) => ( - - - - {item.title} - - - - {getRepoName(item.repository_url)} - - - {item.pull_request?.merged_at ? "merged" : item.state} - - - {formatDate(item.created_at)} - - - ))} - -
- -
-
+ ))} + + + +
)}
From 0b980eb50818331f1a3eeab63f9280e3b67d7ad6 Mon Sep 17 00:00:00 2001 From: Mehul Date: Tue, 29 Jul 2025 12:13:14 +0530 Subject: [PATCH 7/7] revert nav --- src/components/Navbar.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 11a8596..bf67ba3 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -22,7 +22,7 @@ const Navbar: React.FC = () => { {/* Desktop Links */} -
+
{ > {mode === "dark" ? "🌞 Light" : "🌙 Dark"} - {/* Uncomment if Signup needed - - Signup - - */}
{/* Mobile Menu Button */} @@ -99,7 +91,7 @@ const Navbar: React.FC = () => {
setIsOpen(false)} >