From 113872bb6592b4ffcce80b24ab8f42f32fe068aa Mon Sep 17 00:00:00 2001 From: indresh404 Date: Sun, 24 May 2026 15:50:38 +0530 Subject: [PATCH 1/5] added contributors ranking --- src/app/page.tsx | 252 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 251 insertions(+), 1 deletion(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index f6dd299a..32b11592 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,6 +3,106 @@ import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth"; import { redirect } from "next/navigation"; +interface Contributor { + login: string; + avatar_url: string; + html_url: string; + contributions: number; +} + +const FALLBACK_CONTRIBUTORS: Contributor[] = [ + { + login: "Priyanshu-byte-coder", + avatar_url: "https://github.com/Priyanshu-byte-coder.png?size=150", + html_url: "https://github.com/Priyanshu-byte-coder", + contributions: 154, + }, + { + login: "devendra-w", + avatar_url: "https://github.com/devendra-w.png?size=150", + html_url: "https://github.com/devendra-w", + contributions: 42, + }, + { + login: "pariharakanshi33-svg", + avatar_url: "https://github.com/pariharakanshi33-svg.png?size=150", + html_url: "https://github.com/pariharakanshi33-svg", + contributions: 28, + }, + { + login: "sanrishi", + avatar_url: "https://github.com/sanrishi.png?size=150", + html_url: "https://github.com/sanrishi", + contributions: 19, + }, + { + login: "indresh404", + avatar_url: "https://github.com/indresh404.png?size=150", + html_url: "https://github.com/indresh404", + contributions: 15, + }, + { + login: "AaravCode", + avatar_url: "https://github.com/AaravCode.png?size=150", + html_url: "https://github.com/AaravCode", + contributions: 12, + }, + { + login: "Siddharth-07", + avatar_url: "https://github.com/Siddharth-07.png?size=150", + html_url: "https://github.com/Siddharth-07", + contributions: 8, + }, + { + login: "Rohan-dev", + avatar_url: "https://github.com/Rohan-dev.png?size=150", + html_url: "https://github.com/Rohan-dev", + contributions: 6, + }, + { + login: "Anjali-Sharma", + avatar_url: "https://github.com/Anjali-Sharma.png?size=150", + html_url: "https://github.com/Anjali-Sharma", + contributions: 4, + }, + { + login: "Neha-Gupta", + avatar_url: "https://github.com/Neha-Gupta.png?size=150", + html_url: "https://github.com/Neha-Gupta", + contributions: 2, + }, +]; + +async function fetchContributors(): Promise { + try { + const res = await fetch( + "https://api.github.com/repos/Priyanshu-byte-coder/devtrack/contributors", + { + headers: { + "User-Agent": "DevTrack-App", + }, + next: { revalidate: 3600 }, + } + ); + if (!res.ok) { + throw new Error(`GitHub API error: ${res.status}`); + } + const data = await res.json(); + if (Array.isArray(data)) { + return data.map((item: any) => ({ + login: item.login, + avatar_url: item.avatar_url, + html_url: item.html_url, + contributions: item.contributions, + })); + } + return []; + } catch (error) { + console.error("Failed to fetch contributors from GitHub, using fallback:", error); + return []; + } +} + export default async function HomePage() { const session = await getServerSession(authOptions); @@ -34,10 +134,19 @@ export default async function HomePage() { }, ]; + const apiContributors = await fetchContributors(); + const contributors = apiContributors.length > 0 ? apiContributors : FALLBACK_CONTRIBUTORS; + const sortedContributors = [...contributors].sort((a, b) => b.contributions - a.contributions); + const top3 = sortedContributors.slice(0, 3); + const rest = sortedContributors.slice(3); + const firstPlace = top3[0]; + const secondPlace = top3[1]; + const thirdPlace = top3[2]; + return (
-

+

DevTrack

@@ -86,6 +195,147 @@ export default async function HomePage() { ))}

+ +
+

+ Top Contributors +

+

+ Meet the developers who are actively shaping DevTrack. Thank you for making our open-source productivity platform grow! +

