Skip to content

feat(tracker): enhance UI improved header, filters, and dark-mode f…#335

Open
swati-204 wants to merge 1 commit into
GitMetricsLab:mainfrom
swati-204:feat/tracker-ui
Open

feat(tracker): enhance UI improved header, filters, and dark-mode f…#335
swati-204 wants to merge 1 commit into
GitMetricsLab:mainfrom
swati-204:feat/tracker-ui

Conversation

@swati-204
Copy link
Copy Markdown

@swati-204 swati-204 commented May 19, 2026

Related Issue

  • Closes: #<256>

Description

Polished the Tracker UI: hero/header with gradient, descriptive copy, and an overview panel showing loaded vs visible items.
Added a visibility progress bar and active-filter summary to help users understand filter impact.
Improved authentication card: helper link to GitHub PAT docs, rounded inputs, clearer fetch button state.
Refined filter bar and empty states clearer messaging and a prominent Clear action.
Table improvements: smoother hover affordance, row click opens item in GitHub, rounded repo chips, and clearer state badges.
Resolved upstream merge conflicts and fixed duplicate/garbled imports.
All functional logic (hooks, data fetching) remains unchanged; only src/pages/Tracker/Tracker.tsx was modified.

How Has This Been Tested?

Started dev server (npm run dev) and confirmed Vite serves the app without parse/build errors.

Visually inspected the Tracker page in both light and dark themes to confirm contrast and layout.

Exercised filters (search, repo, date range), tab switching (Issues / Pull Requests), and token helper link.

Verified no TypeScript/JSX diagnostics for the touched file.

Screenshots (if applicable)

image image image

Type of Change

  • Bug fix
  • New feature
  • Code style update
  • Breaking change
  • Documentation update

Summary by CodeRabbit

  • New Features
    • Enhanced Tracker page with advanced filtering options including issue/PR state, title search, and date range selection.
    • Improved table display with clickable rows (opens in new tab), formatted dates with tooltips, and status icons.
    • Redesigned layout with better visual hierarchy using Material UI components including loading indicators, alerts, and skeletons.

Review Change Stack

Copilot AI review requested due to automatic review settings May 19, 2026 15:50
@netlify
Copy link
Copy Markdown

netlify Bot commented May 19, 2026

Deploy Preview for github-spy ready!

Name Link
🔨 Latest commit 9a0970f
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6a0c86d75624ca0008049bba
😎 Deploy Preview https://deploy-preview-335--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 19, 2026

📝 Walkthrough

Walkthrough

The Tracker page is redesigned with expanded Material UI support and modernized filtering. Filter state tracks issue/PR status, title search, repository substring, and date ranges. A new StatCard component displays stats, and the layout is restructured into a hero section, authentication card, alerts, tabs, filter controls, and an enhanced table with status indicators, tooltips, and interactive row navigation.

Changes

Tracker Page UI Redesign

Layer / File(s) Summary
Styling and Component Infrastructure
src/pages/Tracker/Tracker.tsx
React import adds useMemo for memoized computations. Material UI imports expand significantly to include progress, alerts, tabs, form controls, typography, chips, tooltips, icons, skeletons, and layout helpers. A reusable StatCard component is introduced to display stat information with icons and labels. Theme-based dark-mode styling (isDark) is computed to support the new themed presentation.
Filter State and UI Layout Redesign
src/pages/Tracker/Tracker.tsx
Filter state is expanded to track issue state, PR state, title search, repository substring, date ranges, and hasFetched flag for conditional messaging. A shared filterData function applies filtering with memoized computed stats for open/closed/merged counts. Layout is restructured into a themed gradient hero section with stat cards, an authentication card with inline loading spinner, an errors alert area, tabs and state dropdown controls, a filter bar with conditional Clear button, and a main content area that conditionally renders loading skeletons, "No data yet" prompt, "No results match filters" message, or the results table. Table rendering is enhanced with status icons and state chips, repository values displayed as outlined chips, created dates formatted with locale helper and wrapped in tooltips, and row-click navigation via window.open. Pagination controls are integrated within the redesigned table container.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • GitMetricsLab/github_tracker#253: Feature request for dashboard/summary cards and charts on the Tracker page directly overlaps with the StatCard introduction and computed activity stats added in this PR.

