Skip to content

feat: implement analytics dashboard and fix server-side filtering#255

Merged
mehul-m-prajapati merged 7 commits into
GitMetricsLab:mainfrom
ishwari418:feat/dashboard-and-filtering-fix
May 20, 2026
Merged

feat: implement analytics dashboard and fix server-side filtering#255
mehul-m-prajapati merged 7 commits into
GitMetricsLab:mainfrom
ishwari418:feat/dashboard-and-filtering-fix

Conversation

@ishwari418
Copy link
Copy Markdown

@ishwari418 ishwari418 commented May 15, 2026

Related Issue

Description
This PR introduces two major improvements to the GitHub Tracker:

Analytics Dashboard: Added a visual summary section at the top of the Tracker page using Recharts. It includes a Pie Chart for contribution mix (Issues vs. PRs) and a Bar Chart for activity by repository.
Server-Side Filtering: Refactored the filtering and search logic to use the GitHub Search API. This fixes a bug where filters only applied to the first 10 items. Users can now search and filter across their entire contribution history.
Code Optimization: Renamed core components for better maintainability and optimized API requests to reduce rate-limit usage.
How Has This Been Tested?
Manual Testing: Verified on localhost:5173 using a Personal Access Token.
Search Verification: Confirmed that searching for titles now works across multiple pages of data.
Visual Check: Verified that the Dashboard is fully responsive and compatible with the existing Dark/Light mode theme.

Type of Change
Bug fix
New feature

Summary by CodeRabbit

  • New Features

    • Added a Dashboard with charts showing issue vs PR totals and top-repository activity.
    • Added debounced search behavior for more responsive querying.
  • Improvements

    • Fetching now returns both issues and PRs so summaries and totals stay in sync.
    • Tracker page auto-refreshes based on search, repo/date/state filters and tab/page changes.
    • Improved login/signup error handling for clearer messages.
  • Chores

    • Updated project dependencies for charting and tooling.

Review Change Stack

@netlify
Copy link
Copy Markdown

netlify Bot commented May 15, 2026

Deploy Preview for github-spy ready!

Name Link
🔨 Latest commit 0ba9174
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6a09f033a3ca9d00084ef77c
😎 Deploy Preview https://deploy-preview-255--github-spy.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
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Warning

Rate limit exceeded

@ishwari418 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 23 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef721aee-f994-4e16-9301-c2d6c12d216b

📥 Commits

Reviewing files that changed from the base of the PR and between 0dc6dbe and 0ba9174.

📒 Files selected for processing (1)
  • src/hooks/useGitHubData.ts
📝 Walkthrough

Walkthrough

Adds a Recharts Dashboard component, extends useGitHubData to accept typed filters and fetch issues/PRs concurrently with request-id guarding, integrates the Dashboard into Tracker with debounced effect-driven fetching, and applies typing and error-handling tweaks across hooks and pages.

Changes

Analytics Dashboard Implementation

