Skip to content

fix(ui): resolve count inconsistencies between sidebar and overview headings#252

Merged
mpiton merged 1 commit intomainfrom
fix/244-count-inconsistencies
Apr 12, 2026
Merged

fix(ui): resolve count inconsistencies between sidebar and overview headings#252
mpiton merged 1 commit intomainfrom
fix/244-count-inconsistencies

Conversation

@mpiton
Copy link
Copy Markdown
Owner

@mpiton mpiton commented Apr 12, 2026

Summary

Fixes #244 — count inconsistencies between sidebar badges, stats bar, and Overview section headings.

  • Sub-components (ReviewQueue, MyPRs, Issues, ActivityFeed) rendered their own SectionHead with counts from sliced preview arrays when embedded in Overview, conflicting with Overview's correct badges and the sidebar stats
  • PRs in Overview were sliced from all states but the badge counted only open+draft, causing mismatches
  • No "View all" drill-down existed for Reviews and My PRs sections

Changes

  • Add hideHeader prop to ReviewQueue, MyPRs, Issues, and ActivityFeed — suppresses SectionHead when embedded in Overview (which has its own card headers with correct counts)
  • Fix PR filtering in Overview: filter to open+draft before slicing (aligning with the Issues pattern)
  • Add "View all N reviews" and "View all N PRs" buttons in Overview when items exceed the 5-item preview limit
  • Add tests: hideHeader behavior for all 4 components, View All button visibility, mixed-state PR edge case

Test plan

  • npx tsc --noEmit — passes
  • npm run lint — 0 warnings, 0 errors
  • npx vitest run — 667 tests pass, 0 failures
  • Adversarial code review: R1 logic bug found and fixed (filter-then-slice for PRs)

Summary by cubic

Fixes inconsistent counts between the sidebar badges and Overview cards by suppressing duplicate headers and aligning PR filtering. Adds “View all” actions for Reviews and My PRs when items exceed the preview limit.

  • Bug Fixes

    • Added hideHeader to ReviewQueue, MyPRs, Issues, and ActivityFeed; Overview now hides sub-headers to avoid mismatched counts.
    • Filtered My PRs to open + draft before slicing so Overview counts match the sidebar and badges.
  • New Features

    • Added “View all N reviews” and “View all N PRs” buttons in Overview when more than 5 items are available.

Written for commit 39bc3a7. Summary will update on new commits.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added optional header visibility control across dashboard components for flexible layout customization.
    • Added "View all" buttons in the overview to navigate to full lists when reviews or pull requests exceed display limits.
    • Overview now displays only open and draft pull requests, excluding merged ones.
  • Tests

    • Extended test coverage for conditional header visibility and view-all button behavior across components.

…eadings

Sub-components (ReviewQueue, MyPRs, Issues, ActivityFeed) rendered their
own SectionHead with counts from sliced preview arrays when embedded in
Overview, conflicting with Overview's own correct badges and the sidebar.

- Add hideHeader prop to all 4 section components
- Overview passes hideHeader to suppress duplicate headers
- Filter PRs to open+draft before slicing (matching Issues pattern)
- Add "View all" drill-down buttons for Reviews and My PRs sections
- Add tests for hideHeader behavior and View All edge cases

Closes #244
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

Multiple dashboard components (ActivityFeed, Issues, MyPRs, ReviewQueue) now support an optional hideHeader prop to conditionally hide section headers. Overview component is updated to filter pull requests by state ("open" or "draft"), add "View all" buttons for reviews and PRs when counts exceed limits, and pass the hideHeader prop to child components.

Changes

