Skip to content

Feat: implement multi-view home dashboard with repository-wise metrics - #189

Closed
Atharva7126 wants to merge 12 commits into
CircuitVerse:mainfrom
Atharva7126:add-repo-wise-stats
Closed

Feat: implement multi-view home dashboard with repository-wise metrics#189
Atharva7126 wants to merge 12 commits into
CircuitVerse:mainfrom
Atharva7126:add-repo-wise-stats

Conversation

@Atharva7126

@Atharva7126 Atharva7126 commented Jan 10, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR transforms the existing Home page into a comprehensive Home Dashboard by introducing a seamless tabbed interface. It adds a dedicated "Repositories" view to provide granular insights into project-specific activities, while preserving the existing organization-wide "Overview" stats.

Key Changes:

  • Home Dashboard UI: Implemented a HomeDashboard client component with a smooth "Overview | Repositories" pill toggle.
  • Repository Statistics: Added a new view featuring:
    • Glassmorphism Summary Cards: Displays Total Repos, Total Contributions (Last 30 days), and the Most Active Repo (with growth metrics).
    • Repository Cards: A responsive grid showing detailed metrics for each repo, visualizing the contribution flow (Issues CreatedPRs OpenedPRs Merged) with specific color coding (Neutral/Blue/Green).
  • Backend Logic Updates: Updated the generateRepoOverview script (lib/db.ts or equivalent) to explicitly filter out bot users from Issue and PR counts, ensuring contribution statistics reflect only real human activity.
  • Design Enhancements: Integrated lucide-react icons and a refined dark/light mode compatible theme using the CircuitVerse green accents.

Related Issue

Fixes #180

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation

Checklist

  • Code follows project style
  • Tested locally
  • No unnecessary files added
  • PR title is clear and descriptive

Screenshots (if applicable)

Leaderboard.-.CircuitVerse.-.Google.Chrome.2026-01-10.12-53-21.mp4

Summary by CodeRabbit

  • New Features

    • Client-rendered, tabbed Home dashboard (Overview & Repositories) consuming a consolidated overview payload.
    • Repositories view with summary cards and repository tiles showing language, stars, description, and PR/issue metrics.
    • Added a public 30-day repository activity snapshot for repo-level insights.
  • Refactor

    • Home UI rendering moved from server-rendered sections to a client dashboard component.
  • Bug Fixes / UI

    • UI tweaks: activity section renamed to "Activity Tags", avatar rendering improved, tab and layout refinements.

✏️ Tip: You can customize this high-level summary in your review settings.

@netlify

netlify Bot commented Jan 10, 2026

Copy link
Copy Markdown

Deploy Preview for cv-community-dashboard ready!

Name Link
🔨 Latest commit 9ba6833
🔍 Latest deploy log https://app.netlify.com/projects/cv-community-dashboard/deploys/6963d27776a51000085feaa2
😎 Deploy Preview https://deploy-preview-189--cv-community-dashboard.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jan 10, 2026

Copy link
Copy Markdown

Walkthrough

Server-side app/page.tsx now gathers data (totalMonth, week, month, previousMonthCount, bucketData, config and reposOverview via lib/db.getReposOverview) into an overviewData object and returns the client component HomeDashboard with that payload. A new client component components/home-dashboard.tsx renders Overview and Repositories tabs (summary cards, repo cards, metrics). lib/db.getReposOverview reads public/leaderboard/overview.json and returns RepoStats[], and scripts/generateLeaderboard.ts adds the RepoStats type and a generateRepoOverview flow that writes public/leaderboard/overview.json.

Possibly related PRs

  • PR 115: Adds RepoStats and the overview generation flow in scripts/generateLeaderboard that produces public/leaderboard/overview.json consumed by getReposOverview.
  • PR 74: Modifies app/page.tsx data assembly for monthly bucketData and previousMonthCount—the same server-side values now packaged into overviewData for HomeDashboard.
  • PR 51: Overlaps with leaderboard data generation and leaderboard/contributor UI edits that intersect with the new HomeDashboard and RepoStats usage.
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: implementing a multi-view home dashboard with repository-wise metrics, which aligns with the PR's primary objective of converting the home page into a tabbed dashboard with an Overview and Repositories view.
Description check ✅ Passed The PR description includes all major required template sections: description, related issue, type of change, and checklist with all items checked.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @components/home-dashboard.tsx:
- Around line 173-179: The "Total Contributions" SummaryCard is showing only
activeRepo.totalContributions (misleading); either rename the label to reflect
"Most Active Repo Contributions" or compute the real aggregate and use it:
create a totalContributions const by summing repos via repos.reduce((sum, r) =>
sum + r.current.currentTotalContribution, 0) and pass value={totalContributions}
to the SummaryCard (target the SummaryCard usage and the
activeRepo.totalContributions reference to update).

In @scripts/generateLeaderboard.ts:
- Around line 564-582: In fetchPRsMerge, the bot-filter condition is inverted:
currently it continues when a PR author is NOT a bot, which excludes human PRs;
change the check so the loop skips when isBotUser(pr.user) is true (i.e.,
continue for bots) so only human PRs are counted, updating the condition at the
line containing if (!isBotUser(pr.user)) continue; accordingly.
🧹 Nitpick comments (6)
lib/db.ts (1)

227-243: Add error handling for JSON parse to prevent server crashes.

JSON.parse can throw on malformed JSON. Other functions in this file (e.g., getUpdatedTime at lines 163-172) wrap JSON parsing in try-catch. Apply the same pattern here for consistency and robustness.

♻️ Suggested fix
 export async function getReposOverview(): Promise<RepoStats[]> {
   const filePath = path.join(
     process.cwd(),
     "public",
     "leaderboard",
     `overview.json`
   );

   if (!fs.existsSync(filePath)) return [];

-  const file = fs.readFileSync(filePath, "utf-8");
-  const data = JSON.parse(file);
-
-  if (!data?.repos?.length) return [];
-
-  return data.repos;
+  try {
+    const file = fs.readFileSync(filePath, "utf-8");
+    const data = JSON.parse(file);
+
+    if (!data?.repos?.length) return [];
+
+    return data.repos;
+  } catch {
+    return [];
+  }
 }