Layer / File(s) Summary
Library dependencies
package.json
Adds recharts to dependencies and inserts backend/test tooling entries (express, mongoose, jasmine, passport, passport-local, supertest, typescript-eslint, vite) in devDependencies.
Dashboard component with charts
src/components/Dashboard.tsx
New default-exported Dashboard React component with GitHubItem/DashboardProps types; prepares a two-slice pie dataset and top-5 repository bar dataset and renders responsive Recharts PieChart and BarChart with MUI layout and theme-aware colors.
Debounce utility hook
src/hooks/useDebounce.ts
Adds useDebounce<T>(value, delay) returning a debounced value via timeout-managed state.
Auth hook API change
src/hooks/useGitHubAuth.ts
Removes internal error state and stops returning error/setError from the hook’s public API.
GitHub data hook: filters & concurrency
src/hooks/useGitHubData.ts
Introduces GitHubItem and FetchFilters types, requires `Octokit
Tracker page refactor & integration
src/pages/Tracker/Tracker.tsx
Renames HomeTracker, imports Dashboard and useDebounce, replaces client-side filtering with a dependency-driven useEffect that builds filters and calls fetchData(username, page+1, ROWS_PER_PAGE, type, filters), adjusts submit/pagination logic, selects data by active tab, and conditionally renders Dashboard with totals and current tab data.
Typing and error-handling tweaks
src/pages/ContributorProfile/ContributorProfile.tsx, src/pages/Contributors/Contributors.tsx, src/pages/Login/Login.tsx, src/pages/Signup/Signup.tsx
Adds a local Profile type; removes unused catch parameters; updates Login catch to treat errors as unknown and use axios.isAxiosError; reformats Signup POST and normalizes success-message comparison.

Sequence Diagram

sequenceDiagram
  participant User
  participant Tracker
  participant useDebounce
  participant useGitHubData
  participant GitHubAPI
  participant Dashboard

  User->>Tracker: set filters (search/repo/date/state)
  Tracker->>useDebounce: debounce inputs
  Tracker->>useGitHubData: fetchData(username, page, perPage, activeTab, filters)
  useGitHubData->>GitHubAPI: GET /search/issues?q=... (issues & PRs)
  GitHubAPI-->>useGitHubData: responses
  useGitHubData-->>Tracker: issues/prs + totalIssues/totalPrs (guarded by requestId)
  Tracker->>Dashboard: pass totals + currentTabData + theme
  Dashboard-->>User: render pie & bar charts
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

gssoc25, level:intermediate

Suggested reviewers

  • mehul-m-prajapati

Poem

🐰 I hopped in with charts and a cheerful tune,
Pie slices glowing like a silver moon,
Bars that climb where repos meet,
Totals tally every issue and PR beat,
Hop, gaze, enjoy the dashboard bloom!

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR partially addresses linked issue #253: it implements a Pie Chart and Bar Chart for dashboard analytics, but omits the Activity Summary Cards and Activity Timeline (Line Graph) that were required. Implement Activity Summary Cards (Total Issues, Total PRs, Merged PRs counts) and Activity Timeline (Line Graph) showing contributions over the last 30 days as specified in issue #253.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Most changes are in-scope; however, dependency additions (express, mongoose) and modifications to useGitHubAuth error handling appear unrelated to the dashboard and filtering objectives. Clarify the purpose of adding backend dependencies (express, mongoose) and why useGitHubAuth error state was removed, as these are not mentioned in the linked issue objectives.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures both major changes: the analytics dashboard implementation and server-side filtering fix, which align with the main objectives of the PR.
Description check ✅ Passed The description follows the template structure with Related Issue, Description, Testing, and Type of Change sections, though the formatting deviates slightly from the template.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

🎉 Thank you @ishwari418 for your contribution. Please make sure your PR follows https://github.com/GitMetricsLab/github_tracker/blob/main/CONTRIBUTING.md#-pull-request-guidelines

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (1)
src/hooks/useGitHubData.ts (1)

47-89: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

rateLimited is set but never cleared — the hook gets permanently blocked.

Once a 403 is hit, setRateLimited(true) runs and the early return on line 50 (if (!octokit || !username || rateLimited) return;) prevents every subsequent call for the lifetime of the component. There's no timeout, no reset on token/username change, and no manual recovery path, so users have to do a full page reload after a single rate-limit error — even after the GitHub window resets or they paste a different PAT.

Consider resetting rateLimited when getOctokit/username changes, or expose a reset function from the hook and call it on form submit / auth change. Optionally honor the X-RateLimit-Reset header and auto-clear after that timestamp.

🛠️ Suggested reset on auth change
   const fetchData = useCallback(
     async (username: string, page = 1, perPage = 10, type?: 'issue' | 'pr', filters: any = {}) => {
       const octokit = getOctokit();
       if (!octokit || !username || rateLimited) return;
+      // reset transient errors on a fresh, non-rate-limited call
+      setError('');
       ...
     },
     [getOctokit, rateLimited]
   );
+
+  const reset = useCallback(() => {
+    setRateLimited(false);
+    setError('');
+  }, []);
+
   return {
     issues,
     prs,
     totalIssues,
     totalPrs,
     loading,
     error,
     fetchData,
+    reset,
   };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/useGitHubData.ts` around lines 47 - 89, The hook permanently blocks
fetches because fetchData (inside useCallback) returns early when the
rateLimited flag is true; update the hook to clear rateLimited when auth or
username changes and provide a manual reset: add logic to reset
setRateLimited(false) when getOctokit() or the username argument changes (e.g.,
in an effect watching getOctokit/username) and expose a reset function from the
hook (e.g., resetRateLimit) that calls setRateLimited(false) so callers (form
submit/auth change) can clear the block; optionally, when catching the 403 in
fetchData, parse the X-RateLimit-Reset header from the response returned by
fetchPaginated and schedule an automatic setRateLimited(false) after that
timestamp.
🧹 Nitpick comments (5)
src/hooks/useGitHubData.ts (1)

12-19: ⚡ Quick win

Replace filters: any with an explicit type.

