Skip to content

Commit 0db6fff

Browse files
authored
Merge branch 'main' into HomeUI
2 parents aa3cafd + 251b486 commit 0db6fff

16 files changed

Lines changed: 710 additions & 221 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Auto Assign Issue Author
2+
3+
on:
4+
issues:
5+
types: [opened]
6+
7+
jobs:
8+
auto-assign:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
issues: write # Required for assigning issues
12+
13+
steps:
14+
- name: Assign issue to creator
15+
uses: actions/github-script@v7
16+
with:
17+
script: |
18+
const issueCreator = context.payload.issue.user.login;
19+
const issueNumber = context.payload.issue.number;
20+
21+
await github.rest.issues.addAssignees({
22+
owner: context.repo.owner,
23+
repo: context.repo.repo,
24+
issue_number: issueNumber,
25+
assignees: [issueCreator],
26+
});
27+
28+
console.log(`Assigned issue #${issueNumber} to @${issueCreator}`);

.github/workflows/greetings.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Greetings
2+
3+
on: [pull_request_target]
4+
5+
jobs:
6+
greeting:
7+
runs-on: ubuntu-latest
8+
permissions:
9+
issues: write
10+
pull-requests: write
11+
steps:
12+
- uses: actions/first-interaction@v1
13+
with:
14+
repo-token: ${{ secrets.GITHUB_TOKEN }}
15+
pr-message: " 🎉 Thank you @${{ github.actor }} for your contribution. Please make sure your PR follows https://github.com/GitMetricsLab/github_tracker/blob/main/CONTRIBUTING.md#-pull-request-guidelines"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Post-PR Merge Thank You
2+
3+
on:
4+
pull_request_target:
5+
types: [closed] # Trigger when a PR is closed
6+
7+
permissions:
8+
issues: write
9+
pull-requests: write
10+
11+
jobs:
12+
post_merge_message:
13+
if: github.event.pull_request.merged == true # Only run if the PR was merged
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Post thank you message
18+
uses: actions/github-script@v7
19+
with:
20+
github-token: ${{ secrets.GITHUB_TOKEN }} # Ensure token is used
21+
script: |
22+
const prNumber = context.payload.pull_request.number;
23+
const owner = context.repo.owner;
24+
const repo = context.repo.repo;
25+
26+
// Post a thank you message upon PR merge
27+
await github.rest.issues.createComment({
28+
owner: owner,
29+
repo: repo,
30+
issue_number: prNumber,
31+
body: `🎉🎉 Thank you for your contribution! Your PR #${prNumber} has been merged! 🎉🎉`
32+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Unassign Issues with No PR After 5 Days
2+
3+
on:
4+
schedule:
5+
- cron: '0 2 * * *' # Runs daily at 2 AM UTC
6+
workflow_dispatch: # Manual trigger support
7+
8+
jobs:
9+
unassign-stale-issues:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Check for stale assigned issues
13+
uses: actions/github-script@v7
14+
with:
15+
github-token: ${{ secrets.PAT }}
16+
script: |
17+
const daysBeforeUnassign = 5;
18+
const cutoffDate = new Date();
19+
cutoffDate.setDate(cutoffDate.getDate() - daysBeforeUnassign);
20+
21+
const issues = await github.paginate(github.rest.issues.listForRepo, {
22+
owner: context.repo.owner,
23+
repo: context.repo.repo,
24+
state: 'open',
25+
assignee: '*'
26+
});
27+
28+
for (const issue of issues) {
29+
if (issue.pull_request) continue; // Skip PRs
30+
31+
const createdAt = new Date(issue.created_at);
32+
const assigned = issue.assignees.length > 0;
33+
34+
if (assigned && createdAt < cutoffDate) {
35+
// Check if there's a linked PR via timeline
36+
const timeline = await github.paginate(github.rest.issues.listEventsForTimeline, {
37+
owner: context.repo.owner,
38+
repo: context.repo.repo,
39+
issue_number: issue.number,
40+
mediaType: {
41+
previews: ["mockingbird"]
42+
}
43+
});
44+
45+
const hasLinkedPR = timeline.some(event => event.event === 'connected');
46+
47+
if (!hasLinkedPR) {
48+
console.log(`Unassigning issue #${issue.number} (no PR in 5 days)`);
49+
await github.rest.issues.removeAssignees({
50+
owner: context.repo.owner,
51+
repo: context.repo.repo,
52+
issue_number: issue.number,
53+
assignees: issue.assignees.map(user => user.login)
54+
});
55+
56+
await github.rest.issues.createComment({
57+
owner: context.repo.owner,
58+
repo: context.repo.repo,
59+
issue_number: issue.number,
60+
body: `⏰ This issue was automatically unassigned because no pull request was raised within 5 days. Feel free to reassign if you're still working on it.`
61+
});
62+
}
63+
}
64+
}

README.md

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,27 +82,6 @@ $ npm i
8282
$ npm start
8383
```
8484

85-
---
86-
87-
### 🌟 Coming Soon
88-
- Add options to track stars, followers, following
89-
- Add options to track engagements (e.g. comments, closing, opening and merging PRs)
90-
- **👥 Team Monitoring**: Track activities of your team members in one place.
91-
- **📊 Custom Dashboards**: Create personalized dashboards to visualize the data that matters to you.
92-
93-
---
94-
95-
# 👀 Our Contributors
96-
97-
- We extend our heartfelt gratitude for your invaluable contribution to our project.
98-
- Make sure you show some love by giving ⭐ to our repository.
99-
100-
<div align="center">
101-
<a href="https://github.com/mehul-m-prajapati/github_tracker">
102-
<img src="https://contrib.rocks/image?repo=mehul-m-prajapati/github_tracker&&max=1000" />
103-
</a>
104-
</div>
105-
10685
## 🧪 Backend Unit & Integration Testing with Jasmine
10786

10887
This project uses the Jasmine framework for backend unit and integration tests. The tests cover:
@@ -156,4 +135,13 @@ spec_files: [
156135

157136
---
158137

159-
For any questions or to add more tests (including frontend), see the contribution guidelines or open an issue.
138+
# 👀 Our Contributors
139+
140+
- We extend our heartfelt gratitude for your invaluable contribution to our project.
141+
- Make sure you show some love by giving ⭐ to our repository.
142+
143+
<div align="center">
144+
<a href="https://github.com/mehul-m-prajapati/github_tracker">
145+
<img src="https://contrib.rocks/image?repo=mehul-m-prajapati/github_tracker&&max=1000" />
146+
</a>
147+
</div>

src/App.tsx

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import Navbar from "./components/Navbar";
22
import Footer from "./components/Footer";
3-
import ScrollProgressBar from './components/ScrollProgressBar';
3+
import ScrollProgressBar from "./components/ScrollProgressBar";
44
import { Toaster } from "react-hot-toast";
5-
65
import Router from "./Routes/Router";
6+
import ThemeWrapper from "./ThemeContext"; // ✅ import your wrapper
77

88
function App() {
99
return (
10-
10+
<ThemeWrapper>
1111
<div className="relative flex flex-col min-h-screen">
12-
<ScrollProgressBar/>
12+
<ScrollProgressBar />
1313

1414
{/* Navbar */}
1515
<Navbar />
1616

1717
{/* Main content */}
18-
<main className="flex-grow bg-gray-50 flex justify-center items-center">
19-
<Router/>
18+
<main className="flex-grow bg-gray-50 dark:bg-gray-900 flex justify-center items-center">
19+
<Router />
2020
</main>
2121

2222
{/* Footer */}
@@ -27,24 +27,21 @@ function App() {
2727
reverseOrder={false}
2828
gutter={8}
2929
containerClassName="mt-12"
30-
containerStyle={{}}
3130
toastOptions={{
32-
className: 'bg-white',
31+
className: "bg-white dark:bg-gray-800 text-black dark:text-white",
3332
duration: 5000,
34-
//removeDelay: 1000,
35-
3633
success: {
3734
duration: 3000,
3835
iconTheme: {
39-
primary: 'green',
40-
secondary: 'white',
36+
primary: "green",
37+
secondary: "white",
4138
},
4239
},
4340
}}
4441
/>
4542
</div>
46-
43+
</ThemeWrapper>
4744
);
4845
}
4946

50-
export default App;
47+
export default App;

src/Routes/Login/Login.tsx

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import React, { useState, ChangeEvent, FormEvent, useContext } from "react";
2+
import axios from "axios";
3+
import { useNavigate } from "react-router-dom";
4+
import { ThemeContext } from "../../ThemeContext";
5+
import type { ThemeContextType } from "../../ThemeContext";
6+
7+
const backendUrl = import.meta.env.VITE_BACKEND_URL;
8+
9+
interface LoginFormData {
10+
email: string;
11+
password: string;
12+
}
13+
14+
const Login: React.FC = () => {
15+
const [formData, setFormData] = useState<LoginFormData>({ email: "", password: "" });
16+
const [message, setMessage] = useState<string>("");
17+
const [isLoading, setIsLoading] = useState<boolean>(false);
18+
19+
const navigate = useNavigate();
20+
const themeContext = useContext(ThemeContext) as ThemeContextType;
21+
const { mode } = themeContext;
22+
23+
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
24+
const { name, value } = e.target;
25+
setFormData({ ...formData, [name]: value });
26+
};
27+
28+
const handleSubmit = async (e: FormEvent) => {
29+
e.preventDefault();
30+
setIsLoading(true);
31+
32+
try {
33+
const response = await axios.post(`${backendUrl}/api/auth/login`, formData);
34+
setMessage(response.data.message);
35+
36+
if (response.data.message === "Login successful") {
37+
navigate("/home");
38+
}
39+
} catch (error: any) {
40+
setMessage(error.response?.data?.message || "Something went wrong");
41+
} finally {
42+
setIsLoading(false);
43+
}
44+
};
45+
46+
return (
47+
<div
48+
className={`min-h-screen w-full flex items-center justify-center relative overflow-hidden ${
49+
mode === "dark"
50+
? "bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900"
51+
: "bg-gradient-to-br from-slate-100 via-purple-100 to-slate-100"
52+
}`}
53+
>
54+
{/* Background blobs */}
55+
<div className="absolute inset-0 pointer-events-none">
56+
<div className={`absolute -top-40 -right-40 w-96 h-96 ${mode === "dark" ? "bg-purple-500" : "bg-purple-300"} rounded-full blur-3xl opacity-30 animate-pulse`} />
57+
<div className={`absolute -bottom-40 -left-40 w-96 h-96 ${mode === "dark" ? "bg-blue-500" : "bg-blue-300"} rounded-full blur-3xl opacity-30 animate-pulse`} />
58+
<div className={`absolute top-40 left-40 w-96 h-96 ${mode === "dark" ? "bg-pink-500" : "bg-pink-300"} rounded-full blur-3xl opacity-30 animate-pulse`} />
59+
</div>
60+
61+
{/* Login Card */}
62+
<div className="relative w-full max-w-md px-6">
63+
<div className="text-center mb-10">
64+
<div className={`inline-flex items-center justify-center w-20 h-20 bg-white rounded-3xl mb-6 shadow-2xl overflow-hidden`}>
65+
<img src="/crl-icon.png" alt="Logo" className="w-14 h-14 object-contain" />
66+
</div>
67+
<h1 className={`text-4xl font-bold bg-clip-text text-transparent mb-2 ${
68+
mode === "dark" ? "bg-gradient-to-r from-purple-300 via-pink-300 to-indigo-300" : "bg-gradient-to-r from-purple-600 via-pink-600 to-indigo-600"
69+
}`}>
70+
GitHubTracker
71+
</h1>
72+
<p className={`${mode === "dark" ? "text-slate-300" : "text-gray-700"} text-lg font-medium`}>Track your GitHub journey</p>
73+
</div>
74+
75+
{/* Form */}
76+
<div className={`rounded-3xl p-10 shadow-2xl border ${
77+
mode === "dark" ? "bg-white/10 backdrop-blur-xl border-white/20 text-white" : "bg-white border-gray-200 text-black"
78+
}`}>
79+
<h2 className={`text-2xl font-bold text-center mb-8 ${mode === "dark" ? "text-white" : "text-gray-800"}`}>Welcome Back</h2>
80+
81+
<form onSubmit={handleSubmit} className="space-y-6">
82+
<input
83+
type="email"
84+
name="email"
85+
placeholder="Enter your email"
86+
value={formData.email}
87+
onChange={handleChange}
88+
autoComplete="username"
89+
required
90+
className={`w-full px-4 py-4 rounded-2xl focus:outline-none transition-all ${
91+
mode === "dark"
92+
? "bg-white/5 border border-white/10 text-white placeholder-slate-400 focus:ring-2 focus:ring-purple-500"
93+
: "bg-gray-100 border border-gray-300 text-gray-900 placeholder-gray-500 focus:ring-2 focus:ring-purple-400"
94+
}`}
95+
/>
96+
97+
<input
98+
type="password"
99+
name="password"
100+
autoComplete="current-password"
101+
placeholder="Enter your password"
102+
value={formData.password}
103+
onChange={handleChange}
104+
required
105+
className={`w-full px-4 py-4 rounded-2xl focus:outline-none transition-all ${
106+
mode === "dark"
107+
? "bg-white/5 border border-white/10 text-white placeholder-slate-400 focus:ring-2 focus:ring-purple-500"
108+
: "bg-gray-100 border border-gray-300 text-gray-900 placeholder-gray-500 focus:ring-2 focus:ring-purple-400"
109+
}`}
110+
/>
111+
112+
<button
113+
type="submit"
114+
disabled={isLoading}
115+
className="w-full bg-gradient-to-r from-purple-600 via-pink-600 to-indigo-600 text-white py-4 px-6 rounded-2xl font-semibold focus:ring-4 focus:ring-purple-500/50 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
116+
>
117+
{isLoading ? "Signing in..." : "Sign In"}
118+
</button>
119+
</form>
120+
121+
{message && (
122+
<div className={`mt-6 p-4 rounded-2xl text-center text-sm font-medium ${
123+
message === "Login successful"
124+
? "bg-green-500/20 text-green-300 border border-green-500/30"
125+
: "bg-red-500/20 text-red-300 border border-red-500/30"
126+
}`}>
127+
{message}
128+
</div>
129+
)}
130+
</div>
131+
132+
{/* Footer Text */}
133+
<div className="text-center mt-8 pb-8">
134+
<p className={`${mode === "dark" ? "text-slate-500" : "text-gray-600"} text-sm`}>
135+
Don't have an account?
136+
<a href="#" className="ml-1 text-purple-400 hover:text-purple-300 transition-colors duration-300">
137+
Sign up here
138+
</a>
139+
</p>
140+
</div>
141+
</div>
142+
143+
{/* Lower gradient */}
144+
<div className={`${mode === "dark" ? "from-slate-900" : "from-slate-100"} absolute bottom-0 left-0 w-full h-20 bg-gradient-to-t to-transparent`} />
145+
</div>
146+
);
147+
};
148+
149+
export default Login;

0 commit comments

Comments
 (0)