components/home-dashboard.tsx (3)

26-30: Consider adding proper TypeScript types instead of any.

The overviewData prop and several component props use any type, which bypasses TypeScript's type checking. Since RepoStats is already exported from @/scripts/generateLeaderboard, you could define a proper interface:

♻️ Suggested type definition
import { RepoStats } from "@/scripts/generateLeaderboard";
import { ActivityGroup, MonthBuckets } from "@/lib/db";

type OverviewData = {
  totalMonth: number;
  week: ActivityGroup[];
  month: ActivityGroup[];
  previousMonthCount: number;
  bucketData: MonthBuckets;
  config: { org: { name: string; description: string } };
  reposData: {
    reposOverview: RepoStats[];
  };
};

export default function HomeDashboard({
  overviewData,
}: {
  overviewData: OverviewData;
}) {
  // ...
}

202-204: Use a guaranteed unique key for repository cards.

repo.name can be null per the RepoStats type. Consider using repo.html_url which is guaranteed to be unique and non-null.

-<RepoCard key={repo.name} repo={repo} />
+<RepoCard key={repo.html_url} repo={repo} />

315-319: External links should open in new tab with proper security attributes.

The repository link points to an external GitHub URL. For better UX and security, external links should open in a new tab with rel="noopener noreferrer".

♻️ Suggested fix
 <div className="text-lg font-bold text-zinc-900 dark:text-zinc-100 hover:text-[#50B78B] dark:hover:text-[#50B78B] transition-colors truncate">
-  <Link href={repo.html_url}>
+  <Link href={repo.html_url} target="_blank" rel="noopener noreferrer">
     {repo.name}
   </Link>
 </div>
scripts/generateLeaderboard.ts (2)

471-491: Type syntax cleanup: number | 0 is redundant.

The union number | 0 is redundant since 0 is already a number. Simplify to just number.

♻️ Suggested fix
 export type RepoStats = {
   name: string | null,
   description: string | null,
   language: string | null,
   avatar_url: string,
   html_url: string,
-  stars: number | 0,
-  forks: number | 0,
+  stars: number,
+  forks: number,
   current: {
     pr_opened: number,
     pr_merged: number,
     issue_created: number,
-    currentTotalContribution: number | 0,
+    currentTotalContribution: number,
   },
   // ...
 }

513-535: Missing rate limiting in fetchAll could trigger GitHub API limits.

Other fetch functions use smartSleep for rate limiting (e.g., fetchRepoPRs at line 375), but fetchAll doesn't. Since this function is used for paginated fetches across multiple repos, it could quickly exhaust the API rate limit.