any removes the main benefit of TS here — typos in keys (startData instead of startDate) silently produce broken queries. A small interface near the top of the file documents the contract and protects callers like Tracker.tsx.

♻️ Suggested type
+export interface GitHubDataFilters {
+  search?: string;
+  repo?: string;
+  startDate?: string;
+  endDate?: string;
+  state?: 'all' | 'open' | 'closed' | 'merged';
+}
+
   const fetchPaginated = async (
     octokit: any,
     username: string,
     type: string,
     page = 1,
     per_page = 10,
-    filters: any = {}
+    filters: GitHubDataFilters = {}
   ) => {
-    async (username: string, page = 1, perPage = 10, type?: 'issue' | 'pr', filters: any = {}) => {
+    async (username: string, page = 1, perPage = 10, type?: 'issue' | 'pr', filters: GitHubDataFilters = {}) => {

Also applies to: 47-48

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/useGitHubData.ts` around lines 12 - 19, Define a strict interface
(e.g., GitHubFetchFilters) near the top of the file and replace the loose
filters: any in the fetchPaginated function signature with filters:
GitHubFetchFilters; the interface should include the expected keys (for example
optional startDate?: string, endDate?: string, repoNames?: string[],
includeForks?: boolean, etc.) so typos are caught at compile time, and update
the other occurrences that currently use filters: any (the ones referenced
around the other function signatures/calls) to use GitHubFetchFilters as well.
src/pages/Tracker/Tracker.tsx (1)

131-171: 💤 Low value

Reuse currentFilteredData instead of recomputing the tab selection.

currentFilteredData on Line 132 already represents tab === 0 ? issues : prs. Passing it through keeps the two sites in sync if the selection rule ever changes.

♻️ Tiny dedup
-        <Dashboard 
-          totalIssues={totalIssues} 
-          totalPrs={totalPrs} 
-          data={tab === 0 ? issues : prs} 
-          theme={theme}
-        />
+        <Dashboard
+          totalIssues={totalIssues}
+          totalPrs={totalPrs}
+          data={currentFilteredData}
+          theme={theme}
+        />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Tracker/Tracker.tsx` around lines 131 - 171, The Dashboard is being
passed a recomputed tab selection (data={tab === 0 ? issues : prs}) even though
currentFilteredData already holds that value; update the Dashboard invocation to
pass data={currentFilteredData} instead (referencing currentFilteredData and the
Dashboard component) so the selection logic is centralized and stays consistent
if the rule changes.
src/components/Dashboard.tsx (3)

27-30: 💤 Low value

Consider adding empty state handling.

When both totalIssues and totalPrs are 0, the pie chart renders but displays no meaningful data. Consider showing a "No data available" message instead.

📊 Proposed empty state check
+const hasData = totalIssues > 0 || totalPrs > 0;
+
 const pieData = [
   { name: 'Issues', value: totalIssues },
   { name: 'Pull Requests', value: totalPrs },
 ];

Then conditionally render the chart or a fallback message based on hasData.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard.tsx` around lines 27 - 30, The pie chart should
handle the empty state when both totalIssues and totalPrs are 0: compute a
hasData flag (e.g., const hasData = totalIssues + totalPrs > 0) and
conditionally render either the pie chart using pieData or a simple fallback
UI/message like "No data available" inside the Dashboard component (where
pieData, totalIssues and totalPrs are defined) so the chart area shows a clear
empty state instead of an empty pie.

32-32: 💤 Low value

Consider using theme-aware colors for better consistency.

The hard-coded COLORS array doesn't adapt to the theme. Using theme palette colors would ensure consistency with the rest of the application's color scheme.

🎨 Proposed theme-aware colors
-const COLORS = ['#0088FE', '#00C49F'];
+const COLORS = [theme.palette.primary.main, theme.palette.secondary.main];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard.tsx` at line 32, The hard-coded COLORS array in
Dashboard (const COLORS) should be replaced with theme-aware colors so the chart
adapts to the app palette; inside the Dashboard component use the app theme
(e.g., via useTheme() or the project’s theme hook) and derive COLORS from
theme.palette (for example primary/main and secondary/main or suitable
contrast/variant keys) and update any consumers of COLORS (chart props or
components that reference const COLORS) to use the new theme-derived array.

17-22: ⚡ Quick win

Replace any types with proper TypeScript interfaces.

Using any for data and theme defeats TypeScript's type safety and can lead to runtime errors if the wrong shape is passed.

♻️ Proposed type definitions
+interface DataItem {
+  repository_url: string;
+  // Add other properties as needed based on the actual data structure
+}
+
+interface Theme {
+  palette: {
+    background: {
+      paper: string;
+    };
+  };
+}
+
 interface DashboardProps {
   totalIssues: number;
   totalPrs: number;
-  data: any[];
-  theme: any;
+  data: DataItem[];
+  theme: Theme;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard.tsx` around lines 17 - 22, The DashboardProps uses
unsafe any types for data and theme; define proper interfaces (e.g., DataItem or
IssuePrItem and DashboardTheme) that reflect the actual shapes used by the
component (for DataItem include fields like id, type ('issue'|'pr'), title,
createdAt, author, state, url and any metadata the component accesses; for
DashboardTheme include colors, spacing, and any theme properties read by the
component) and replace data: any[] with data: DataItem[] and theme: any with
theme: DashboardTheme in the DashboardProps (and update the Dashboard component
signature and any usages to import/consume these interfaces).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Line 22: package.json includes server-side dependencies "express" and
"mongoose" that likely aren't used in this frontend React/Vite project; search
the repository for imports/usages of express and mongoose (look for "express"
and "mongoose" strings and any server-related folders or files) and if there are
no imports or backend files (no API/server code), remove these dependencies from
package.json and package-lock or yarn.lock and update install scripts (run
npm/yarn install after removal); if they are required by a new backend module,
instead move that module into a dedicated backend package or workspace and add
express/mongoose only to that server package to avoid bloating the frontend.

In `@src/components/Dashboard.tsx`:
- Around line 36-39: The loop using data.forEach that computes repoName from
item.repository_url is unsafe and fragile: add a null/undefined guard for item
and item.repository_url before splitting and fallback when parsing fails, then
derive repoName more robustly (e.g., trim, remove trailing slashes, attempt to
parse with the URL constructor or split on '/' from the end while ignoring empty
segments) and only increment repoCounts[repoName] when repoName is non-empty;
update the function/loop that references repository_url and repoCounts to use
this validated parsing and fallback behavior to avoid runtime errors.

In `@src/hooks/useGitHubData.ts`:
- Around line 56-76: When fetching GitHub data in the type-branching block,
avoid leaving the inactive tab’s total stale and stop older requests from
stomping newer state: update the flow in the function that calls fetchPaginated
so that when filters/search/repo/date change you still fetch both sides (or at
minimum fetch the other side’s total) instead of only updating
setIssues/setTotalIssues or setPrs/setTotalPrs for the active type; and add
request cancellation/ordering protection by using an AbortController passed into
fetchPaginated/octokit.request or by tracking an incremental requestId in the
enclosing fetchData and ignoring any responses whose id is older than the latest
before calling setIssues/setPrs/setTotalIssues/setTotalPrs.

In `@src/pages/Tracker/Tracker.tsx`:
- Line 95: The effect in the Tracker component currently includes searchTitle
and selectedRepo in its dependency array and those states update on every
keystroke (handlers around lines 175–202), causing a GitHub Search API call per
character; fix by introducing debounced versions of those inputs (e.g.,
useDebouncedValue or a small debounce hook) and use the debounced values in the
effect dependency array and API call instead of raw searchTitle/selectedRepo,
with the input handlers still updating immediate state but the API driven only
by the debounced state (debounce delay ~300–500ms) so rapid typing won’t trigger
multiple search requests.
- Around line 82-101: The effect that calls fetchData omits username from its
dependency array and handleSubmit is a no-op when page is already 0, so add
username to the useEffect deps and make handleSubmit explicitly trigger a fetch
(or set a submitted boolean that is included in the deps) to guarantee an
initial fetch; specifically, update the dependency list of the useEffect that
references fetchData/username/tab/page/... to include username, and modify
handleSubmit (which currently calls setPage(0)) to either call
fetchData(username, 1, ROWS_PER_PAGE, tab === 0 ? "issue" : "pr", { search:
searchTitle, repo: selectedRepo, startDate, endDate, state: tab === 0 ?
issueFilter : prFilter }) directly or set a new submitted state that the
useEffect watches so the fetch runs even when page === 0.

---

Outside diff comments:
In `@src/hooks/useGitHubData.ts`:
- Around line 47-89: The hook permanently blocks fetches because fetchData
(inside useCallback) returns early when the rateLimited flag is true; update the
hook to clear rateLimited when auth or username changes and provide a manual
reset: add logic to reset setRateLimited(false) when getOctokit() or the
username argument changes (e.g., in an effect watching getOctokit/username) and
expose a reset function from the hook (e.g., resetRateLimit) that calls
setRateLimited(false) so callers (form submit/auth change) can clear the block;
optionally, when catching the 403 in fetchData, parse the X-RateLimit-Reset
header from the response returned by fetchPaginated and schedule an automatic
setRateLimited(false) after that timestamp.

---

Nitpick comments:
In `@src/components/Dashboard.tsx`:
- Around line 27-30: The pie chart should handle the empty state when both
totalIssues and totalPrs are 0: compute a hasData flag (e.g., const hasData =
totalIssues + totalPrs > 0) and conditionally render either the pie chart using
pieData or a simple fallback UI/message like "No data available" inside the
Dashboard component (where pieData, totalIssues and totalPrs are defined) so the
chart area shows a clear empty state instead of an empty pie.
- Line 32: The hard-coded COLORS array in Dashboard (const COLORS) should be
replaced with theme-aware colors so the chart adapts to the app palette; inside
the Dashboard component use the app theme (e.g., via useTheme() or the project’s
theme hook) and derive COLORS from theme.palette (for example primary/main and
secondary/main or suitable contrast/variant keys) and update any consumers of
COLORS (chart props or components that reference const COLORS) to use the new
theme-derived array.
- Around line 17-22: The DashboardProps uses unsafe any types for data and
theme; define proper interfaces (e.g., DataItem or IssuePrItem and
DashboardTheme) that reflect the actual shapes used by the component (for
DataItem include fields like id, type ('issue'|'pr'), title, createdAt, author,
state, url and any metadata the component accesses; for DashboardTheme include
colors, spacing, and any theme properties read by the component) and replace
data: any[] with data: DataItem[] and theme: any with theme: DashboardTheme in
the DashboardProps (and update the Dashboard component signature and any usages
to import/consume these interfaces).

In `@src/hooks/useGitHubData.ts`:
- Around line 12-19: Define a strict interface (e.g., GitHubFetchFilters) near
the top of the file and replace the loose filters: any in the fetchPaginated
function signature with filters: GitHubFetchFilters; the interface should
include the expected keys (for example optional startDate?: string, endDate?:
string, repoNames?: string[], includeForks?: boolean, etc.) so typos are caught
at compile time, and update the other occurrences that currently use filters:
any (the ones referenced around the other function signatures/calls) to use
GitHubFetchFilters as well.

In `@src/pages/Tracker/Tracker.tsx`:
- Around line 131-171: The Dashboard is being passed a recomputed tab selection
(data={tab === 0 ? issues : prs}) even though currentFilteredData already holds
that value; update the Dashboard invocation to pass data={currentFilteredData}
instead (referencing currentFilteredData and the Dashboard component) so the
selection logic is centralized and stays consistent if the rule changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b38d8a7c-dcbf-42d0-9f20-ef0cd431796c

📥 Commits

Reviewing files that changed from the base of the PR and between 56e17a3 and 6de67e9.

📒 Files selected for processing (4)
  • package.json
  • src/components/Dashboard.tsx
  • src/hooks/useGitHubData.ts
  • src/pages/Tracker/Tracker.tsx

Comment thread package.json Outdated
"@primer/octicons-react": "^19.15.5",
"@vitejs/plugin-react": "^4.3.3",
"axios": "^1.7.7",
"express": "^5.2.1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoff

Verify that express and mongoose are actually required.

These are backend/server-side packages being added to a frontend React application. Based on the PR context, this appears to be a Vite-based frontend-only app with no backend server implementation shown. Adding server-side dependencies to a frontend project can:

  • Bloat node_modules unnecessarily
  • Create confusion about the application architecture
  • Potentially cause build issues if accidentally imported in client code

If server-side filtering is implemented purely through the GitHub Search API (as the PR summary suggests), these dependencies may not be needed.

Run the following script to check if these packages are actually imported anywhere in the codebase:

#!/bin/bash
# Description: Search for imports of express and mongoose in the source code

echo "=== Searching for 'express' imports ==="
rg -n --type=ts --type=tsx --type=js --type=jsx "from ['\"]express['\"]|require\(['\"]express['\"]\)" src/

echo -e "\n=== Searching for 'mongoose' imports ==="
rg -n --type=ts --type=tsx --type=js --type=jsx "from ['\"]mongoose['\"]|require\(['\"]mongoose['\"]\)" src/

echo -e "\n=== Checking for any server/backend files ==="
fd -e js -e ts "server|backend|api" --type f

Also applies to: 25-25

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 22, package.json includes server-side dependencies
"express" and "mongoose" that likely aren't used in this frontend React/Vite
project; search the repository for imports/usages of express and mongoose (look
for "express" and "mongoose" strings and any server-related folders or files)
and if there are no imports or backend files (no API/server code), remove these
dependencies from package.json and package-lock or yarn.lock and update install
scripts (run npm/yarn install after removal); if they are required by a new
backend module, instead move that module into a dedicated backend package or
workspace and add express/mongoose only to that server package to avoid bloating
the frontend.

Comment thread src/components/Dashboard.tsx
Comment thread src/hooks/useGitHubData.ts Outdated
Comment thread src/pages/Tracker/Tracker.tsx
Comment thread src/pages/Tracker/Tracker.tsx Outdated
@mehul-m-prajapati
Copy link
Copy Markdown
Collaborator

@ishwari418 : good work, pls resolve conflicts

@ishwari418
Copy link
Copy Markdown
Author

@ishwari418 : good work, pls resolve conflicts

Thanks for the review, I will soon fix the conflicts....

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (1)
src/hooks/useGitHubData.ts (1)

94-128: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix malformed try/catch block with unreachable state updates.

Lines 94–127 contain two consecutive catch blocks (invalid syntax) and attempts to reference issueRes/prRes inside the catch handler where they are out of scope. Lines 103–107 incorrectly call state setters with variables that don't exist in the catch scope and would cause a ReferenceError at runtime. Consolidate into a single catch block with proper error handling as suggested.

Suggested fix
-      } catch (err: unknown) {
-        if (requestId === lastRequestId.current) {
-          const error = err as { status?: number; message?: string };
-          if (error.status === 403) {
-            setError('GitHub API rate limit exceeded. Please wait or use a token.');
-            setRateLimited(true);
-          } else {
-            setError(error.message || 'Failed to fetch data');
-          }
-        setIssues(issueRes.items);
-        setPrs(prRes.items);
-        setTotalIssues(issueRes.total);
-        setTotalPrs(prRes.total);
-        setRateLimited(false);
-      } catch (err: any) {
-        const errorMessage = err.message?.toLowerCase() || "";
-        if (err.status === 403) {
-          setError('GitHub API rate limit exceeded. Please provide a PAT to continue.');
-          setRateLimited(true); 
-        } else if (errorMessage.includes("do not exist")){
-          setError('User not found. Please check the spelling of the GitHub username.');
-        } else if (err.status === 401 || errorMessage.includes("permission")){
-          setError('Private repository detected. Please input PAT.');
-        }else if(err.status===404){
-          setError('Resource not found.');
-        }
-        else if (errorMessage.includes("validation failed")) {
-          setError('Invalid GitHub username or insufficient permissions.');
-        }
-        else {
-          setError(
-            'Unable to fetch GitHub data. Please verify the username, token, or network connection.'
-          );
-        }
+      } catch (err: unknown) {
+        if (requestId !== lastRequestId.current) return;
+        const e = err as { status?: number; message?: string };
+        const errorMessage = e.message?.toLowerCase() || '';
+        if (e.status === 403) {
+          setError('GitHub API rate limit exceeded. Please provide a PAT to continue.');
+          setRateLimited(true);
+        } else if (errorMessage.includes('do not exist')) {
+          setError('User not found. Please check the spelling of the GitHub username.');
+        } else if (e.status === 401 || errorMessage.includes('permission')) {
+          setError('Private repository detected. Please input PAT.');
+        } else if (e.status === 404) {
+          setError('Resource not found.');
+        } else if (errorMessage.includes('validation failed')) {
+          setError('Invalid GitHub username or insufficient permissions.');
+        } else {
+          setError('Unable to fetch GitHub data. Please verify the username, token, or network connection.');
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/useGitHubData.ts` around lines 94 - 128, The try/catch is
malformed: there are two consecutive catch blocks and the catch scope
incorrectly references issueRes/prRes and updates state (setIssues, setPrs,
setTotalIssues, setTotalPrs) that are only defined in the try. Fix by merging
into a single catch that first checks requestId === lastRequestId.current, then
maps errors (inspect err.status and err.message/errorMessage) to the appropriate
setError and setRateLimited calls, and remove any references to issueRes or
prRes from the catch; leave state updates that use issueRes/prRes inside the try
where they belong and keep the finally block intact in useGitHubData.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Around line 57-64: Fix the invalid JSON and duplicate dependency entries in
devDependencies: add the missing comma after the "vite": "^5.4.10" entry to make
the object parseable, remove the earlier duplicate entries for "jasmine",
"passport", "passport-local", "supertest", and "vite" so each package appears
only once, and ensure the retained versions are the intended ones (e.g., keep
"jasmine": "^5.13.0" if that's the desired version). Confirm the final
package.json parses as valid JSON after these edits.

In `@src/hooks/useGitHubData.ts`:
- Around line 72-75: The fetchData callback in useGitHubData references the
rateLimited state but the useCallback dependency array only includes getOctokit,
causing a stale closure; update the useCallback dependencies for fetchData (the
callback defined around line 72) to include rateLimited in addition to
getOctokit so the callback sees changes to rateLimited and stops making API
calls when setRateLimited(true).
- Line 72: The hook's rateLimited flag is never cleared on success, so update
the success path in useGitHubData (the block that handles successful octokit
responses — currently around the code handling the response at the success path
after checking octokit/username) to call setRateLimited(false) so future
requests are allowed; locate the success-handling logic that currently updates
state with the fetched data (the same place where user/repo data is set) and add
setRateLimited(false) there.

In `@src/pages/ContributorProfile/ContributorProfile.tsx`:
- Around line 11-15: The Profile type in ContributorProfile.tsx is too strict:
change the bio property from string to string | null to match GitHub's /users
nullable bio; locate the type alias named Profile (avatar_url, login, bio) and
update the bio declaration to accept null so downstream code that consumes
Profile matches the API shape.

In `@src/pages/Signup/Signup.tsx`:
- Around line 41-52: The catch block in Signup.tsx is malformed (there are two
catch-like blocks/statements and a stray axios.post inside the catch), causing a
compile error; fix by consolidating into a single try/catch: remove the
duplicate/stray axios.post call inside the catch, add an error parameter to the
catch (e.g., catch (err)), and handle/log the error and setMessage appropriately
(use setMessage with an error message and optionally log err) while keeping the
original axios.post call inside the try that uses backendUrl and formData and
the navigate logic after success.

---

Outside diff comments:
In `@src/hooks/useGitHubData.ts`:
- Around line 94-128: The try/catch is malformed: there are two consecutive
catch blocks and the catch scope incorrectly references issueRes/prRes and
updates state (setIssues, setPrs, setTotalIssues, setTotalPrs) that are only
defined in the try. Fix by merging into a single catch that first checks
requestId === lastRequestId.current, then maps errors (inspect err.status and
err.message/errorMessage) to the appropriate setError and setRateLimited calls,
and remove any references to issueRes or prRes from the catch; leave state
updates that use issueRes/prRes inside the try where they belong and keep the
finally block intact in useGitHubData.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3234814f-ed65-4e52-a8e1-b305f2b74792

📥 Commits

Reviewing files that changed from the base of the PR and between 6de67e9 and 0c76301.

📒 Files selected for processing (10)
  • package.json
  • src/components/Dashboard.tsx
  • src/hooks/useDebounce.ts
  • src/hooks/useGitHubAuth.ts
  • src/hooks/useGitHubData.ts
  • src/pages/ContributorProfile/ContributorProfile.tsx
  • src/pages/Contributors/Contributors.tsx
  • src/pages/Login/Login.tsx
  • src/pages/Signup/Signup.tsx
  • src/pages/Tracker/Tracker.tsx
💤 Files with no reviewable changes (1)
  • src/hooks/useGitHubAuth.ts
✅ Files skipped from review due to trivial changes (1)
  • src/pages/Contributors/Contributors.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/Tracker/Tracker.tsx

Comment thread package.json
Comment on lines +57 to 64
"jasmine": "^5.9.0",
"mongoose": "^9.6.2",
"passport": "^0.7.0",
"passport-local": "^1.0.0",
"supertest": "^7.1.4",
"typescript-eslint": "^8.59.3",
"vite": "^5.4.10"
"jasmine": "^5.13.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

head -75 package.json | tail -30

Repository: GitMetricsLab/github_tracker

Length of output: 943


Fix invalid JSON and duplicate dependency keys in devDependencies.

Line 62 is missing a trailing comma after "vite": "^5.4.10", making package.json unparseable. Additionally, jasmine, passport, passport-local, supertest, and vite appear twice with conflicting or redundant versions—remove the first occurrences and keep only the second set.

Suggested cleanup
-    "jasmine": "^5.9.0",
     "mongoose": "^9.6.2",
-    "passport": "^0.7.0",
-    "passport-local": "^1.0.0",
-    "supertest": "^7.1.4",
     "typescript-eslint": "^8.59.3",
-    "vite": "^5.4.10"
+    "vite": "^5.4.10",
     "jasmine": "^5.13.0",
     "jasmine-spec-reporter": "^7.0.0",
     "jsdom": "^29.1.1",
-    "passport": "^0.7.0",
-    "passport-local": "^1.0.0",
     "supertest": "^7.2.2",
-    "vite": "^5.4.10",
     "vitest": "^4.1.6"
🧰 Tools
🪛 Biome (2.4.15)

[error] 64-64: expected , but instead found "jasmine"

(parse)


[error] 57-57: The key jasmine was already declared.

(lint/suspicious/noDuplicateObjectKeys)


[error] 59-59: The key passport was already declared.

(lint/suspicious/noDuplicateObjectKeys)


[error] 60-60: The key passport-local was already declared.

(lint/suspicious/noDuplicateObjectKeys)


[error] 61-61: The key supertest was already declared.

(lint/suspicious/noDuplicateObjectKeys)


[error] 63-63: The key vite was already declared.

(lint/suspicious/noDuplicateObjectKeys)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 57 - 64, Fix the invalid JSON and duplicate
dependency entries in devDependencies: add the missing comma after the "vite":
"^5.4.10" entry to make the object parseable, remove the earlier duplicate
entries for "jasmine", "passport", "passport-local", "supertest", and "vite" so
each package appears only once, and ensure the retained versions are the
intended ones (e.g., keep "jasmine": "^5.13.0" if that's the desired version).
Confirm the final package.json parses as valid JSON after these edits.

Comment on lines +72 to 75
if (!octokit || !username || rateLimited) return;

if (!octokit || !username) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

cat -n src/hooks/useGitHubData.ts | head -200

Repository: GitMetricsLab/github_tracker

Length of output: 5737


Add rateLimited to the useCallback dependency array.

fetchData references rateLimited in the guard condition at line 72, but the useCallback dependency array at line 134 only includes [getOctokit]. This creates a stale closure where the callback retains the initial false value of rateLimited. When setRateLimited(true) is called during rate limiting (lines 99, 112), the callback doesn't recognize the state change and continues attempting API calls despite rate limiting.

Add rateLimited to the dependency array:

Suggested fix
   const fetchData = useCallback(
     async (...) => {
       ...
     },
-    [getOctokit]
+    [getOctokit, rateLimited]
   );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!octokit || !username || rateLimited) return;
if (!octokit || !username) return;
const fetchData = useCallback(
async (...) => {
...
},
[getOctokit, rateLimited]
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/useGitHubData.ts` around lines 72 - 75, The fetchData callback in
useGitHubData references the rateLimited state but the useCallback dependency
array only includes getOctokit, causing a stale closure; update the useCallback
dependencies for fetchData (the callback defined around line 72) to include
rateLimited in addition to getOctokit so the callback sees changes to
rateLimited and stops making API calls when setRateLimited(true).

Comment thread src/hooks/useGitHubData.ts
Comment on lines +11 to +15
type Profile = {
avatar_url: string;
login: string;
bio: string;
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In GitHub REST API users response schema, is bio nullable (string | null)?

💡 Result:

Yes, in the GitHub REST API users response schema, the bio field is defined as nullable (string | null) [1][2][3][4]. Official documentation explicitly lists bio as required and of type string or null [1][4].

Citations:


Change Profile.bio to string | null to match GitHub API contract.

The GitHub API's /users endpoint returns bio as nullable. The current type bio: string is too strict for the API response shape.

Proposed fix
 type Profile = {
   avatar_url: string;
   login: string;
-  bio: string;
+  bio: string | null;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type Profile = {
avatar_url: string;
login: string;
bio: string;
};
type Profile = {
avatar_url: string;
login: string;
bio: string | null;
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/ContributorProfile/ContributorProfile.tsx` around lines 11 - 15,
The Profile type in ContributorProfile.tsx is too strict: change the bio
property from string to string | null to match GitHub's /users nullable bio;
locate the type alias named Profile (avatar_url, login, bio) and update the bio
declaration to accept null so downstream code that consumes Profile matches the
API shape.

Comment thread src/pages/Signup/Signup.tsx Outdated
Removed redundant signup error handling and response logic.
Removed setting state for issues and PRs in the error handling block.
@mehul-m-prajapati mehul-m-prajapati merged commit f1bca09 into GitMetricsLab:main May 20, 2026
6 checks passed
@github-actions
Copy link
Copy Markdown

🎉🎉 Thank you for your contribution! Your PR #255 has been merged! 🎉🎉

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Add Analytics Dashboard with Contribution Charts

2 participants