Possibly related PRs

  • GitMetricsLab/github_tracker#242: Both PRs modify the Tracker page's loading/empty-state rendering logic, replacing the prior spinner with skeleton loaders and updating "no data/no results" UI messaging.
  • GitMetricsLab/github_tracker#238: Both PRs modify the Tracker page's authentication and error handling flow, with this PR redesigning the auth card and errors area while the related PR adjusts PAT handling and corresponding error messages.

Suggested labels

gssoc25, level2, quality:clean

Poem

🐰 Cards arranged in glowing rows,
Filters flow where data goes,
Chips and tooltips brightly shine,
Memoized stats in a design so fine,
A rabbit hops through UI delight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title references key changes (header, filters, dark-mode) but is truncated and incomplete, making it unclear what the primary focus is. Complete the title to clearly convey the main change, e.g., 'feat(tracker): enhance UI with improved header, filters, and dark-mode support' or focus on the most important aspect.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description provides comprehensive details about all changes, includes testing methodology, screenshots, and properly marks the PR type as a new feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 @swati-204 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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR polishes the Tracker page UI in src/pages/Tracker/Tracker.tsx, introducing a new hero/header layout, improved auth card, richer filter bar/empty states, and enhanced table presentation (chips, badges, hover affordances).

Changes:

  • Added a new header/overview panel with visibility progress, plus stat cards for open/closed/merged counts.
  • Refined authentication and filter UI (helper link, clear actions, loading affordances, and empty states).
  • Updated the table UI to be row-clickable (opens GitHub), with improved styling for title/repo/state/created cells.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +126 to 133
if (username) fetchData(username, page + 1, ROWS_PER_PAGE);
}, [tab, page]);

const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
setPage(0);
setHasFetched(true);
fetchData(username, 1, ROWS_PER_PAGE);
Comment on lines +146 to +147
!!searchTitle || !!selectedRepo || !!startDate || !!endDate ||
issueFilter !== "all" || prFilter !== "all";
Comment on lines +183 to +188
const visibleStats = useMemo(() => {
const open = currentFilteredData.filter((i) => i.state === "open").length;
const merged = currentFilteredData.filter((i) => !!i.pull_request?.merged_at).length;
const closed = currentFilteredData.filter((i) => i.state === "closed" && !i.pull_request?.merged_at).length;
return { open, merged, closed };
}, [currentFilteredData]);
}, [tab, issueFilter, prFilter, searchTitle, selectedRepo, startDate, endDate]);

const activeFilterCount = activeFilterSummary.length;
const visibleShare = totalCount ? Math.round((currentFilteredData.length / totalCount) * 100) : 0;

const activeFilterCount = activeFilterSummary.length;
const visibleShare = totalCount ? Math.round((currentFilteredData.length / totalCount) * 100) : 0;
const progressValue = Math.max(8, visibleShare || 0);
Comment on lines 400 to +407
<TextField
label="Personal Access Token"
value={token}
onChange={(e) => setToken(e.target.value)}
type="password"
sx={{ flex: 1, minWidth: 150 }}
// Helper link to guide users on generating a GitHub Personal Access Token
required
size="small"
sx={{ flex: 2, minWidth: 200, "& .MuiOutlinedInput-root": { borderRadius: "12px" } }}
sx={{ color: theme.palette.primary.main }}
href={item.html_url}
target="_blank"
rel="noopener noreferrer"
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: 4