♻️ Add rate limiting
 async function fetchAll(url: string) {
   let page = 1;
   let results: any[] = [];

   while (true) {
     const res = await fetch(`${url}&per_page=100&page=${page}`, {
       headers: {
         Authorization: `Bearer ${TOKEN}`,
         Accept: "application/vnd.github+json",
       },
     });

     if (!res.ok) break;

+    await smartSleep(res, 500);
     const data = await res.json();
     results.push(...data);

     if (data.length < 100) break;
     page++;
   }

   return results;
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13639da and 3999e27.

📒 Files selected for processing (5)
  • app/page.tsx
  • components/home-dashboard.tsx
  • lib/db.ts
  • public/leaderboard/overview.json
  • scripts/generateLeaderboard.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
📚 Learning: 2026-01-07T10:51:39.554Z
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.

Applied to files:

  • app/page.tsx
🧬 Code graph analysis (2)
lib/db.ts (1)
scripts/generateLeaderboard.ts (1)
  • RepoStats (471-491)
app/page.tsx (2)
lib/db.ts (5)
  • ActivityGroup (21-26)
  • getRecentActivitiesGroupedByType (89-148)
  • getPreviousMonthActivityCount (209-225)
  • getMonthlyActivityBuckets (177-207)
  • getReposOverview (227-243)
components/home-dashboard.tsx (1)
  • HomeDashboard (26-213)
🔇 Additional comments (8)
public/leaderboard/overview.json (1)

1-426: LGTM!

This is a generated static data file that matches the RepoStats type schema defined in scripts/generateLeaderboard.ts. The data structure is consistent across all repository entries.

lib/db.ts (1)

3-3: LGTM!

Import correctly updated to include RepoStats type which is used as the return type for the new getReposOverview function.

components/home-dashboard.tsx (3)

69-213: LGTM!

The dashboard structure, tab switching logic, and layout are well-implemented. The responsive grid layouts and conditional rendering based on activeTab state work correctly.


217-298: LGTM!

SummaryCard is a well-structured presentational component with appropriate glassmorphism styling and decoration variants.


300-416: LGTM!

RepoCard and MetricFlowItem components are well-implemented with proper variant-based styling for the metrics display.

scripts/generateLeaderboard.ts (2)

596-646: LGTM!

The generateRepoOverview function correctly aggregates repository metrics and handles missing metadata gracefully by skipping repos where meta fetch fails.


878-878: LGTM!

Integration point correctly calls generateRepoOverview() at the end of the year generation flow.

app/page.tsx (1)

1-41: LGTM!

Clean separation of server-side data fetching and client-side rendering. The overviewData bundle consolidates all necessary data for the dashboard in a well-organized structure. This follows proper Next.js App Router patterns for server/client component composition.

Comment thread components/home-dashboard.tsx
Comment thread scripts/generateLeaderboard.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In @components/home-dashboard.tsx:
- Line 25: Move the RepoStats type out of the build script into a shared types
module and update imports: create a new types file (e.g., types/repos.ts)
exporting the RepoStats type, change this component to import RepoStats from
that shared module instead of scripts/generateLeaderboard, and update
scripts/generateLeaderboard to import RepoStats from the new shared module as
well so both runtime components and build scripts reference the same centralized
type.

In @scripts/generateLeaderboard.ts:
- Around line 596-646: generateRepoOverview currently lets any error during repo
processing bubble up and crash the whole run; wrap the per-repository work
inside the for loop in a try-catch so failures in fetchRepoMeta,
fetchIssuesCreated, fetchPRsOpened, fetchPRsMerge, etc. do not abort processing
(log the repo name and error and continue), and also add a top-level try-catch
around the function body to catch unexpected errors so writeRepoOverview(res)
still runs with whatever partial results were collected (or ensure
writeRepoOverview is called from a finally block), including clear error logging
that includes the repo identifier and error details.
- Around line 493-496: The module-level date constants NOW, CURRENT_START,
PREVIOUS_START and PREVIOUS_END are computed at import time and can become
stale; move their computation into generateRepoOverview() so they are evaluated
when the function runs (or replace them with functions that compute values on
demand), and update any helpers that currently read those globals (e.g., daysAgo
usage, functions referenced inside generateRepoOverview) to accept the computed
dates as parameters so all date-dependent logic uses the fresh per-call values.
- Line 878: generateRepoOverview() is an async function but is invoked without
awaiting its result, so the script can exit before overview.json is written;
update the call site to await generateRepoOverview() and wrap the call in a
try-catch so any errors are logged/handled (e.g., using console.error or the
existing logger) to prevent the whole leaderboard generation from crashing;
locate the invocation of generateRepoOverview and replace it with an awaited,
error-handled call.
🧹 Nitpick comments (5)
components/home-dashboard.tsx (3)

80-108: Eliminate duplicate sorting logic.

The same sorting operation is performed twice: once inside getActiveRepoStats (lines 89-93) and again for sortedRepos (lines 104-108). This is inefficient and violates the DRY principle.

♻️ Proposed refactor

Compute sortedRepos once and reuse it:

-  function getActiveRepoStats() {
-    if (!repos || repos.length === 0) {
-      return {
-        name: "N/A",
-        growth: 0,
-        totalContributions: 0,
-      };
-    }
-
-    const topRepo = [...repos].sort(
-      (a, b) =>
-        b.current.currentTotalContribution -
-        a.current.currentTotalContribution
-    )[0];
-
-    return {
-      name: topRepo?.name,
-      growth: topRepo?.growth?.pr_merged ?? 0,
-      totalContributions:
-        topRepo?.current.currentTotalContribution,
-    };
-  }
-  const activeRepo = getActiveRepoStats();
-
   const sortedRepos = [...repos].sort(
     (a, b) =>
       b.current.currentTotalContribution -
       a.current.currentTotalContribution
   );
+
+  function getActiveRepoStats() {
+    if (sortedRepos.length === 0) {
+      return {
+        name: "N/A",
+        growth: 0,
+        totalContributions: 0,
+      };
+    }
+
+    const topRepo = sortedRepos[0];
+    return {
+      name: topRepo.name,
+      growth: topRepo.growth?.pr_merged ?? 0,
+      totalContributions: topRepo.current.currentTotalContribution,
+    };
+  }
+  const activeRepo = getActiveRepoStats();

349-355: Consider a more descriptive alt text fallback.

The alt text fallback "Image" is not very descriptive. Consider using a more informative fallback that helps with accessibility.

♻️ Suggested improvement
             <Image
               src={repo.avatar_url}
-              alt={repo.name ?? "Image"}
+              alt={repo.name ?? "Repository avatar"}
               width={40}
               height={40}
             />

404-429: LGTM with optional type safety improvement.

The component logic is sound. The type assertion on line 428 is safe given the MetricVariant type constraint, but you could eliminate it with const assertion on the variantStyles object.

♻️ Optional: Remove type assertion
   const variantStyles = {
     neutral: {
       icon: "text-zinc-400",
       count: "text-zinc-700 dark:text-zinc-300",
       bg: "hover:bg-zinc-100 dark:hover:bg-zinc-700/50",
     },
     active: {
       icon: "text-blue-500/70 dark:text-blue-400/70",
       count: "text-zinc-800 dark:text-zinc-200",
       bg: "hover:bg-blue-50 dark:hover:bg-blue-900/20",
     },
     success: {
       icon: "text-[#50B78B]",
       count: "text-[#50B78B] font-bold",
       bg: "hover:bg-[#50B78B]/10",
     },
-  };
-  const styles =
-    variantStyles[variant as keyof typeof variantStyles];
+  } as const satisfies Record<MetricVariant, { icon: string; count: string; bg: string }>;
+  const styles = variantStyles[variant];
scripts/generateLeaderboard.ts (2)

500-511: Add error logging in fetchRepoMeta.

The function returns null on error without logging the error details, making debugging difficult when repository metadata fetching fails.

🔧 Suggested improvement
 async function fetchRepoMeta(repo:string) {
    const res = await fetch(`${GITHUB_API}/repos/${ORG}/${repo}`, {
     headers: {
       Authorization: `Bearer ${TOKEN}`,
       Accept: "application/vnd.github+json",
     }
   });

-  if (!res.ok) return null;
+  if (!res.ok) {
+    console.error(`   ⚠️ Failed to fetch metadata for ${repo}: ${res.status}`);
+    return null;
+  }
   await smartSleep(res, 300)
   return res.json()
 }

513-535: Replace any[] with a more specific type.

Using any[] reduces type safety and makes the code harder to maintain. Consider using a more specific type or at least unknown[].

