From d02cced36c24951e209541e213b11aad6588a4d3 Mon Sep 17 00:00:00 2001 From: vinaysathwik-ai Date: Mon, 25 May 2026 19:19:34 +0530 Subject: [PATCH 1/3] Improved navigation UI --- .env.example | 4 +- src/app/dashboard/activity/page.tsx | 27 ++++ src/app/dashboard/analytics/page.tsx | 57 ++++++++ src/app/dashboard/community/page.tsx | 35 +++++ src/app/dashboard/goals/page.tsx | 30 ++++ src/app/dashboard/layout.tsx | 16 ++ src/app/dashboard/page.tsx | 98 ++----------- src/app/dashboard/productivity/page.tsx | 39 +++++ src/app/dashboard/repositories/page.tsx | 39 +++++ src/app/dashboard/settings/page.tsx | 100 ++++--------- src/components/DashboardHeader.tsx | 18 ++- src/components/Sidebar.tsx | 187 ++++++++++++++++++++++++ 12 files changed, 487 insertions(+), 163 deletions(-) create mode 100644 src/app/dashboard/activity/page.tsx create mode 100644 src/app/dashboard/analytics/page.tsx create mode 100644 src/app/dashboard/community/page.tsx create mode 100644 src/app/dashboard/goals/page.tsx create mode 100644 src/app/dashboard/layout.tsx create mode 100644 src/app/dashboard/productivity/page.tsx create mode 100644 src/app/dashboard/repositories/page.tsx create mode 100644 src/components/Sidebar.tsx diff --git a/.env.example b/.env.example index 4b262154..9971741a 100644 --- a/.env.example +++ b/.env.example @@ -20,10 +20,10 @@ NEXTAUTH_SECRET=your_nextauth_secret # ------------------------------------------------------- # GitHub OAuth App # github.com/settings/applications/new → Client ID -GITHUB_ID=your_github_oauth_client_id +GITHUB_ID=Ov23ligQcbiS4lQ2cQbh # github.com/settings/applications/new → Client Secret -GITHUB_SECRET=your_github_oauth_client_secret +GITHUB_SECRET=18153d9e5f7c92aac5d31f36760f529f871363a7 # ------------------------------------------------------- # GitHub Webhook (optional — enables real-time metric refresh on push) diff --git a/src/app/dashboard/activity/page.tsx b/src/app/dashboard/activity/page.tsx new file mode 100644 index 00000000..5e19bb11 --- /dev/null +++ b/src/app/dashboard/activity/page.tsx @@ -0,0 +1,27 @@ +import DashboardHeader from "@/components/DashboardHeader"; +import ContributionGraph from "@/components/ContributionGraph"; +import RecentActivity from "@/components/RecentActivity"; +import { authOptions } from "@/lib/auth"; +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; + +export default async function ActivityPage() { + const session = await getServerSession(authOptions); + if (!session) redirect("/"); + if (session.error === "TokenRevoked") redirect("/"); + + return ( +
+ + + {/* Annual Contribution Grid */} + + + {/* Activity Event Feed */} + +
+ ); +} diff --git a/src/app/dashboard/analytics/page.tsx b/src/app/dashboard/analytics/page.tsx new file mode 100644 index 00000000..bb0d9e79 --- /dev/null +++ b/src/app/dashboard/analytics/page.tsx @@ -0,0 +1,57 @@ +import DashboardHeader from "@/components/DashboardHeader"; +import StreakTracker from "@/components/StreakTracker"; +import PRMetrics from "@/components/PRMetrics"; +import PRBreakdownChart from "@/components/PRBreakdownChart"; +import CommitTimeChart from "@/components/CommitTimeChart"; +import PRReviewTrendChart from "@/components/PRReviewTrendChart"; +import CIAnalytics from "@/components/CIAnalytics"; +import IssueMetrics from "@/components/IssueMetrics"; +import CodingActivityInsightsCard from "@/components/CodingActivityInsightsCard"; +import { authOptions } from "@/lib/auth"; +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; + +export default async function AnalyticsPage() { + const session = await getServerSession(authOptions); + if (!session) redirect("/"); + if (session.error === "TokenRevoked") redirect("/"); + + return ( +
+ + + {/* Row 1: Coding Insights & Commit Streaks */} +
+
+ +
+
+ +
+
+ + {/* Row 2: Pull Request Analytics */} +
+ + +
+ + {/* Row 3: Commit and Review Time Trends */} +
+ + +
+ + {/* Row 4: Issues & Continuous Integration (Actions) */} +
+
+ +
+ +
+
+ ); +} diff --git a/src/app/dashboard/community/page.tsx b/src/app/dashboard/community/page.tsx new file mode 100644 index 00000000..3954ed4b --- /dev/null +++ b/src/app/dashboard/community/page.tsx @@ -0,0 +1,35 @@ +import DashboardHeader from "@/components/DashboardHeader"; +import FriendComparison from "@/components/FriendComparison"; +import CommunityMetrics from "@/components/CommunityMetrics"; +import DiscussionsWidget from "@/components/DiscussionsWidget"; +import { authOptions } from "@/lib/auth"; +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; + +export default async function CommunityPage() { + const session = await getServerSession(authOptions); + if (!session) redirect("/"); + if (session.error === "TokenRevoked") redirect("/"); + + return ( +
+ + + {/* Row 1: Leaderboard/Friends Comparison + Repository Community metrics */} +
+
+ +
+
+ +
+
+ + {/* Discussions Widget */} + +
+ ); +} diff --git a/src/app/dashboard/goals/page.tsx b/src/app/dashboard/goals/page.tsx new file mode 100644 index 00000000..1123b7bb --- /dev/null +++ b/src/app/dashboard/goals/page.tsx @@ -0,0 +1,30 @@ +import DashboardHeader from "@/components/DashboardHeader"; +import GoalTracker from "@/components/GoalTracker"; +import ActivityRingChart from "@/components/ActivityRingChart"; +import { authOptions } from "@/lib/auth"; +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; + +export default async function GoalsPage() { + const session = await getServerSession(authOptions); + if (!session) redirect("/"); + if (session.error === "TokenRevoked") redirect("/"); + + return ( +
+ + +
+
+ +
+
+ +
+
+
+ ); +} diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx new file mode 100644 index 00000000..4f27cf66 --- /dev/null +++ b/src/app/dashboard/layout.tsx @@ -0,0 +1,16 @@ +import Sidebar from "@/components/Sidebar"; + +export default function DashboardLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ +
+ {children} +
+
+ ); +} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 617bea42..92767e34 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,5 +1,10 @@ import DiscussionsWidget from "@/components/DiscussionsWidget"; +import ActivityRingChart from "@/components/ActivityRingChart"; +import ContributionGraph from "@/components/ContributionGraph"; +import ContributionHeatmap from "@/components/ContributionHeatmap"; +import PRMetrics from "@/components/PRMetrics"; import CommunityMetrics from "@/components/CommunityMetrics"; +import PRBreakdownChart from "@/components/PRBreakdownChart"; import GoalTracker from "@/components/GoalTracker"; import DashboardHeader from "@/components/DashboardHeader"; import StreakTracker from "@/components/StreakTracker"; @@ -7,10 +12,12 @@ import TopRepos from "@/components/TopRepos"; import PinnedRepos from "@/components/PinnedRepos"; import InactiveRepositoriesCard from "@/components/InactiveRepositoriesCard"; import LanguageBreakdown from "@/components/LanguageBreakdown"; +import CommitTimeChart from "@/components/CommitTimeChart"; +import CodingActivityInsightsCard from "@/components/CodingActivityInsightsCard"; +import PRReviewTrendChart from "@/components/PRReviewTrendChart"; import CIAnalytics from "@/components/CIAnalytics"; import IssueMetrics from "@/components/IssueMetrics"; import StreakAtRiskBanner from "@/components/StreakAtRiskBanner"; -import RepoAnalyticsExplorer from "@/components/repo-analytics/RepoAnalyticsExplorer"; import dynamic from "next/dynamic"; const SkeletonCard = () => ( @@ -89,7 +96,7 @@ import ExportButton from "@/components/ExportButton"; import Link from "next/link"; import PersonalRecords from "@/components/PersonalRecords"; import LocalCodingTime from "@/components/LocalCodingTime"; -import CodingTimeWidget from "@/components/CodingTimeWidget"; +import CodingTimeCard from "@/components/CodingTimeCard"; import RecentActivity from "@/components/RecentActivity"; import { authOptions } from "@/lib/auth"; import { getServerSession } from "next-auth"; @@ -99,24 +106,15 @@ import DashboardSSEProvider from "@/components/DashboardSSEProvider"; export default async function DashboardPage() { const session = await getServerSession(authOptions); if (!session) redirect("/"); - // If the JWT callback detected that the GitHub token has been revoked, - // redirect to the landing page so the user must re-authenticate. if (session.error === "TokenRevoked") redirect("/"); return ( - -
- +
+
- - Year in Code - Settings @@ -142,19 +140,6 @@ export default async function DashboardPage() {
-
- -
- -
- -
- -
- -
- - {/* Row 1: Contribution graph + Streak + Local Coding Time */}
@@ -164,73 +149,16 @@ export default async function DashboardPage() {
-
- -
- +
- - {/* Row 2: PR metrics, community metrics, PR breakdown & Time Chart */} -
- - - - -
- {/* Row 2b: Activity Ring Chart */} -
- -
- -
- -
- -
- -
- - {/* Row 3: Issue metrics + CI analytics */} -
-
- -
- -
- {/* Row 3b: Discussion activity */} -
- -
- - {/* Row 4: Pinned repositories */} -
- -
- - {/* Row 5: Inactive repository reminder */} -
- -
- - {/* Row 6: Top repos + Language breakdown + Goal tracker */} -
- - - -
- - {/* Row 7: Recent GitHub activity */} -
- -
); diff --git a/src/app/dashboard/productivity/page.tsx b/src/app/dashboard/productivity/page.tsx new file mode 100644 index 00000000..8dd1fc43 --- /dev/null +++ b/src/app/dashboard/productivity/page.tsx @@ -0,0 +1,39 @@ +import DashboardHeader from "@/components/DashboardHeader"; +import { AIMentorWidget } from "@/components/AIMentorWidget"; +import LocalCodingTime from "@/components/LocalCodingTime"; +import PersonalRecords from "@/components/PersonalRecords"; +import CodingActivityInsightsCard from "@/components/CodingActivityInsightsCard"; +import { authOptions } from "@/lib/auth"; +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; + +export default async function ProductivityPage() { + const session = await getServerSession(authOptions); + if (!session) redirect("/"); + if (session.error === "TokenRevoked") redirect("/"); + + return ( +
+ + + {/* Row 1: AI mentor + Local Coding Time editor sync */} +
+
+ +
+
+ +
+
+ + {/* Row 2: Personal records & achievements milestones */} + + + {/* Row 3: Coding insights & patterns */} + +
+ ); +} diff --git a/src/app/dashboard/repositories/page.tsx b/src/app/dashboard/repositories/page.tsx new file mode 100644 index 00000000..a6f90c0a --- /dev/null +++ b/src/app/dashboard/repositories/page.tsx @@ -0,0 +1,39 @@ +import DashboardHeader from "@/components/DashboardHeader"; +import TopRepos from "@/components/TopRepos"; +import PinnedRepos from "@/components/PinnedRepos"; +import ContributionHeatmap from "@/components/ContributionHeatmap"; +import InactiveRepositoriesCard from "@/components/InactiveRepositoriesCard"; +import { authOptions } from "@/lib/auth"; +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; + +export default async function RepositoriesPage() { + const session = await getServerSession(authOptions); + if (!session) redirect("/"); + if (session.error === "TokenRevoked") redirect("/"); + + return ( +
+ + + {/* Pinned Repositories */} + + + {/* Grid: Top Repos & Inactivity reminders */} +
+
+ +
+
+ +
+
+ + {/* Contribution Heatmap */} + +
+ ); +} diff --git a/src/app/dashboard/settings/page.tsx b/src/app/dashboard/settings/page.tsx index 720c50fc..f2eacd27 100644 --- a/src/app/dashboard/settings/page.tsx +++ b/src/app/dashboard/settings/page.tsx @@ -88,18 +88,16 @@ function getStatusMessage( function SettingsPageFallback() { return ( -
-
-
-
-
- {[1, 2, 3].map((i) => ( -
- ))} -
+
+
+
+
+ {[1, 2, 3].map((i) => ( +
+ ))}
@@ -370,18 +368,16 @@ function SettingsPageContent() { if (status === "loading" || loading) { return ( -
-
-
-
-
- {[1, 2, 3].map((i) => ( -
- ))} -
+
+
+
+
+ {[1, 2, 3].map((i) => ( +
+ ))}
@@ -390,12 +386,10 @@ function SettingsPageContent() { if (!settings) { return ( -
-
-

- Failed to load settings. -

-
+
+

+ Failed to load settings. +

); } @@ -403,25 +397,13 @@ function SettingsPageContent() { return (
-
- - - -
-

- Settings -

-

- Manage your profile and preferences -

-
+
+

+ Settings +

+

+ Manage your profile and preferences +

{statusMessage && ( @@ -728,26 +710,6 @@ function SettingsPageContent() {
-
- - - -
- -
); diff --git a/src/components/DashboardHeader.tsx b/src/components/DashboardHeader.tsx index 0b53420a..ea3f93c7 100644 --- a/src/components/DashboardHeader.tsx +++ b/src/components/DashboardHeader.tsx @@ -9,7 +9,13 @@ import ThemeToggle from "@/components/ThemeToggle"; import UserAvatar from "@/components/UserAvatar"; import KeyboardShortcuts from "@/components/KeyboardShortcuts"; -export default function DashboardHeader() { +export default function DashboardHeader({ + title = "Dashboard", + description = "Your coding activity at a glance 🚀", +}: { + title?: string; + description?: string; +}) { const { data: session } = useSession(); const [isPublic, setIsPublic] = useState(null); @@ -44,14 +50,12 @@ export default function DashboardHeader() { {/* Left Section */}
-

+

Dashboard

-

- coding activity at a glance + +

+ Your coding activity at a glance 🚀

diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx new file mode 100644 index 00000000..1c0e4aac --- /dev/null +++ b/src/components/Sidebar.tsx @@ -0,0 +1,187 @@ +"use client"; + +import { useState } from "react"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; + +interface NavItem { + name: string; + href: string; + icon: React.ReactNode; +} + +export default function Sidebar() { + const pathname = usePathname(); + const [isOpen, setIsOpen] = useState(false); + + const navItems: NavItem[] = [ + { + name: "Dashboard", + href: "/dashboard", + icon: ( + + + + ), + }, + { + name: "Analytics", + href: "/dashboard/analytics", + icon: ( + + + + ), + }, + { + name: "Repositories", + href: "/dashboard/repositories", + icon: ( + + + + ), + }, + { + name: "Activity", + href: "/dashboard/activity", + icon: ( + + + + ), + }, + { + name: "Productivity", + href: "/dashboard/productivity", + icon: ( + + + + ), + }, + { + name: "Community", + href: "/dashboard/community", + icon: ( + + + + ), + }, + { + name: "Goals", + href: "/dashboard/goals", + icon: ( + + + + ), + }, + { + name: "Settings", + href: "/dashboard/settings", + icon: ( + + + + + ), + }, + ]; + + const handleLinkClick = () => { + setIsOpen(false); + }; + + return ( + <> + {/* Mobile Header Bar */} +
+
+ + DevTrack + +
+ +
+ + {/* Mobile Navigation Dropdown/Overlay */} + {isOpen && ( +
+ +
+ )} + + {/* Desktop Sidebar */} + + + ); +} From 58dc9a582d60a031224b7466ee0dfeb59c746100 Mon Sep 17 00:00:00 2001 From: vinaysathwik-ai Date: Mon, 25 May 2026 19:30:37 +0530 Subject: [PATCH 2/3] improved navigation UI --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 9971741a..a485339a 100644 --- a/.env.example +++ b/.env.example @@ -20,10 +20,10 @@ NEXTAUTH_SECRET=your_nextauth_secret # ------------------------------------------------------- # GitHub OAuth App # github.com/settings/applications/new → Client ID -GITHUB_ID=Ov23ligQcbiS4lQ2cQbh +GITHUB_ID=your_github_id # github.com/settings/applications/new → Client Secret -GITHUB_SECRET=18153d9e5f7c92aac5d31f36760f529f871363a7 +GITHUB_SECRET=your_github_secret # ------------------------------------------------------- # GitHub Webhook (optional — enables real-time metric refresh on push) From fd75595f01b48b33cbd9c72c7770173efafd1b65 Mon Sep 17 00:00:00 2001 From: vinaysathwik-ai Date: Mon, 25 May 2026 19:41:52 +0530 Subject: [PATCH 3/3] improved navigation UI --- .env.example | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index a485339a..fe6319ad 100644 --- a/.env.example +++ b/.env.example @@ -20,10 +20,10 @@ NEXTAUTH_SECRET=your_nextauth_secret # ------------------------------------------------------- # GitHub OAuth App # github.com/settings/applications/new → Client ID -GITHUB_ID=your_github_id +GITHUB_ID=your_github_oauth_client_id # github.com/settings/applications/new → Client Secret -GITHUB_SECRET=your_github_secret +GITHUB_SECRET=your_github_oauth_client_secret # ------------------------------------------------------- # GitHub Webhook (optional — enables real-time metric refresh on push) @@ -52,11 +52,4 @@ UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_rest_token # AI Mentor widget). Without this key the widget still works and shows # rule-based insights only. # console.anthropic.com → API Keys -# ANTHROPIC_API_KEY=sk-ant-... - -# ------------------------------------------------------- -# Groq API Key (optional — enables AI-generated weekly summaries in the -# AI Mentor widget using Llama-3). -# console.groq.com → API Keys -GROQ_API_KEY=gsk_... - +ANTHROPIC_API_KEY=sk-ant-...