Cohort / File(s) Summary
Dashboard Components – hideHeader Support
src/components/ActivityFeed/ActivityFeed.tsx, src/components/Issues/Issues.tsx, src/components/MyPRs/MyPRs.tsx, src/components/ReviewQueue/ReviewQueue.tsx
Each component now accepts an optional hideHeader?: boolean prop (defaulting to false). The SectionHead rendering is now conditional: omitted when hideHeader is true, otherwise rendered as before with title and count.
Dashboard Components – hideHeader Tests
src/components/ActivityFeed/ActivityFeed.test.tsx, src/components/Issues/Issues.test.tsx, src/components/MyPRs/MyPRs.test.tsx, src/components/ReviewQueue/ReviewQueue.test.tsx
Added test cases verifying that section headers ("Activity", "Issues", "My PRs", "Reviews") do not render when the hideHeader prop is set to true.
Overview Component Updates
src/components/Overview/Overview.tsx
Updated PR selection logic to filter myPullRequests to only "open" or "draft" states before slicing to MAX_PRS. Added conditional "View all …" buttons for reviews (when reviewRequests.length > MAX_REVIEWS) and PRs (when openPrCount > MAX_PRS) that switch dashboard view. Passes hideHeader prop to child components (ReviewQueue, MyPRs, Issues, ActivityFeed).
Overview Component Tests
src/components/Overview/Overview.test.tsx
Added test coverage for "View all" button visibility in reviews and PRs sections based on item count thresholds. Added tests validating that only open PRs are included in the overview preview and count badge.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Headers tuck away when called so sweet,
View-all buttons make the dashboard complete,
Open PRs filter through with grace,
Dashboard counts find their rightful place! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: fixing count inconsistencies between sidebar and overview headings, which is the core of this PR's changes.
Linked Issues check ✅ Passed All primary objectives from issue #244 are implemented: hideHeader props added to suppress headers when embedded in Overview, PR filtering fixed to show open+draft only, and View All buttons added with correct counts.
Out of Scope Changes check ✅ Passed All changes directly address issue #244's requirements. The test additions (58 lines in Overview.test.tsx) validate View All button behavior and open PR filtering, which are scoped fixes for the count consistency issue.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/244-count-inconsistencies

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

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
src/components/Overview/Overview.test.tsx (1)

318-336: Add a draft-PR assertion to fully lock the open+draft contract.

Line 318’s test validates merged exclusion, but it doesn’t explicitly assert that draft PRs are included in count/preview. Given the filter now includes both open and draft, add one draft PR to this case to prevent regressions.