🤖 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 `@src/pages/Tracker/Tracker.tsx`:
- Around line 459-463: The empty-filter "No results match your filters." message
is shown even after a fetch/auth error; update the empty-state rendering logic
to suppress that message when authError or dataError exist. Locate the
conditional that currently checks hasFetched and emptiness of the result arrays
(e.g., hasFetched && filteredRecords.length === 0 or similar) and add a guard so
it only renders when !authError && !dataError. Make the same change for the
second occurrence referenced (the block around the 634-657 range) so both
empty-state branches require no errors before displaying the "No results..."
message.
- Around line 200-201: The progress bar's hard minimum forces a non-zero display
even when visibleShare is 0; change the logic so progressValue uses the minimum
only when visibleShare > 0. Keep visibleShare as computed (from
currentFilteredData.length and totalCount), then compute progressValue with a
conditional: if visibleShare > 0 use Math.max(8, visibleShare) otherwise 0;
update the variable progressValue (referenced in the Tracker component)
accordingly.
- Around line 701-713: The row-level onClick (which calls
window.open(item.html_url, ...)) is being triggered when the nested Link is
clicked; update the Link component (and any clickable children inside the title
cell) to stop event propagation so the row handler doesn't also run —
specifically add an onClick handler on the Link (and any inner interactive
element) that calls event.stopPropagation() (you may optionally call
event.preventDefault() only if you want to suppress Link's default navigation
and handle it manually); locate the Link in the title cell near
getStatusIcon(item) and add the stopPropagation logic there.
- Around line 167-168: The current date filtering in Tracker.tsx uses new
Date(startDate)/new Date(endDate) which treats endDate as midnight and excludes
items later that day; update the end-date comparison used by the filtered array
(the lines that currently filter on new Date(i.created_at) <= new Date(endDate))
to make the end day inclusive by computing an endOfDay for endDate (e.g., set
hours to 23:59:59.999 or advance by one day and compare with <) and use that
endOfDay in the filtered.filter call so items created anytime on the selected
"To" date are included.
🪄 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: eeae03c6-88c4-4753-9916-9d80e44abe1d

📥 Commits

Reviewing files that changed from the base of the PR and between 8d17610 and 9a0970f.

📒 Files selected for processing (1)
  • src/pages/Tracker/Tracker.tsx

Comment on lines +167 to +168
if (startDate) filtered = filtered.filter((i) => new Date(i.created_at) >= new Date(startDate));
if (endDate) filtered = filtered.filter((i) => new Date(i.created_at) <= new Date(endDate));
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

Make the date range inclusive of the selected end day.

type="date" gives you a day value, but new Date(endDate) compares against midnight at the start of that day. Items created later on the selected "To" date will be excluded unexpectedly.

Suggested fix
-    if (startDate) filtered = filtered.filter((i) => new Date(i.created_at) >= new Date(startDate));
-    if (endDate) filtered = filtered.filter((i) => new Date(i.created_at) <= new Date(endDate));
+    if (startDate) filtered = filtered.filter((i) => i.created_at.slice(0, 10) >= startDate);
+    if (endDate) filtered = filtered.filter((i) => i.created_at.slice(0, 10) <= endDate);
📝 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 (startDate) filtered = filtered.filter((i) => new Date(i.created_at) >= new Date(startDate));
if (endDate) filtered = filtered.filter((i) => new Date(i.created_at) <= new Date(endDate));
if (startDate) filtered = filtered.filter((i) => i.created_at.slice(0, 10) >= startDate);
if (endDate) filtered = filtered.filter((i) => i.created_at.slice(0, 10) <= endDate);
🤖 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 167 - 168, The current date
filtering in Tracker.tsx uses new Date(startDate)/new Date(endDate) which treats
endDate as midnight and excludes items later that day; update the end-date
comparison used by the filtered array (the lines that currently filter on new
Date(i.created_at) <= new Date(endDate)) to make the end day inclusive by
computing an endOfDay for endDate (e.g., set hours to 23:59:59.999 or advance by
one day and compare with <) and use that endOfDay in the filtered.filter call so
items created anytime on the selected "To" date are included.