♻️ Suggested improvement
-async function fetchAll(url: string) {
+async function fetchAll<T = unknown>(url: string): Promise<T[]> {
   let page = 1;
-  let results: any[] = [];
+  let results: T[] = [];

   while (true) {
     const res = await fetch(`${url}&per_page=100&page=${page}`, {

This preserves flexibility while providing better type safety at call sites.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3999e27 and 1ba2582.

📒 Files selected for processing (2)
  • components/home-dashboard.tsx
  • scripts/generateLeaderboard.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
🧬 Code graph analysis (1)
components/home-dashboard.tsx (7)
lib/db.ts (2)
  • ActivityGroup (21-26)
  • MonthBuckets (34-39)
types/config.ts (1)
  • Config (53-58)
scripts/generateLeaderboard.ts (1)
  • RepoStats (471-491)
lib/utils.ts (1)
  • cn (5-7)
components/Leaderboard/stats-card/activity-line-card.tsx (1)
  • ActivityLineCard (139-314)
components/Leaderboard/stats-card/activity-types.tsx (1)
  • ActivityTypes (44-148)
components/PaginatedActivitySection.tsx (1)
  • PaginatedActivitySection (32-286)
🔇 Additional comments (2)
scripts/generateLeaderboard.ts (2)

539-582: LGTM! Bot filtering is correctly implemented.

The metric fetcher functions correctly filter out bot users using isBotUser() and properly handle date range filtering for current and previous periods. This ensures contribution stats reflect only human activity as intended.


584-594: LGTM!

The function correctly writes the repository overview data with appropriate metadata (timestamp and period).

import { PaginatedActivitySection } from "@/components/PaginatedActivitySection";
import { ActivityGroup, MonthBuckets } from "@/lib/db";
import { Config } from "@/types/config";
import { RepoStats } from "@/scripts/generateLeaderboard";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Move RepoStats type to a shared types directory.

Importing types directly from a build script (scripts/generateLeaderboard.ts) into a client component creates tight coupling between build-time and runtime code. This violates separation of concerns and makes the codebase harder to maintain.

♻️ Recommended refactor

Create a new shared types file (e.g., types/repos.ts or add to an existing types file) and move the RepoStats type definition there. Then update both this file and scripts/generateLeaderboard.ts to import from the shared location:

-import { RepoStats } from "@/scripts/generateLeaderboard";
+import { RepoStats } from "@/types/repos";

Update scripts/generateLeaderboard.ts:

+import { RepoStats } from "@/types/repos";
+
-export type RepoStats = {
-  // ... type definition
-}
🤖 Prompt for AI Agents
In @components/home-dashboard.tsx at line 25, Move the RepoStats type out of the
build script into a shared types module and update imports: create a new types
file (e.g., types/repos.ts) exporting the RepoStats type, change this component
to import RepoStats from that shared module instead of
scripts/generateLeaderboard, and update scripts/generateLeaderboard to import
RepoStats from the new shared module as well so both runtime components and
build scripts reference the same centralized type.

Comment thread scripts/generateLeaderboard.ts Outdated
Comment thread scripts/generateLeaderboard.ts
Comment thread scripts/generateLeaderboard.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In @scripts/generateLeaderboard.ts:
- Around line 880-881: The call to generateRepoOverview() can throw and
currently bubbles up to fail generateYear() and exit the whole leaderboard run;
wrap the generateRepoOverview() invocation (the call site inside
generateYear()/the end of scripts/generateLeaderboard.ts where you call await
generateRepoOverview()) in a try/catch, log the error (including error details)
via the existing logger, and allow execution to continue (do not rethrow or call
process.exit) so year/week/month artifacts still get produced; if desired, set a
boolean/flag or return value to indicate overview failed for later reporting.
- Around line 471-497: The current window boundaries allow a merge at exactly
CURRENT_START to be counted in both windows and the RepoStats type uses
redundant unions; set PREVIOUS_END = CURRENT_START and change the
previous-window upper-bound check to be exclusive (< PREVIOUS_END instead of <=
PREVIOUS_END) wherever merges are filtered (so events at CURRENT_START are only
in current), and simplify RepoStats by removing pointless unions like number | 0
(use number) and change name: string | null to name: string to match usage.
🧹 Nitpick comments (1)
scripts/generateLeaderboard.ts (1)

584-648: Make overview generation more robust (directory, ordering, typing).

  • writeRepoOverview() assumes public/leaderboard exists (currently true via generateYear(), but easy to break if reused).
  • meta is any; a missing owner/field will crash the whole repo’s processing.
  • Consider sorting res (e.g., by current.currentTotalContribution) to keep output stable for the UI.
Proposed diff
 function writeRepoOverview(repo:RepoStats[]) {
+  const outDir = path.join(process.cwd(), "public", "leaderboard");
+  fs.mkdirSync(outDir, { recursive: true });
   fs.writeFileSync(
-      path.join(process.cwd(), "public", "leaderboard", "overview.json"),
+      path.join(outDir, "overview.json"),
       JSON.stringify({
         updatedAt: Date.now(),
         period: "Last_30days",
-        repos: repo
+        repos: repo
       }, null, 2)
     );
     console.log(`✅ Generated overview.json (${repo.length} repos)`);
 }
-  writeRepoOverview(res);
+  res.sort((a, b) => b.current.currentTotalContribution - a.current.currentTotalContribution);
+  writeRepoOverview(res);
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ba2582 and 961e04d.

📒 Files selected for processing (1)
  • scripts/generateLeaderboard.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.

Comment thread scripts/generateLeaderboard.ts
Comment thread scripts/generateLeaderboard.ts Outdated
Comment on lines +539 to +582
async function fetchIssuesCreated(repo: string) {
console.log(" 🔎 Fetching current issues...");
const issues = await fetchAll(
`${GITHUB_API}/repos/${ORG}/${repo}/issues?state=all&since=${iso(CURRENT_START)}`
);

return issues.filter(
i =>
!i.pull_request &&
new Date(i.created_at) >= CURRENT_START &&
!isBotUser(i.user)
).length;
}

async function fetchPRsOpened(repo: string) {
console.log(" 🔎 Fetching current PRs opened...");
const prs = await fetchAll(
`${GITHUB_API}/repos/${ORG}/${repo}/pulls?state=all&sort=created&direction=desc`
);

return prs.filter(
pr => new Date(pr.created_at) >= CURRENT_START && (!isBotUser(pr.user))
).length;
}

async function fetchPRsMerge(repo:string) {
console.log(" 🔎 Fetching PRs merged...");
const prs = await fetchAll(
`${GITHUB_API}/repos/${ORG}/${repo}/pulls?state=closed&sort=updated&direction=desc`
);

let current = 0;
let previous = 0;

for (const pr of prs) {
if (!pr.merged_at) continue;
if (isBotUser(pr.user)) continue;
const mergedAt = new Date(pr.merged_at);
if (mergedAt >= CURRENT_START && mergedAt <= NOW) current++;
if (mergedAt >= PREVIOUS_START && mergedAt <= PREVIOUS_END) previous++;
}

return { current, previous };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, verify the actual code at the specified location
cd scripts && wc -l generateLeaderboard.ts && head -590 generateLeaderboard.ts | tail -55

Repository: CircuitVerse/community-dashboard

Length of output: 1677


🌐 Web query:

GitHub Search API count PRs merged issues created date range best practice official documentation

💡 Result:

Short answer — best practices and official guidance:

  • Use the Search API query qualifiers: is:pr is:merged merged:YYYY-MM-DD..YYYY-MM-DD for merged PR counts, and is:issue created:YYYY-MM-DD..YYYY-MM-DD for issues created in a date range. Construct queries the same way as on GitHub.com and pass them to the search endpoint (q=...). [1][2]

  • Expect the Search API to return total_count, incomplete_results, and be subject to the Search-specific rate limits — authenticate your requests to get higher limits and watch X-RateLimit headers. Use per_page (max 100) + pagination when you need items. [2]

  • Important limitation: GitHub’s search result set is effectively capped for practical retrieval (historically you can only page the first ~1,000 results), so total_count from search may be an estimate and you cannot reliably enumerate arbitrarily-large result sets with a single search. To get exact counts beyond that, use repository-scoped REST endpoints (list issues / list pulls) with date filtering + pagination, GraphQL, or time-slicing your queries (split the date range into smaller windows). [3][4]

  • Recommended workflow for accurate counts over ranges:

    1. Try Search API first for quick estimates (use qualifiers above). [1][2]
    2. If you need exact counts or >1,000 results, call repository-specific REST endpoints (List issues, List pull requests) or use GraphQL and paginate through results or split the date range into smaller windows (e.g., per-day / per-week) to avoid the search cap. [4][3]

References:

If you want, I can: (A) give exact example queries and curl/octokit/GraphQL snippets for counts over a specific date range, or (B) help split a date range into safe time slices and provide code to iterate and sum counts. Which do you want?


🌐 Web query:

GitHub Search API total_count accuracy limits caveats official

💡 Result:

Summary — GitHub Search API total_count accuracy, limits, and caveats

Key points

  • total_count is returned by the Search API but is not guaranteed exact for large result sets; results can be truncated by timeouts and the response may set incomplete_results: true. Relying on total_count as a precise, stable count is unsafe. [1][4]
  • The Search API enforces a practical cap: you cannot page through more than ~1000 results for a single query (many community reports and discussions; the API/UI show different reachable counts). To get beyond that you must narrow the query (date ranges, other filters) and run multiple queries. [2][3][5]
  • Search has custom rate limits and time limits. Slow/expensive queries may time out and return partial matches; those cases set incomplete_results = true. Respect X-RateLimit headers (search uses lower per-minute limits). [1]
  • API results (indexing) may differ from GitHub web UI search because indexing state, sync timing, and different search backends can produce different counts and items. Expect transient variation. [3][5]

Practical recommendations

  • Treat total_count as an estimate, not an authoritative population count. Check incomplete_results; if true, consider splitting the query (by date, repo, language, etc.) and re-running smaller queries to build an accurate aggregate.
  • Page only up to the available limit (per_page up to 100) and design for the 1000-results ceiling by slicing the search space.
  • Monitor X-RateLimit-* headers and back off on 403/rate-limit responses.
  • For stable, repeatable extraction use narrow predicates and deterministic pagination; for very large sets, aggregate with multiple bounded queries.

Sources

  • Official GitHub Search API docs (timeouts, incomplete_results, rate limits). [1]
  • Community/issue reports on the 1000-results limit and behavior. [2][4][5]

References
[1] GitHub Search API docs — timeouts, incomplete_results, rate limits.
[2] Issue/discussion: “There is a limit of 1000 results per search.” (PyGithub/GitHub threads).
[3] Issue: API vs web search differences — indexing and result-count divergence.
[4] Community discussion reporting total_count variability / incomplete results behavior.
[5] Additional community threads on 1000-result cap and practical workarounds.

Would you like me to fetch the exact doc URLs or show example code to page/slice queries?


🌐 Web query:

GitHub GraphQL search API count issues PRs per repository date range performance

💡 Result:

Short answer and recommendations:

  • Limits to know

    • GraphQL enforces a query “points” rate limit (typically 5,000 points/hr for a user) plus secondary limits and a 500k node-per-call validation; include rateLimit in queries to monitor usage. (docs.github.com)
    • The GitHub search API (REST or GraphQL search field) returns at most 1,000 result items for any single search query (total_count can be larger, but you cannot page past the first 1,000). (docs.github.com)
  • Counting issues/PRs per repo in a date range — practical approaches

    1. Repository-level connections (recommended when you can iterate repos)

      • Use repository.issues (IssueConnection) and repository.pullRequests connections. IssueFilters supports a since (DateTime) filter for “updated at or after” and other filters (assignee, createdBy, states). You can request totalCount for a connection and paginate. This is efficient per-repo and avoids the 1,000-search-result limit. (docs.github.com)
      • Caveat: issues.since is “updated at or after” (not strictly “created at”), so getting counts for a created-date range may require additional filtering client-side or fetching items and filtering by createdAt field.
    2. Search queries (useful when you need cross-repo counts or want to use created: qualifiers)

      • Use the search API (GraphQL search(...) or REST /search/issues) with qualifiers like repo:, is:issue/is:pr, created:, updated: to restrict a date range. But each search result set is capped to the first 1,000 returned items — to cover more than 1,000 matches you must split the date range (e.g., per-day or per-hour buckets) and run multiple queries. (docs.github.com)
  • Performance and cost trade-offs

    • GraphQL query complexity and node count affect “points” cost; deep queries and requesting many fields increase cost and risk hitting node/compute limits — request only totalCount where possible, keep first/last <=100 and paginate. (docs.github.com)
    • If you must compute counts across many repositories or long date ranges, prefer:
      • Iterating repos and using repository-level connections with since + totalCount (batch and paginate repos to spread cost). (docs.github.com)
      • Or run search queries split into narrow date buckets so each search returns <=1000 items; aggregate counts across buckets. (stackoverflow.com)
    • Use exponential backoff, limit concurrency (≤100 concurrent requests), and include rateLimit in your queries to avoid secondary limits. (docs.github.com)
  • Quick implementation tips

    • For per-repo created-date counts: fetch issues/pullRequests connections and page items, filtering client-side by createdAt if the API lacks a created-date filter on the connection. Use totalCount only when it matches your filter (e.g., states/since); otherwise page and count. (docs.github.com)
    • For large cross-repo queries, break the date range into slices (day/hour) so each search query’s result set <1,000, then sum counts. (stackoverflow.com)

If you want, tell me: (a) how many repositories, (b) whether you need created vs updated date counts, and (c) whether you prefer GraphQL or REST — I’ll draft a sample GraphQL query and a date-slicing plan sized to your rate limits.

Citations:


Performance issue confirmed: add early-stop pagination and prefer GraphQL repository connections over Search API.

The current implementation fetches all PRs/issues without server-side time filtering, causing unnecessary API calls and rate-limit exhaustion. This is a real inefficiency.

However, refine the solution approach:

  • Search API total_count is unreliable: GitHub's official documentation states total_count is an estimate (not exact), incomplete_results can indicate truncation/timeouts, and practical result pagination is capped at ~1,000 items. Relying on it for counts is unsafe.
  • Recommended approaches per GitHub docs (in priority order):
    1. GraphQL repository-level connections (best for per-repo counts): Query repository.issues / repository.pullRequests with createdAt filters and request totalCount on the connection. Avoids the 1,000-result search limit and is accurate.
    2. REST repository endpoints with pagination + date filtering: List issues/pulls per repo, filter by date server-side where supported (since parameter), and paginate through results. Early-stop when crossing your date threshold (as shown in the review's minimal approach).
    3. Time-sliced search queries (if cross-repo search needed): Split the date range into smaller windows (per-day/per-week) and aggregate counts; each slice ≤1,000 results.

The early-stop pagination approach shown is valid but incomplete—it optimizes one function. Consider migrating to GraphQL repository connections for all three metric fetchers for cleaner, more efficient queries.

Comment thread scripts/generateLeaderboard.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
components/Leaderboard/LeaderboardView.tsx (1)

455-463: Remove commented-out dead code.

The updateRolesParam function is no longer used since its logic has been inlined into toggleRole (lines 364-383). Commented-out code should be removed rather than left in the codebase, as version control preserves the history if needed.

🧹 Proposed cleanup
-  // const updateRolesParam = (roles: Set<string>) => {
-  //   const params = new URLSearchParams(searchParams.toString());
-  //   if (roles.size > 0) {
-  //     params.set("roles", Array.from(roles).join(","));
-  //   } else {
-  //     params.delete("roles");
-  //   }
-  //   if (typeof window !== 'undefined') window.history.replaceState(null, '', `${pathname}?${params.toString()}`);
-  // };
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 961e04d and c62b09a.

📒 Files selected for processing (6)
  • app/ThemeSelector.tsx
  • components/Leaderboard/LeaderboardCard.tsx
  • components/Leaderboard/LeaderboardView.tsx
  • components/people/ContributorCard.tsx
  • components/people/ContributorDetail.tsx
  • components/people/PeopleStats.tsx
💤 Files with no reviewable changes (2)
  • components/people/ContributorDetail.tsx
  • components/people/ContributorCard.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
📚 Learning: 2026-01-07T10:51:39.554Z
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.

Applied to files:

  • components/Leaderboard/LeaderboardView.tsx
🔇 Additional comments (6)
app/ThemeSelector.tsx (1)

15-15: Good cleanup of unused variable.

Removing the unused theme variable from the destructuring is a clean refactor that improves code quality without affecting functionality.

components/Leaderboard/LeaderboardCard.tsx (1)

226-226: LGTM! Excellent adherence to naming conventions.

Prefixing the unused activityName parameter with an underscore in the filter callbacks is a standard best practice that improves code readability and satisfies linting rules. The filter predicate only uses data.count, and the subsequent .map() callbacks correctly define their own activityName parameter in their respective scopes.

Also applies to: 314-314, 455-455, 550-550

components/Leaderboard/LeaderboardView.tsx (3)

29-29: LGTM! Clean removal of unused import.

The useRouter import was correctly removed as the component now consistently uses window.history.replaceState() for URL parameter updates throughout. This aligns with the retrieved learning that client-side URL management with proper guards provides better UX in this codebase.


636-636: LGTM! Correct use of unused parameter convention.

Renaming the parameter from e to _e correctly signals that the event parameter is intentionally unused in the handler. This follows the standard convention for marking unused function parameters.


811-811: LGTM! Correct removal of unused parameter.

The index parameter was correctly removed from the map callback since it's not used anywhere in the function body (lines 812-825). The rank is computed from the pre-calculated entryRanks map instead, which ensures consistent ranking across pagination.

components/people/PeopleStats.tsx (1)

177-181: No changes needed. The code correctly implements Next.js Image with the project's configuration.

The unoptimized: true setting in next.config.ts disables optimization requirements, making the width and height props optional. Additionally, the GitHub avatar domain (avatars.githubusercontent.com) is already configured in the remotePatterns array, so the Image component will load properly. This implementation is correct and follows the project's Next.js settings.

Likely an incorrect or invalid review comment.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @lib/db.ts:
- Around line 227-243: The getReposOverview function currently reads and
JSON.parse()s overview.json without guarding against malformed JSON; wrap the
file read and JSON.parse call in a try-catch, catch any parsing or read errors,
log the error (or use an existing logger) and return an empty array on failure
to avoid crashing the app; mirror the defensive pattern used in
getRecentActivitiesGroupedByType so the function returns [] when the file is
missing or corrupted and includes a clear error log referencing
getReposOverview.
🧹 Nitpick comments (3)
lib/db.ts (1)

28-32: Consider removing commented-out type if no longer needed.

If RecentActivitiesJSON is permanently deprecated, consider removing the commented block to keep the codebase clean.

scripts/generateLeaderboard.ts (2)

499-510: Consider logging errors in fetchRepoMeta for better observability.

The function silently returns null on API failures. While the caller logs when the fetch fails, adding error logging here would help diagnose API issues during script execution.

📊 Suggested enhancement
 async function fetchRepoMeta(repo:string) {
    const res = await fetch(`${GITHUB_API}/repos/${ORG}/${repo}`, {
     headers: {
       Authorization: `Bearer ${TOKEN}`,
       Accept: "application/vnd.github+json",
     }
   });
 
-  if (!res.ok) return null;
+  if (!res.ok) {
+    console.error(`   ⚠️ Failed to fetch meta for ${repo}: ${res.status}`);
+    return null;
+  }
   await smartSleep(res, 300)
   return res.json()
 }

586-596: Add error handling for file write operation.

While the directory is created earlier in the flow, wrapping the file write in a try-catch would make this function more resilient and provide clearer error messages if the write fails due to permissions or disk space issues.

🛡️ Proposed enhancement
 function writeRepoOverview(repo:RepoStats[]) {
+  try {
     fs.writeFileSync(
       path.join(process.cwd(), "public", "leaderboard", "overview.json"),
       JSON.stringify({
         updatedAt: Date.now(),
         period: "Last_30days",
         repos: repo
       }, null, 2)
     );
     console.log(`✅ Generated overview.json (${repo.length} repos)`);
+  } catch (error) {
+    console.error(`❌ Failed to write overview.json:`, error);
+    throw error;
+  }
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c62b09a and 86bd153.

📒 Files selected for processing (2)
  • lib/db.ts
  • scripts/generateLeaderboard.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
🧬 Code graph analysis (1)
lib/db.ts (1)
scripts/generateLeaderboard.ts (1)
  • RepoStats (471-491)
🔇 Additional comments (8)
lib/db.ts (1)

3-3: LGTM!

The import additions are appropriate for the new getReposOverview function that returns RepoStats[].

scripts/generateLeaderboard.ts (7)

471-495: LGTM with note on time constants.

The RepoStats type is well-structured. The module-level time constants (NOW, CURRENT_START, PREVIOUS_START) are appropriate for a script that runs and exits. If this module were ever used in a long-running process, these would need to be computed at invocation time.


512-537: LGTM!

The fetchAll helper has good error handling, proper pagination logic, and appropriate rate limiting with smartSleep.


541-553: LGTM!

The function correctly filters out bot users and pull requests, counting only genuine issues created by humans within the 30-day window.


555-564: LGTM!

Consistent bot filtering and date range validation ensure accurate PR metrics.


566-584: LGTM!

The date range logic correctly separates current (last 30 days) and previous (30-60 days ago) merged PRs, with proper bot filtering.


598-650: LGTM with resilient error handling.

The per-repo try-catch ensures that failures in individual repositories don't stop the entire overview generation. The sequential processing is appropriate given GitHub API rate limits.


882-882: LGTM!

The placement of generateRepoOverview() at the end of the year generation flow ensures the overview is created alongside other leaderboard data.

Comment thread lib/db.ts

@naman79820 naman79820 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Atharva7126 some conflicts in generateLeaderboard and coderabbit suggestions. Thankss :))

@Atharva7126

Copy link
Copy Markdown
Collaborator Author

@naman79820 done :]
also run the genearatedLearder.ts so we can get the latest data, along side we can also test it in production

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
lib/db.ts (2)

28-32: Consider removing commented-out code.

The commented RecentActivitiesJSON type appears to be unused. If it's no longer needed, removing it would improve code maintainability.


227-246: LGTM: Error handling implemented correctly.

The function properly handles file reading errors with try-catch and returns a safe empty array fallback. The implementation is consistent with other data-fetching functions in this file.

Optional improvements for production robustness

Consider these enhancements for better runtime safety and observability:

  1. Runtime type validation: Add validation to ensure data.repos conforms to the RepoStats[] structure before returning, especially if the JSON file could be manually edited or corrupted.

  2. Enhanced error logging: Replace console.error with structured logging or an error tracking service for better observability in production environments.

These are nice-to-have improvements since the current implementation provides safe fallbacks and the JSON file is generated by your own scripts.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86bd153 and 184e61d.

📒 Files selected for processing (1)
  • lib/db.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
🧬 Code graph analysis (1)
lib/db.ts (1)
scripts/generateLeaderboard.ts (1)
  • RepoStats (471-491)
🔇 Additional comments (1)
lib/db.ts (1)

3-3: LGTM: Import updated correctly.

The RepoStats import is properly added to support the new getReposOverview function's return type.

@naman79820

Copy link
Copy Markdown
Member

still there is merge conflicts @Atharva7126

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
components/Leaderboard/LeaderboardCard.tsx (1)

566-642: Critical: Syntax errors and merge conflict artifacts block compilation.

The desktop layout section contains unresolved merge conflicts and syntax errors that prevent the code from compiling:

  1. Line 587: Orphaned > closing tag with no matching opening tag
  2. Lines 588-600: Duplicate nested JSX fragment inside the IconComponent conditional (lines 584-586 already render IconComponent, then lines 588-600 duplicate it)
  3. Lines 606-642: Entire "Top Activities" section appears to be a duplicate or misplaced fragment
  4. Structural issue: Lines 566-604 define an "Activity Tags" section but lines 586-600 contain conflicting markup

This aligns with the PR comment that "merge conflicts still exist." The file requires manual conflict resolution.

🔧 Resolution guidance

The desktop layout section (starting line 509) should likely contain only ONE activity display block. Review the git diff to determine which version is correct:

  • Keep lines 566-604 (Activity Tags) and remove lines 606-642 (Top Activities), OR
  • Keep lines 606-642 (Top Activities) and remove lines 566-604 (Activity Tags)

Then fix the syntax error by removing the orphaned code at lines 586-600 (the duplicate IconComponent rendering inside the conditional).

Expected structure should be:

{/* Activity Tags or Top Activities - pick one */}
<div className="space-y-1 flex-1">
  {sortActivitiesByPriority(Object.entries(entry.activity_breakdown))
    .filter(([_activityName, data]) => data.count > 0)
    .map(([activityName, data]) => {
      const style = getActivityStyle(activityName);
      const IconComponent = style.icon;
      
      return (
        <div key={activityName} className={cn(/* ... */)}>
          <div className="flex items-center gap-1.5">
            {IconComponent && (
              <IconComponent className={cn("w-3 h-3", style.textColor)} />
            )}
            <span className={cn("font-medium truncate", style.textColor)}>
              {activityName}:
            </span>
          </div>
          <div className="flex items-center gap-1">
            <span className="font-semibold">{data.count}</span>
            <span className={cn("font-bold", style.textColor)}>+{data.points}</span>
          </div>
        </div>
      );
    })}
</div>
components/Leaderboard/LeaderboardView.tsx (1)

637-730: Critical: Missing closing tag breaks JSX structure.

The <div className="space-y-4"> opened at line 640 is never closed before the </PopoverContent> tag at line 730. This syntax error will prevent the component from rendering.

🐛 Proposed fix

Add the missing closing </div> tag after the Role section and before </PopoverContent>:

                              ))}
                            </div>
                          </div>
+                       </div>
                      </PopoverContent>

The correct structure should be:

<PopoverContent>
  <div className="space-y-4">
    {/* Sort By Section */}
    <div>...</div>
    {/* Divider */}
    <div />
    {/* Role Section */}
    <div>...</div>
  </div>  ← Missing this closing tag
</PopoverContent>
🧹 Nitpick comments (1)
components/Leaderboard/LeaderboardView.tsx (1)

477-485: Remove commented-out code.

The updateRolesParam function has been refactored and its logic inlined in toggleRole and other functions. Commented-out code should be removed to maintain codebase cleanliness.

♻️ Proposed cleanup
-  // const updateRolesParam = (roles: Set<string>) => {
-  //   const params = new URLSearchParams(searchParams.toString());
-  //   if (roles.size > 0) {
-  //     params.set("roles", Array.from(roles).join(","));
-  //   } else {
-  //     params.delete("roles");
-  //   }
-  //   if (typeof window !== 'undefined') window.history.replaceState(null, '', `${pathname}?${params.toString()}`);
-  // };
-
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3bf81d and 4eeba0d.

📒 Files selected for processing (2)
  • components/Leaderboard/LeaderboardCard.tsx
  • components/Leaderboard/LeaderboardView.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
📚 Learning: 2026-01-07T10:51:39.554Z
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.

Applied to files:

  • components/Leaderboard/LeaderboardView.tsx
🧬 Code graph analysis (1)
components/Leaderboard/LeaderboardCard.tsx (1)
lib/utils.ts (1)
  • cn (5-7)
🪛 Biome (2.1.2)
components/Leaderboard/LeaderboardView.tsx

[error] 640-640: Expected corresponding JSX closing tag for 'div'.

Opening tag

closing tag

(parse)

components/Leaderboard/LeaderboardCard.tsx

[error] 642-642: Expected an expression but instead found '<'.

Expected an expression here.

(parse)

🔇 Additional comments (3)
components/Leaderboard/LeaderboardCard.tsx (1)

246-246: LGTM! Good practice to indicate unused variables.

Prefixing the unused activityName parameter with an underscore correctly signals that it's intentionally unused in the filter predicate.

Also applies to: 334-334, 569-569, 611-611

components/Leaderboard/LeaderboardView.tsx (2)

658-658: LGTM: Clear unused parameter naming.

Using _e instead of e clearly indicates the event parameter is intentionally unused, which is a good practice for code readability.


831-831: LGTM: Simplified map callback.

Removing the unused index parameter from the map callback improves code clarity while preserving all functionality.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
components/Leaderboard/LeaderboardCard.tsx (1)

475-475: Apply consistent parameter naming for uniformity.

For consistency with the changes at lines 246, 334, and 569, this filter callback should also use _activityName since the parameter is unused.

♻️ Suggested consistency fix
-                  .filter(([activityName, data]) => data.count > 0)
+                  .filter(([_activityName, data]) => data.count > 0)
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b08de52 and dc54f37.

📒 Files selected for processing (1)
  • components/Leaderboard/LeaderboardCard.tsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: akshitvigg
Repo: CircuitVerse/community-dashboard PR: 139
File: app/leaderboard/page.tsx:1-24
Timestamp: 2026-01-07T10:51:39.554Z
Learning: In the CircuitVerse/community-dashboard Next.js app, client-side redirect with skeleton loading is intentionally used in app/leaderboard/page.tsx instead of server-side redirect() because the server-side redirect causes a blank screen during navigation. The client-side approach with router.replace() and LeaderboardSkeleton provides better UX with immediate visual feedback.
🔇 Additional comments (2)
components/Leaderboard/LeaderboardCard.tsx (2)

246-246: LGTM! Good practice for unused parameters.

Prefixing the unused activityName parameter with an underscore correctly signals that it's intentionally unused in the filter predicates. This follows best practices and prevents linter warnings.

Also applies to: 334-334, 569-569


566-598: LGTM! Activity Tags section is well-implemented.

The Activity Tags section is correctly structured with:

  • Proper parameter naming (_activityName in filter, activityName in map)
  • Consistent styling with color-coded activity types
  • Responsive layout and proper icon integration
  • Correct display of counts and points

@naman79820 naman79820 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Atharva7126 why did you remove unnecessary changes?

Image

@Atharva7126

Atharva7126 commented Jan 11, 2026

Copy link
Copy Markdown
Collaborator Author

just accepted the current changes @naman79820
do you want me to add it again?

@naman79820

Copy link
Copy Markdown
Member

Yes you need to add every unnecessary changes that you have removed. The one i sent image was being used to fetch data for issue labeled assigned and closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feat: Enhanced Home Dashboard with Repository-wise Statistics View

2 participants