💡 Suggested test extension
   it("should only show open PRs in overview and exclude merged from count", () => {
     const openPrs = Array.from({ length: 3 }, (_, i) => makePr(i + 10));
+    const draftPr = {
+      ...makePr(99),
+      pullRequest: { ...makePr(99).pullRequest, state: "draft" as const },
+    };
     const mergedPrs = Array.from({ length: 4 }, (_, i) => ({
       ...makePr(i + 20),
       pullRequest: { ...makePr(i + 20).pullRequest, state: "merged" as const },
     }));
-    setupMock(makeDashboard({ myPullRequests: [...openPrs, ...mergedPrs] }));
+    setupMock(makeDashboard({ myPullRequests: [...openPrs, draftPr, ...mergedPrs] }));
@@
-    // "View all" hidden because openPrCount (3) <= MAX_PRS (5)
+    // "View all" hidden because openPrCount (4: open + draft) <= MAX_PRS (5)
     expect(screen.queryByTestId("overview-prs-view-all")).not.toBeInTheDocument();
-    // Badge shows correct open count
-    expect(screen.getByText("3 open")).toBeInTheDocument();
+    // Badge shows correct open/draft count
+    expect(screen.getByText("4 open")).toBeInTheDocument();
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Overview/Overview.test.tsx` around lines 318 - 336, The test
"should only show open PRs in overview and exclude merged from count" (in
Overview.test.tsx) doesn't assert that draft PRs are treated like open, so add a
draft PR to the mock dashboard and assert it appears in the preview and in the
open count; update the setupMock call that builds makeDashboard({
myPullRequests: [...] }) to include one makePr(...) whose pullRequest.state is
"draft" (use the same pattern used for merged PRs), then assert the draft PR
title (e.g., "PR `#21`") is present with the other open previews, and adjust the
expected badge text to reflect the increased open+draft count (and confirm
overview-prs-view-all visibility logic against MAX_PRS remains correct).
src/components/Overview/Overview.tsx (1)

152-161: Consider extracting duplicated “View all” button markup.

Both blocks share near-identical structure/classes; extracting a tiny helper/component would reduce repetition and keep future style/behavior edits in one place.

Also applies to: 188-197

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Overview/Overview.tsx` around lines 152 - 161, Duplicate "View
all" button markup in Overview.tsx should be extracted into a small reusable
component or helper: create a ViewAllButton component (e.g., function
ViewAllButton({count, onClick, testId})) that renders the exact button markup
and uses FOCUS_RING for classes; replace both occurrences (the block rendering
when !showLoadingState && reviewRequests.length > MAX_REVIEWS and the similar
block at the other location) with <ViewAllButton count={reviewRequests.length}
onClick={() => useDashboardStore.getState().setView("reviews")}
testId="overview-reviews-view-all" /> so style/behavior edits are centralized
and no duplicate class strings remain in Overview.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/Overview/Overview.test.tsx`:
- Around line 318-336: The test "should only show open PRs in overview and
exclude merged from count" (in Overview.test.tsx) doesn't assert that draft PRs
are treated like open, so add a draft PR to the mock dashboard and assert it
appears in the preview and in the open count; update the setupMock call that
builds makeDashboard({ myPullRequests: [...] }) to include one makePr(...) whose
pullRequest.state is "draft" (use the same pattern used for merged PRs), then
assert the draft PR title (e.g., "PR `#21`") is present with the other open
previews, and adjust the expected badge text to reflect the increased open+draft
count (and confirm overview-prs-view-all visibility logic against MAX_PRS
remains correct).

In `@src/components/Overview/Overview.tsx`:
- Around line 152-161: Duplicate "View all" button markup in Overview.tsx should
be extracted into a small reusable component or helper: create a ViewAllButton
component (e.g., function ViewAllButton({count, onClick, testId})) that renders
the exact button markup and uses FOCUS_RING for classes; replace both
occurrences (the block rendering when !showLoadingState && reviewRequests.length
> MAX_REVIEWS and the similar block at the other location) with <ViewAllButton
count={reviewRequests.length} onClick={() =>
useDashboardStore.getState().setView("reviews")}
testId="overview-reviews-view-all" /> so style/behavior edits are centralized
and no duplicate class strings remain in Overview.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8ef24219-09a5-4d3b-8cdd-a90f57d1677e

📥 Commits

Reviewing files that changed from the base of the PR and between 8529f7c and 39bc3a7.

📒 Files selected for processing (10)
  • src/components/ActivityFeed/ActivityFeed.test.tsx
  • src/components/ActivityFeed/ActivityFeed.tsx
  • src/components/Issues/Issues.test.tsx
  • src/components/Issues/Issues.tsx
  • src/components/MyPRs/MyPRs.test.tsx
  • src/components/MyPRs/MyPRs.tsx
  • src/components/Overview/Overview.test.tsx
  • src/components/Overview/Overview.tsx
  • src/components/ReviewQueue/ReviewQueue.test.tsx
  • src/components/ReviewQueue/ReviewQueue.tsx

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 10 files

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 12, 2026

Greptile Summary

This PR fixes count inconsistencies in the Overview by adding a hideHeader prop to all four sub-components (ReviewQueue, MyPRs, Issues, ActivityFeed) so that embedded panels no longer render a duplicate SectionHead that conflicts with Overview's own card headers. It also corrects the PR filtering logic — myPullRequests is now filtered to open | draft before slicing (matching the existing Issues pattern), and adds "View all" drill-down buttons for reviews and PRs when items exceed the 5-item preview limit.

  • When MyPRs is embedded in Overview, only open/draft PRs are passed (prs = openPrs.slice(0, MAX_PRS)), but MyPRs still renders "Open N" and "Merged 0" tabs because it has no hideTabs equivalent — unlike Issues which receives both hideTabs and hideHeader from Overview, suppressing all filter chrome.

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style/UX suggestions with no data or logic impact

The core bug fixes (filter-then-slice, hideHeader suppression, View All buttons) are correctly implemented and well-tested. The only open finding is a P2 UX inconsistency where MyPRs renders an empty 'Merged 0' tab in the Overview panel, unlike Issues which uses hideTabs to suppress its filter chrome. This is cosmetic and does not affect correctness or data integrity.

src/components/MyPRs/MyPRs.tsx and its usage in src/components/Overview/Overview.tsx — missing hideTabs prop causes an empty 'Merged 0' tab in the Overview panel

Important Files Changed

Filename Overview
src/components/Overview/Overview.tsx Core fix: filter-then-slice for PRs is correct; 'View all' buttons use consistent counts; MyPRs is missing hideTabs so 'Merged 0' tab is always visible in the Overview panel
src/components/ReviewQueue/ReviewQueue.tsx Added hideHeader prop correctly; SectionHead is suppressed when embedded; filter bar remains functional
src/components/MyPRs/MyPRs.tsx Added hideHeader prop correctly, but no hideTabs equivalent exists; 'Merged 0' tab renders in Overview context where only open/draft PRs are passed
src/components/Issues/Issues.tsx Added hideHeader prop correctly alongside existing hideTabs; both are used in Overview to suppress all filter chrome
src/components/ActivityFeed/ActivityFeed.tsx Added hideHeader prop correctly; implementation is clean
src/components/Overview/Overview.test.tsx Good coverage for new View All visibility, mixed-state PR edge cases, and activity/issue limits

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    D[dashboard data] --> RR[reviewRequests]
    D --> MP[myPullRequests]
    D --> AI[assignedIssues]
    D --> RA[recentActivity]

    RR -->|slice 0..5| reviews["reviews (≤5)"]
    MP -->|filter open+draft| openPrs[openPrs]
    openPrs -->|slice 0..5| prs["prs (≤5)"]
    AI -->|filter open| openIssues[openIssues]
    openIssues -->|slice 0..5| issues["issues (≤5)"]
    RA -->|slice 0..5| activities["activities (≤5)"]

    reviews -->|hideHeader| RQ[ReviewQueue]
    prs -->|hideHeader| MYP[MyPRs]
    issues -->|hideHeader + hideTabs| ISS[Issues]
    activities -->|hideHeader| AF[ActivityFeed]

    RR -->|length > 5| VR["View all N reviews btn"]
    openPrs -->|length > 5| VP["View all N PRs btn"]
    openIssues -->|length > 5| VI["View all N issues btn"]
Loading

Comments Outside Diff (1)

  1. src/components/Overview/Overview.tsx, line 180-186 (link)

    P2 "Merged 0" tab renders in Overview panel

    MyPRs receives only open/draft PRs here (from openPrs.slice), so tabCounts.merged will always be 0. Unlike Issues, which receives both hideTabs and hideHeader to suppress all filter chrome, MyPRs only gets hideHeader — leaving a permanently-empty "Merged 0" tab visible to users in the "Work in flight" card.

    Consider adding a hideTabs prop to MyPRs (mirroring Issues) and passing it from Overview:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/components/Overview/Overview.tsx
    Line: 180-186
    
    Comment:
    **"Merged 0" tab renders in Overview panel**
    
    `MyPRs` receives only open/draft PRs here (from `openPrs.slice`), so `tabCounts.merged` will always be `0`. Unlike `Issues`, which receives both `hideTabs` and `hideHeader` to suppress all filter chrome, `MyPRs` only gets `hideHeader` — leaving a permanently-empty "Merged 0" tab visible to users in the "Work in flight" card.
    
    Consider adding a `hideTabs` prop to `MyPRs` (mirroring `Issues`) and passing it from Overview:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

Fix All in Claude Code

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/components/Overview/Overview.tsx
Line: 180-186

Comment:
**"Merged 0" tab renders in Overview panel**

`MyPRs` receives only open/draft PRs here (from `openPrs.slice`), so `tabCounts.merged` will always be `0`. Unlike `Issues`, which receives both `hideTabs` and `hideHeader` to suppress all filter chrome, `MyPRs` only gets `hideHeader` — leaving a permanently-empty "Merged 0" tab visible to users in the "Work in flight" card.

Consider adding a `hideTabs` prop to `MyPRs` (mirroring `Issues`) and passing it from Overview:

```suggestion
            <MyPRs
              prs={prs}
              isLoading={showLoadingState}
              onOpen={openUrl}
              onWorkspaceAction={handleWorkspaceAction}
              hideHeader
              hideTabs
            />
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(ui): resolve count inconsistencies b..." | Re-trigger Greptile

@mpiton mpiton merged commit 970840f into main Apr 12, 2026
9 checks passed
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.

fix(ui): Count inconsistencies between sidebar, stats bar, and view headings

1 participant