+ + {/* Podium for top 3 */} +
+ {/* 2nd Place */} + {secondPlace && ( +
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {secondPlace.login} +
+ 2nd +
+
+
+ + @{secondPlace.login} + + + {secondPlace.contributions} commits + +
+
+ )} + + {/* 1st Place */} + {firstPlace && ( +
+
👑
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {firstPlace.login} +
+ 1st +
+
+
+ + @{firstPlace.login} + + + {firstPlace.contributions} commits + +
+
+ )} + + {/* 3rd Place */} + {thirdPlace && ( +
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {thirdPlace.login} +
+ 3rd +
+
+
+ + @{thirdPlace.login} + + + {thirdPlace.contributions} commits + +
+
+ )} +
+ + {/* Rest of Contributors Grid */} + {rest.length > 0 && ( +
+ {rest.map((contrib, index) => { + const rank = index + 4; + return ( +
+ + #{rank} + + {/* eslint-disable-next-line @next/next/no-img-element */} + {contrib.login} +
+ + @{contrib.login} + +

+ {contrib.contributions} commits +

+
+
+ ); + })} +
+ )} +
); } From f92a4b6baae08b3283d32feb74565095eb37edbc Mon Sep 17 00:00:00 2001 From: indresh404 Date: Sun, 24 May 2026 16:09:50 +0530 Subject: [PATCH 2/5] improved UI --- src/app/page.tsx | 80 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 32b11592..36590380 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -143,8 +143,27 @@ export default async function HomePage() { const secondPlace = top3[1]; const thirdPlace = top3[2]; + const isFirstCreator = firstPlace?.login === "indresh404"; + const isSecondCreator = secondPlace?.login === "indresh404"; + const isThirdCreator = thirdPlace?.login === "indresh404"; + return (
+ +

DevTrack @@ -201,14 +220,16 @@ export default async function HomePage() { Top Contributors

- Meet the developers who are actively shaping DevTrack. Thank you for making our open-source productivity platform grow! + Meet the developers who are actively shaping DevTrack. Thank you for making our open-source productivity platform grow! Section built with ❤️ by @indresh404 (Leaderboard Creator).

{/* Podium for top 3 */}
{/* 2nd Place */} {secondPlace && ( -
+
{/* eslint-disable-next-line @next/next/no-img-element */} @{secondPlace.login} + {isSecondCreator && ( + + Created by + + )} {secondPlace.contributions} commits @@ -238,7 +264,9 @@ export default async function HomePage() { {/* 1st Place */} {firstPlace && ( -
+
👑
{/* eslint-disable-next-line @next/next/no-img-element */} @@ -260,6 +288,11 @@ export default async function HomePage() { > @{firstPlace.login} + {isFirstCreator && ( + + Created by + + )} {firstPlace.contributions} commits @@ -269,7 +302,9 @@ export default async function HomePage() { {/* 3rd Place */} {thirdPlace && ( -
+
{/* eslint-disable-next-line @next/next/no-img-element */} @{thirdPlace.login} + {isThirdCreator && ( + + Created by + + )} {thirdPlace.contributions} commits @@ -303,10 +343,15 @@ export default async function HomePage() {
{rest.map((contrib, index) => { const rank = index + 4; + const isCreator = contrib.login === "indresh404"; return (
#{rank} @@ -318,14 +363,21 @@ export default async function HomePage() { className="w-10 h-10 rounded-full border border-[var(--border)] object-cover" />
- - @{contrib.login} - +
+ + @{contrib.login} + + {isCreator && ( + + Created by + + )} +

{contrib.contributions} commits

From 6720bc51f36a30c890c5ddecad2759f3f5caa882 Mon Sep 17 00:00:00 2001 From: indresh404 Date: Sun, 24 May 2026 18:58:28 +0530 Subject: [PATCH 3/5] fixed issues --- src/app/page.tsx | 390 +++++++++++++++++------------------------------ 1 file changed, 143 insertions(+), 247 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index c2def69c..b6e284a1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,82 +10,27 @@ interface Contributor { contributions: number; } -const FALLBACK_CONTRIBUTORS: Contributor[] = [ - { - login: "Priyanshu-byte-coder", - avatar_url: "https://github.com/Priyanshu-byte-coder.png?size=150", - html_url: "https://github.com/Priyanshu-byte-coder", - contributions: 154, - }, - { - login: "devendra-w", - avatar_url: "https://github.com/devendra-w.png?size=150", - html_url: "https://github.com/devendra-w", - contributions: 42, - }, - { - login: "pariharakanshi33-svg", - avatar_url: "https://github.com/pariharakanshi33-svg.png?size=150", - html_url: "https://github.com/pariharakanshi33-svg", - contributions: 28, - }, - { - login: "sanrishi", - avatar_url: "https://github.com/sanrishi.png?size=150", - html_url: "https://github.com/sanrishi", - contributions: 19, - }, - { - login: "indresh404", - avatar_url: "https://github.com/indresh404.png?size=150", - html_url: "https://github.com/indresh404", - contributions: 15, - }, - { - login: "AaravCode", - avatar_url: "https://github.com/AaravCode.png?size=150", - html_url: "https://github.com/AaravCode", - contributions: 12, - }, - { - login: "Siddharth-07", - avatar_url: "https://github.com/Siddharth-07.png?size=150", - html_url: "https://github.com/Siddharth-07", - contributions: 8, - }, - { - login: "Rohan-dev", - avatar_url: "https://github.com/Rohan-dev.png?size=150", - html_url: "https://github.com/Rohan-dev", - contributions: 6, - }, - { - login: "Anjali-Sharma", - avatar_url: "https://github.com/Anjali-Sharma.png?size=150", - html_url: "https://github.com/Anjali-Sharma", - contributions: 4, - }, - { - login: "Neha-Gupta", - avatar_url: "https://github.com/Neha-Gupta.png?size=150", - html_url: "https://github.com/Neha-Gupta", - contributions: 2, - }, -]; - async function fetchContributors(): Promise { try { + const token = process.env.GITHUB_TOKEN; + const headers: Record = { + "User-Agent": "DevTrack-App", + Accept: "application/vnd.github+json", + }; + if (token) { + headers.Authorization = `Bearer ${token}`; + } + const res = await fetch( "https://api.github.com/repos/Priyanshu-byte-coder/devtrack/contributors", { - headers: { - "User-Agent": "DevTrack-App", - }, + headers, next: { revalidate: 3600 }, } ); if (!res.ok) { - throw new Error(`GitHub API error: ${res.status}`); + console.error(`GitHub API error: ${res.status}`); + return []; } const data = await res.json(); if (Array.isArray(data)) { @@ -98,7 +43,7 @@ async function fetchContributors(): Promise { } return []; } catch (error) { - console.error("Failed to fetch contributors from GitHub, using fallback:", error); + console.error("Failed to fetch contributors from GitHub:", error); return []; } } @@ -134,8 +79,7 @@ export default async function HomePage() { }, ]; - const apiContributors = await fetchContributors(); - const contributors = apiContributors.length > 0 ? apiContributors : FALLBACK_CONTRIBUTORS; + const contributors = await fetchContributors(); const sortedContributors = [...contributors].sort((a, b) => b.contributions - a.contributions); const top3 = sortedContributors.slice(0, 3); const rest = sortedContributors.slice(3); @@ -143,29 +87,10 @@ export default async function HomePage() { const secondPlace = top3[1]; const thirdPlace = top3[2]; - const isFirstCreator = firstPlace?.login === "indresh404"; - const isSecondCreator = secondPlace?.login === "indresh404"; - const isThirdCreator = thirdPlace?.login === "indresh404"; - return (
- -
-

+

DevTrack

@@ -221,179 +146,150 @@ export default async function HomePage() {
-
-

- Top Contributors -

-

- Meet the developers who are actively shaping DevTrack. Thank you for making our open-source productivity platform grow! Section built with ❤️ by @indresh404 (Leaderboard Creator). -

+ {contributors.length > 0 && ( +
+

+ Top Contributors +

+

+ Meet the developers who are actively shaping DevTrack. Thank you for making our open-source productivity platform grow! +

- {/* Podium for top 3 */} -
- {/* 2nd Place */} - {secondPlace && ( -
-
- {/* eslint-disable-next-line @next/next/no-img-element */} - {secondPlace.login} -
- 2nd + {/* Podium for top 3 */} +
+ {/* 2nd Place */} + {secondPlace && ( +
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {secondPlace.login} +
+ 2nd +
-
-
- - @{secondPlace.login} - - {isSecondCreator && ( - - Created by +
+ + @{secondPlace.login} + + + {secondPlace.contributions} commits - )} - - {secondPlace.contributions} commits - -
-
- )} - - {/* 1st Place */} - {firstPlace && ( -
-
👑
-
- {/* eslint-disable-next-line @next/next/no-img-element */} - {firstPlace.login} -
- 1st
-
- - @{firstPlace.login} - - {isFirstCreator && ( - - Created by - - )} - - {firstPlace.contributions} commits - -
-
- )} + )} - {/* 3rd Place */} - {thirdPlace && ( -
-
- {/* eslint-disable-next-line @next/next/no-img-element */} - {thirdPlace.login} -
- 3rd + {/* 1st Place */} + {firstPlace && ( +
+
👑
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {firstPlace.login} +
+ 1st +
-
-
- - @{thirdPlace.login} - - {isThirdCreator && ( - - Created by +
+ + @{firstPlace.login} + + + {firstPlace.contributions} commits - )} - - {thirdPlace.contributions} commits - +
-
- )} -
+ )} - {/* Rest of Contributors Grid */} - {rest.length > 0 && ( -
- {rest.map((contrib, index) => { - const rank = index + 4; - const isCreator = contrib.login === "indresh404"; - return ( -
- - #{rank} - + {/* 3rd Place */} + {thirdPlace && ( +
+
{/* eslint-disable-next-line @next/next/no-img-element */} {contrib.login} -
-
- - @{contrib.login} - - {isCreator && ( - - Created by - - )} -
-

- {contrib.contributions} commits -

+
+ 3rd
- ); - })} +
+ + @{thirdPlace.login} + + + {thirdPlace.contributions} commits + +
+
+ )}
- )} -
+ + {/* Rest of Contributors Grid */} + {rest.length > 0 && ( +
+ {rest.map((contrib, index) => { + const rank = index + 4; + return ( +
+ + #{rank} + + {/* eslint-disable-next-line @next/next/no-img-element */} + {contrib.login} +
+ +

+ {contrib.contributions} commits +

+
+
+ ); + })} +
+ )} +
+ )}
); } From f397142bb5f97471520f70461f2654e9062518e6 Mon Sep 17 00:00:00 2001 From: indresh404 Date: Sun, 24 May 2026 22:31:57 +0530 Subject: [PATCH 4/5] fixed E2E issue --- e2e/dashboard-widgets.spec.js | 58 ++++++++++------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/e2e/dashboard-widgets.spec.js b/e2e/dashboard-widgets.spec.js index 40ab6562..0a09bef1 100644 --- a/e2e/dashboard-widgets.spec.js +++ b/e2e/dashboard-widgets.spec.js @@ -21,24 +21,26 @@ test.beforeEach(async ({ page }) => { { name: "next-auth.session-token", value: sessionToken, - domain: "127.0.0.1", - path: "/", - httpOnly: true, - sameSite: "Lax", - secure: false, - expires: Math.floor(Date.now() / 1000) + 60 * 60, + url: "http://127.0.0.1:3000", }, ]); - await page.route("**/api/auth/session", async (route) => { + await page.route("**/api/goals", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify({ - user: { name: "Playwright User", email: "playwright@example.com" }, - githubLogin: "playwright-user", - githubId: "12345", - accessToken: "test-token", - expires: "2099-01-01T00:00:00.000Z", + goals: [ + { + id: "goal-1", + title: "Make 10 commits", + target: 10, + current: 4, + unit: "commits", + recurrence: "weekly", + period_start: "2026-05-18", + last_synced_at: null, + }, + ], }), }); }); @@ -65,34 +67,6 @@ test.beforeEach(async ({ page }) => { }); }); - await page.route("**/api/goals", async (route) => { - if (route.request().method() === "POST") { - await route.fulfill({ - contentType: "application/json", - status: 201, - body: JSON.stringify({ ok: true }), - }); - return; - } - - await route.fulfill({ - contentType: "application/json", - body: JSON.stringify({ - goals: [ - { - id: "goal-1", - title: "Make 10 commits", - target: 10, - current: 4, - unit: "commits", - recurrence: "weekly", - period_start: "2026-05-18", - }, - ], - }), - }); - }); - const metricRoutes = [ "**/api/metrics/prs**", "**/api/metrics/pr-breakdown**", @@ -122,10 +96,10 @@ test.beforeEach(async ({ page }) => { test("dashboard widgets render with mocked metrics", async ({ page }) => { await page.goto("/dashboard", { waitUntil: "load" }); await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible({ timeout: 30000 }); + await page.waitForLoadState("networkidle"); await expect(page.getByRole("heading", { name: "Your Commits" })).toBeVisible({ timeout: 10000 }); await expect(page.getByRole("heading", { name: "PR Analytics" })).toBeVisible({ timeout: 10000 }); - await expect(page.getByRole("heading", { name: "Goals" })).toBeVisible({ timeout: 10000 }); - await expect(page.getByText("Make 10 commits")).toBeVisible({ timeout: 10000 }); + await expect(page.getByText("Make 10 commits", { exact: true })).toBeVisible({ timeout: 20000 }); }); test("contribution graph range buttons request a new range", async ({ page }) => { From 7bba64c0b1b07167ac753e852cb10c23e96d34b4 Mon Sep 17 00:00:00 2001 From: indresh404 Date: Sun, 24 May 2026 22:34:04 +0530 Subject: [PATCH 5/5] fixed E2E issue --- e2e/dashboard-widgets.spec.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/e2e/dashboard-widgets.spec.js b/e2e/dashboard-widgets.spec.js index 0a09bef1..0ff5f3f4 100644 --- a/e2e/dashboard-widgets.spec.js +++ b/e2e/dashboard-widgets.spec.js @@ -45,6 +45,16 @@ test.beforeEach(async ({ page }) => { }); }); + await page.route("**/api/goals/sync", async (route) => { + await route.fulfill({ + contentType: "application/json", + body: JSON.stringify({ + synced: true, + updated: 1, + }), + }); + }); + await page.route("**/api/user/settings", async (route) => { await route.fulfill({ contentType: "application/json",