From 4e5a1516411e636d3e3f611fb1abeeb8a384a456 Mon Sep 17 00:00:00 2001 From: Harshita Nagpal Date: Sun, 24 May 2026 22:32:39 +0530 Subject: [PATCH 1/5] feat(ui): modernize interface with light blue and white theme (#924) --- src/app/auth/signin/page.tsx | 42 +---------- src/app/dashboard/page.tsx | 4 +- src/app/globals.css | 96 ++++++++++++++++------- src/app/layout.tsx | 10 ++- src/app/leaderboard/page.tsx | 8 +- src/app/page.tsx | 117 +++++++++++++++-------------- src/app/u/[username]/page.tsx | 12 +-- src/components/DashboardHeader.tsx | 20 ++--- src/components/Footer.tsx | 4 +- src/components/StatsCard.tsx | 40 +++++----- src/components/ThemeContext.tsx | 6 +- 11 files changed, 179 insertions(+), 180 deletions(-) diff --git a/src/app/auth/signin/page.tsx b/src/app/auth/signin/page.tsx index 62f39d22..f3dc2295 100644 --- a/src/app/auth/signin/page.tsx +++ b/src/app/auth/signin/page.tsx @@ -37,21 +37,9 @@ function MouseSpotlight() { export default function SignInPage() { return ( -
- - - {/* Subtle grid */} +
+
+
signIn("github", { callbackUrl: "/dashboard" })} - style={{ - width: "100%", - display: "inline-flex", alignItems: "center", justifyContent: "center", - gap: 10, - background: A, color: "#000", - fontFamily: MONO, fontWeight: 600, fontSize: 14, - padding: "14px 24px", borderRadius: 6, - border: "none", cursor: "pointer", - transition: "background 0.2s, transform 0.1s", - marginBottom: 20, - }} - onMouseEnter={(e) => { - (e.currentTarget as HTMLButtonElement).style.background = "#fff"; - }} - onMouseLeave={(e) => { - (e.currentTarget as HTMLButtonElement).style.background = A; - }} - onMouseDown={(e) => { - (e.currentTarget as HTMLButtonElement).style.transform = "scale(0.97)"; - }} - onMouseUp={(e) => { - (e.currentTarget as HTMLButtonElement).style.transform = "scale(1)"; - }} + className="primary-button relative w-full inline-flex items-center justify-center gap-3 rounded-xl py-3 font-semibold" > diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 159cf9e2..e0671e04 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -39,12 +39,12 @@ export default async function DashboardPage() { if (session.error === "TokenRevoked") redirect("/"); return ( -
+
Settings diff --git a/src/app/globals.css b/src/app/globals.css index cff55606..2d1d27d4 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,58 +4,98 @@ :root { color-scheme: light; - --background: #f8fafc; - --foreground: #0f172a; - --muted-foreground: #475569; - --card: #ffffff; - --card-foreground: #0f172a; - --card-muted: #e2e8f0; - --border: #cbd5e1; - --accent: #6366f1; + --background: #ffffff; + --foreground: #111827; + --muted-foreground: #4b5563; + --card: #f8fafc; + --card-foreground: #111827; + --card-muted: #eff6ff; + --border: #e5e7eb; + --accent: #3b82f6; + --accent-secondary: #60a5fa; --success: #10b981; --warning: #f59e0b; --destructive: #ef4444; - --accent-soft: rgba(99, 102, 241, 0.15); + --accent-soft: rgba(59, 130, 246, 0.14); --accent-foreground: #ffffff; - --control: #e2e8f0; - --control-hover: #cbd5e1; + --control: #f1f5f9; + --control-hover: #e2e8f0; --tooltip: #ffffff; - --tooltip-foreground: #0f172a; - --destructive: #ef4444; + --tooltip-foreground: #111827; --destructive-muted: rgba(239, 68, 68, 0.1); --destructive-muted-border: rgba(239, 68, 68, 0.3); --destructive-foreground: #ffffff; + --shadow-soft: 0 12px 30px -20px rgba(37, 99, 235, 0.35); + --shadow-medium: 0 18px 35px -24px rgba(37, 99, 235, 0.4); } .dark { color-scheme: dark; - --background: #080808; - --foreground: #e8e8e8; - --muted-foreground: #666666; - --card: #0e0e0e; - --card-foreground: #e8e8e8; - --card-muted: #161616; - --border: #222222; - --accent: #818cf8; + --background: #0f172a; + --foreground: #f8fafc; + --muted-foreground: #94a3b8; + --card: #1a2538; + --card-foreground: #f8fafc; + --card-muted: #223248; + --border: #334155; + --accent: #60a5fa; + --accent-secondary: #3b82f6; --success: #10b981; --warning: #fbbf24; --destructive: #f87171; - --accent-soft: rgba(129, 140, 248, 0.12); - --accent-foreground: #000000; - --control: #161616; - --control-hover: #252525; - --tooltip: #0e0e0e; - --tooltip-foreground: #e8e8e8; + --accent-soft: rgba(96, 165, 250, 0.2); + --accent-foreground: #ffffff; + --control: #2a3b53; + --control-hover: #344a67; + --tooltip: #1a2538; + --tooltip-foreground: #f8fafc; --destructive-muted: rgba(248, 113, 113, 0.1); --destructive-muted-border: rgba(248, 113, 113, 0.3); --destructive-foreground: #ffffff; + --shadow-soft: 0 16px 34px -24px rgba(2, 6, 23, 0.8); + --shadow-medium: 0 24px 45px -28px rgba(2, 6, 23, 0.85); } body { - background: var(--background); + background: + radial-gradient(circle at 0% 0%, rgba(96, 165, 250, 0.16), transparent 36%), + radial-gradient(circle at 100% 18%, rgba(59, 130, 246, 0.1), transparent 32%), + var(--background); color: var(--foreground); transition: background-color 200ms ease, color 200ms ease; } + +.surface-card { + border: 1px solid var(--border); + background: linear-gradient(180deg, color-mix(in srgb, var(--card) 92%, #ffffff 8%), var(--card)); + box-shadow: var(--shadow-soft); +} + +.primary-button { + border: 1px solid color-mix(in srgb, var(--accent) 86%, white 14%); + background: linear-gradient(140deg, var(--accent), var(--accent-secondary)); + color: var(--accent-foreground); + transition: transform 180ms ease, box-shadow 180ms ease, filter 180ms ease; +} + +.primary-button:hover { + transform: translateY(-1px); + box-shadow: var(--shadow-medium); + filter: saturate(1.05); +} + +.secondary-button { + border: 1px solid var(--border); + background: color-mix(in srgb, var(--card) 88%, white 12%); + color: var(--card-foreground); + transition: transform 180ms ease, border-color 180ms ease, background-color 180ms ease; +} + +.secondary-button:hover { + transform: translateY(-1px); + border-color: color-mix(in srgb, var(--accent) 50%, var(--border) 50%); + background: color-mix(in srgb, var(--control) 90%, white 10%); +} /* Custom slim scrollbar for dashboard widgets */ .scrollbar-thin { scrollbar-width: thin; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 2ebaa443..7dcf1156 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -63,12 +63,18 @@ export default function RootLayout({ (function() { try { const stored = localStorage.getItem('theme'); - if (stored === 'light') { + if (stored === 'dark') { + document.documentElement.classList.add('dark'); + document.documentElement.style.colorScheme = 'dark'; + } else if (stored === 'light') { document.documentElement.classList.remove('dark'); document.documentElement.style.colorScheme = 'light'; - } else { + } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { document.documentElement.classList.add('dark'); document.documentElement.style.colorScheme = 'dark'; + } else { + document.documentElement.classList.remove('dark'); + document.documentElement.style.colorScheme = 'light'; } } catch (e) {} })(); diff --git a/src/app/leaderboard/page.tsx b/src/app/leaderboard/page.tsx index 3a12bd9e..7945bd75 100644 --- a/src/app/leaderboard/page.tsx +++ b/src/app/leaderboard/page.tsx @@ -92,7 +92,7 @@ export default async function LeaderboardPage({ )}
-
+
{tabs.map((tab) => { const active = tab.id === activeTab; return ( @@ -101,7 +101,7 @@ export default async function LeaderboardPage({ href={`/leaderboard?tab=${tab.id}`} className={`rounded-lg border px-4 py-2 text-sm font-semibold transition-colors ${ active - ? "border-[var(--accent)] bg-[var(--accent)] text-[var(--accent-foreground)]" + ? "border-[var(--accent)] bg-[var(--accent)] text-[var(--accent-foreground)] shadow-sm" : "border-[var(--border)] bg-[var(--card)] text-[var(--card-foreground)] hover:bg-[var(--control)]" }`} > @@ -111,7 +111,7 @@ export default async function LeaderboardPage({ })}
-
+
Rank
Contributor
@@ -168,7 +168,7 @@ export default async function LeaderboardPage({
View diff --git a/src/app/page.tsx b/src/app/page.tsx index b4ca229a..d79522ec 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -18,67 +18,68 @@ const dmSans = DM_Sans({ }); const jetbrains = JetBrains_Mono({ subsets: ['latin'], - variable: '--font-jetbrains', - weight: ['400', '500', '600', '700'], - display: 'swap', -}); - -async function fetchRepoStats(): Promise { - const GH_HEADERS = { Accept: 'application/vnd.github.v3+json' }; - const OPTS = (ttl: number) => ({ next: { revalidate: ttl }, headers: GH_HEADERS }); - - try { - const [repoRes, contribRes, gfiRes] = await Promise.all([ - fetch('https://api.github.com/repos/Priyanshu-byte-coder/devtrack', OPTS(3600)), - fetch('https://api.github.com/repos/Priyanshu-byte-coder/devtrack/contributors?per_page=30', OPTS(3600)), - fetch('https://api.github.com/repos/Priyanshu-byte-coder/devtrack/issues?labels=good+first+issue&state=open&per_page=100', OPTS(1800)), - ]); - - if (!repoRes.ok) throw new Error('repo fetch failed'); - - const repo = await repoRes.json() as Record; - const contributors = contribRes.ok ? (await contribRes.json() as Array>) : []; - const gfiIssues = gfiRes.ok ? (await gfiRes.json() as unknown[]) : []; - - return { - stars: typeof repo.stargazers_count === 'number' ? repo.stargazers_count : 0, - forks: typeof repo.forks_count === 'number' ? repo.forks_count : 0, - openIssues: typeof repo.open_issues_count === 'number' ? repo.open_issues_count : 0, - contributorCount: Array.isArray(contributors) ? contributors.length : 0, - goodFirstIssues: Array.isArray(gfiIssues) ? gfiIssues.length : 0, - contributors: Array.isArray(contributors) - ? contributors.slice(0, 20).map(c => ({ - login: String(c.login ?? ''), - avatar_url: String(c.avatar_url ?? ''), - html_url: String(c.html_url ?? ''), - })) - : [], - }; - } catch { - // Graceful fallback โ€” page still renders without live stats - return { - stars: 40, - forks: 160, - openIssues: 307, - contributorCount: 30, - goodFirstIssues: 36, - contributors: [], - }; - } -} - -export default async function HomePage() { - const session = await getServerSession(authOptions); - - if (session) { - redirect("/dashboard"); - } - - const repoStats = await fetchRepoStats(); - return (
+ ); +
+ + Open-source dev productivity + +

+ DevTrack +

+

+ Open-source developer productivity dashboard. Track coding habits, + visualize GitHub contributions, and hit your goals. +

+
+ + Sign in with GitHub + + + View on GitHub + +
+
+ +
+

+ Everything you need to track your coding growth +

+ +
+ {features.map((feature) => ( +
+
+ {feature.icon} +
+ +

+ {feature.title} +

+ +

+ {feature.description} +

+
+ ))} +
+
+
+
+>>>>>>> 375a1b5 (feat(ui): modernize interface with light blue and white theme (#924)) ); } diff --git a/src/app/u/[username]/page.tsx b/src/app/u/[username]/page.tsx index 4ad8b075..025827a6 100644 --- a/src/app/u/[username]/page.tsx +++ b/src/app/u/[username]/page.tsx @@ -79,7 +79,7 @@ export default async function PublicProfilePage({ if (!profile) { return (
-
+

Profile Not Found

@@ -98,7 +98,7 @@ export default async function PublicProfilePage({

Back to Home @@ -111,7 +111,7 @@ export default async function PublicProfilePage({ const topRepo = profile.repos[0]?.name ?? ""; return ( -
+
@@ -176,7 +176,7 @@ function PublicContributionGraph({ .map(([day, commits]) => ({ day, commits })); return ( -
+

@@ -263,7 +263,7 @@ function PublicStreakTracker({ streak }: { streak: any }) { ]; return ( -
+

Commit Streaks

@@ -307,7 +307,7 @@ function PublicTopRepos({ const maxCommits = repos[0]?.commits ?? 1; return ( -
+

Top Repositories

diff --git a/src/components/DashboardHeader.tsx b/src/components/DashboardHeader.tsx index f830287f..157a21b8 100644 --- a/src/components/DashboardHeader.tsx +++ b/src/components/DashboardHeader.tsx @@ -39,22 +39,13 @@ export default function DashboardHeader() { }, [session]); return ( -
+
{/* Left Section */}
-

- โ–ฒ DEVTRACK -

-

- DASHBOARD +

+ Dashboard

Share Profile )} -

+
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index a9162479..9215409e 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -4,11 +4,11 @@ const year = new Date().getFullYear(); export default function Footer() { return ( -