Comment on lines +200 to +201
const visibleShare = totalCount ? Math.round((currentFilteredData.length / totalCount) * 100) : 0;
const progressValue = Math.max(8, visibleShare || 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 | 🟡 Minor | ⚡ Quick win

Keep the visibility bar at 0 when nothing is visible.

The hard floor of 8 means the UI can say 0% while the progress bar still shows progress. Only apply a minimum when visibleShare > 0.

Suggested fix
-  const progressValue = Math.max(8, visibleShare || 0);
+  const progressValue = visibleShare > 0 ? Math.max(8, visibleShare) : 0;
📝 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
const visibleShare = totalCount ? Math.round((currentFilteredData.length / totalCount) * 100) : 0;
const progressValue = Math.max(8, visibleShare || 0);
const visibleShare = totalCount ? Math.round((currentFilteredData.length / totalCount) * 100) : 0;
const progressValue = visibleShare > 0 ? Math.max(8, visibleShare) : 0;
🤖 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 200 - 201, The progress bar's
hard minimum forces a non-zero display even when visibleShare is 0; change the
logic so progressValue uses the minimum only when visibleShare > 0. Keep
visibleShare as computed (from currentFilteredData.length and totalCount), then
compute progressValue with a conditional: if visibleShare > 0 use Math.max(8,
visibleShare) otherwise 0; update the variable progressValue (referenced in the
Tracker component) accordingly.

Comment on lines +459 to +463
{(authError || dataError) && (
<Alert severity="error" sx={{ mb: 2.5, borderRadius: "10px" }}>
{authError || dataError}
</Alert>
)}
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

Don't show the filter-empty state after a fetch error.

After a failed auth/API request, the error alert renders correctly, but this branch still falls through to "No results match your filters." because hasFetched is already true and the arrays are empty. That message is misleading when nothing was loaded.

Also applies to: 634-657

🤖 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 459 - 463, The empty-filter "No
results match your filters." message is shown even after a fetch/auth error;
update the empty-state rendering logic to suppress that message when authError
or dataError exist. Locate the conditional that currently checks hasFetched and
emptiness of the result arrays (e.g., hasFetched && filteredRecords.length === 0
or similar) and add a guard so it only renders when !authError && !dataError.
Make the same change for the second occurrence referenced (the block around the
634-657 range) so both empty-state branches require no errors before displaying
the "No results..." message.

Comment on lines +701 to +713
onClick={() => window.open(item.html_url, "_blank", "noopener,noreferrer")}
>
{/* Title */}
<TableCell sx={{ ...cellSx, maxWidth: 420 }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<Box sx={{ flexShrink: 0, display: "flex", alignItems: "center", color: "text.secondary" }}>
{getStatusIcon(item)}
</Box>
<Link
href={item.html_url}
target="_blank"
rel="noopener noreferrer"
underline="hover"
sx={{ color: theme.palette.primary.main }}
href={item.html_url}
target="_blank"
rel="noopener noreferrer"
underline="none"
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

Stop the title link from triggering the row click handler too.

Clicking the title currently fires both the nested <Link> navigation and the row-level window.open, which can open the same GitHub item twice.

Suggested fix
                         <Link
                           href={item.html_url}
                           target="_blank"
                           rel="noopener noreferrer"
+                          onClick={(e) => e.stopPropagation()}
                           underline="none"
                           sx={{
📝 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
onClick={() => window.open(item.html_url, "_blank", "noopener,noreferrer")}
>
{/* Title */}
<TableCell sx={{ ...cellSx, maxWidth: 420 }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<Box sx={{ flexShrink: 0, display: "flex", alignItems: "center", color: "text.secondary" }}>
{getStatusIcon(item)}
</Box>
<Link
href={item.html_url}
target="_blank"
rel="noopener noreferrer"
underline="hover"
sx={{ color: theme.palette.primary.main }}
href={item.html_url}
target="_blank"
rel="noopener noreferrer"
underline="none"
onClick={() => window.open(item.html_url, "_blank", "noopener,noreferrer")}
>
{/* Title */}
<TableCell sx={{ ...cellSx, maxWidth: 420 }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<Box sx={{ flexShrink: 0, display: "flex", alignItems: "center", color: "text.secondary" }}>
{getStatusIcon(item)}
</Box>
<Link
href={item.html_url}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
underline="none"
🤖 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 701 - 713, The row-level onClick
(which calls window.open(item.html_url, ...)) is being triggered when the nested
Link is clicked; update the Link component (and any clickable children inside
the title cell) to stop event propagation so the row handler doesn't also run —
specifically add an onClick handler on the Link (and any inner interactive
element) that calls event.stopPropagation() (you may optionally call
event.preventDefault() only if you want to suppress Link's default navigation
and handle it manually); locate the Link in the title cell near
getStatusIcon(item) and add the stopPropagation logic there.

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.

2 participants