Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 76 additions & 26 deletions src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import { authOptions } from "@/lib/auth";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import DashboardSSEProvider from "@/components/DashboardSSEProvider";

import DailyNoteWidget from "@/components/DailyNoteWidget";

import WidgetErrorBoundary from "@/components/WidgetErrorBoundary";

const SkeletonCard = () => (
Expand Down Expand Up @@ -149,24 +151,66 @@ export default async function DashboardPage() {
<TodayFocusHero userName={session.user?.name ?? null} />
</section>

{/* 1. OVERVIEW SECTION */}
<section className="mt-14 space-y-6">
<div className="flex items-center gap-3 border-b border-white/10 pb-4">
<div className="h-8 w-1.5 rounded-full bg-[var(--accent)] shadow-[0_0_15px_var(--accent)]"></div>
<h2 className="text-2xl font-bold tracking-tight">Overview</h2>
</div>
<div className="grid grid-cols-1 gap-6 w-full">
<WeeklySummaryCard />

{/* -- Row 1: Contribution graph (2/3) + Streak sidebar (1/3) -- */}
<div id="streaks" className="mt-6 grid grid-cols-1 gap-6 scroll-mt-24 lg:grid-cols-3">
{/* Left: contribution graph + heatmap */}
<div className="lg:col-span-2 flex flex-col gap-6">
<WidgetErrorBoundary>
<ContributionGraph />
</WidgetErrorBoundary>
<ContributionHeatmap />
</div>
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6 w-full">
<div className="flex flex-col gap-6 w-full overflow-hidden">
<PersonalRecords />
</div>
<div className="flex flex-col gap-6 w-full h-full">
<AIMentorWidget />
</div>

{/* Right: streak + coding time */}
<div className="flex flex-col gap-6">
<WidgetErrorBoundary>
<StreakTracker />
</WidgetErrorBoundary>
<LocalCodingTime />
<CodingTimeWidget />
</div>
</section>
</div>

{/* Friend comparison — full width, below the fold */}
<div className="mt-6">
<LazyWidget fallback={<SkeletonCard />}>
<FriendComparison />
</LazyWidget>
</div>

{/* Repo analytics explorer — full width */}
<div className="mt-6">
<LazyWidget fallback={<SkeletonCard />}>
<RepoAnalyticsExplorer />
</LazyWidget>
</div>

{/* -- Row 2: PR metrics + Community metrics -- */}
<div id="pull-requests" className="mt-6 grid grid-cols-1 gap-6 scroll-mt-24 md:grid-cols-2">
<WidgetErrorBoundary>
<PRMetrics />
</WidgetErrorBoundary>
<CommunityMetrics />
</div>

{/* PR breakdown + commit time — 2-col so charts have room */}
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
<LazyWidget fallback={<SkeletonCard />}>
<PRBreakdownChart />
</LazyWidget>
<LazyWidget fallback={<SkeletonCard />}>
<CommitTimeChart />
</LazyWidget>
</div>

{/* Activity ring — full width */}
<div className="mt-6">
<LazyWidget fallback={<SkeletonCard />}>
<ActivityRingChart />
</LazyWidget>
</div>


{/* 2. ACTIVITY & CODING TIME */}
<section id="streaks" className="mt-14 space-y-6 scroll-mt-28">
Expand Down Expand Up @@ -246,21 +290,28 @@ export default async function DashboardPage() {
</div>
</section>

{/* 4. GOALS & INSIGHTS */}
<section id="goals" className="mt-14 space-y-6 scroll-mt-28 mb-12">
<div className="flex items-center gap-3 border-b border-white/10 pb-4">
<div className="h-8 w-1.5 rounded-full bg-purple-500 shadow-[0_0_15px_rgba(168,85,247,0.5)]"></div>
<h2 className="text-2xl font-bold tracking-tight">Goals & Insights</h2>
</div>

{/* -- Row 4: Top repos + Language breakdown + Goal tracker -- */}
<div className="mt-6 grid grid-cols-1 lg:grid-cols-3 gap-6">
<LazyWidget fallback={<SkeletonCard />}>
<WidgetErrorBoundary>
<TopRepos />
</WidgetErrorBoundary>
</LazyWidget>
<LazyWidget fallback={<SkeletonCard />}>
<LanguageBreakdown />
</LazyWidget>
<WidgetErrorBoundary>
<GoalTracker />
</WidgetErrorBoundary>
</div>


<div className="grid grid-cols-1 xl:grid-cols-3 gap-6 w-full">
<div className="xl:col-span-2 flex flex-col gap-6 w-full overflow-hidden">
<LazyWidget fallback={<SkeletonCard />}>
<IssueMetrics />
</LazyWidget>
<WidgetErrorBoundary>
<GoalTracker />
</WidgetErrorBoundary>
<DailyNoteWidget />
<LazyWidget fallback={<SkeletonCard />}>
<RecentActivity />
Expand All @@ -278,7 +329,6 @@ export default async function DashboardPage() {
</LazyWidget>
</div>
</div>
</section>
</div>
</DashboardSSEProvider>
);
Expand Down
35 changes: 21 additions & 14 deletions src/components/WidgetErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,27 @@ class WidgetErrorBoundary extends React.Component<Props, State> {
render() {
if (this.state.hasError) {
return (
<div className="flex h-full w-full flex-col items-center justify-center rounded-xl border border-[var(--destructive)]/30 bg-[var(--destructive)]/5 p-6 text-center">
<AlertTriangle className="h-8 w-8 text-[var(--destructive)] mb-3" />
<p className="text-sm font-medium text-[var(--destructive)] mb-4">
{this.props.fallbackMessage || "Unable to load widget"}
</p>
<button
onClick={this.handleRetry}
className="flex items-center gap-2 rounded-lg bg-[var(--destructive)] px-4 py-2 text-xs font-semibold text-white hover:opacity-90 transition-opacity"
>
<RefreshCw className="h-3 w-3" />
Retry
</button>
</div>
);
<div className="flex h-full w-full flex-col items-center justify-center rounded-xl border border-[var(--destructive)]/30 bg-[var(--destructive)]/5 p-6 text-center">

<AlertTriangle className="h-8 w-8 text-[var(--destructive)] mb-3" />

<h2 className="mb-2 text-lg font-semibold">
Unable to load data
</h2>

<p className="text-sm text-[var(--muted-foreground)] mb-4">
{this.props.fallbackMessage || "Please try refreshing or try again later."}
</p>

<button
onClick={this.handleRetry}
className="flex items-center gap-2 rounded-lg bg-[var(--destructive)] px-4 py-2 text-xs font-semibold text-white hover:opacity-90 transition-opacity"
>
<RefreshCw className="h-3 w-3" />
Retry
</button>
</div>
);
}

return this.props.children;
Expand Down
Loading