Skip to content

Feat/revamp member profile page#4797

Open
Saurabh-2607 wants to merge 14 commits into
OWASP:mainfrom
Saurabh-2607:feat/revamp-member-profile-page
Open

Feat/revamp member profile page#4797
Saurabh-2607 wants to merge 14 commits into
OWASP:mainfrom
Saurabh-2607:feat/revamp-member-profile-page

Conversation

@Saurabh-2607

Copy link
Copy Markdown
Contributor

Proposed change

Resolves #4339

This PR updates the member profile page layout to follow a structure similar to GitHub’s profile pages, providing a clearer hierarchy for users' contributions, repositories, and activities.

Key changes include:

  • Moving the profile header and contribution activity graph to the top-right / main section.
  • Utilizing MemberDetailSidebar as a clearly defined left sidebar for user details and stats.
  • Improving the layout hierarchy for recent issues, milestones, pull requests, and releases.
  • Updating the MemberDetailsPageSkeleton to match the new UI's two-column design (sidebar on the left, content and heatmap on the right) ensuring a smooth transition during loading.
  • Included/updated tests to cover the new skeleton layout changes.

Screenshots

image image image image

Checklist

  • Required: I followed the contributing workflow
  • Required: I verified that my code works as intended and resolves the issue as described
  • Required: I ran make check-test locally: all warnings addressed, tests passed
  • I used AI for code, documentation, tests, or communication related to this PR

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Summary by CodeRabbit

  • New Features
    • Added a dedicated sidebar section for member details (avatar, bio, account info, and stats), simplifying the main profile layout.
  • Style
    • Reorganized the member profile page layout with a cleaner flex-based sidebar + main content grid.
    • Hidden contribution heatmap scrollbars for a cleaner visual experience.
    • Refined spacing/gap behavior across profile cards and sections.
  • New Features
    • Milestone UI now highlights open issue counts (updated indicators).
    • Increased default initial repository display from 4 to 6 items.
  • Tests
    • Updated unit and accessibility tests to match the revised UI structure and data assertions.

Walkthrough

This PR restructures the member profile page layout by introducing a new MemberDetailSidebar component to encapsulate user details and statistics, simplifying UserSummary, and reorganizing the main content area into a sidebar-plus-main-column structure. Supporting component styling is updated for consistent spacing, Milestones now displays open issues instead of closed, and repository display defaults are increased. The skeleton loader and comprehensive test suite are aligned throughout.

Changes

Member Profile Layout Restructure with Supporting Component Updates

Layer / File(s) Summary
Create MemberDetailSidebar component
frontend/src/components/cards/MemberDetailSidebar.tsx
New React component that renders user avatar with fallback, name/login link, formatted bio, account detail rows (joined date, email, company, location), and stat blocks (followers, following, repositories, contributions) using InfoBlock child components with derived data and explicit fallbacks for missing fields.
Update InfoBlock for optional icon and simplified layout
frontend/src/components/InfoBlock.tsx
Icon prop made optional; default label removed from parameter destructuring; rendering refactored to conditionally display icon and simplify value container with updated flex/gap/alignment styling.
Refactor UserSummary and restructure UserDetailsPage layout
frontend/src/app/members/[memberKey]/page.tsx
UserSummary simplified to accept only user and formattedBio, delegating all sidebar rendering to MemberDetailSidebar. UserDetailsPage restructured from vertical composition to flex layout with aside sidebar and main column conditionally rendering ContributionHeatmap, followed by grid of modules: RepositoriesModules, RecentIssues, RecentPullRequests, Milestones, RecentReleases.
Update ContributionHeatmap scrollbar and chart sizing
frontend/src/components/ContributionHeatmap.tsx
Horizontal-scroll wrapper changed from scrollbar-default to scrollbar-hidden class; inline CSS extended with scrollbar-width, -ms-overflow-style, and ::-webkit-scrollbar rules; calculateChartWidth constants updated for compact/medium/default variants; chart wrapped in responsive md:block container with computed aspectRatio and height/width set to 100%.
Adjust spacing and margins across components
frontend/src/components/ItemCardList.tsx, frontend/src/components/RecentReleases.tsx, frontend/src/components/Release.tsx
ItemCardList applies consistent gap-4 at grid level and removes per-card mb-4 margins; RecentReleases uses grid gap-4 spacing; Release wrapper removes mb-4 margin while retaining other base styling.
Update Milestones to show open issues
frontend/src/components/Milestones.tsx
Icon imports consolidated to single line; FaCircleCheck swapped for FaCircleExclamation; milestone detail changed from displaying closedIssuesCount to openIssuesCount.
Increase repository display defaults and adjust grid
frontend/src/components/RepositoryCard.tsx, frontend/src/components/cards/RepositoriesModules.tsx
RepositoryCard default maxInitialDisplay increased from 4 to 6; lg:grid-cols-4 breakpoint removed to reduce columns on large screens; RepositoriesModules passes maxInitialDisplay={6} to RepositoryCard.
Update MemberDetailsPageSkeleton for new layout structure
frontend/src/components/skeletons/MemberDetailsPageSkeleton.tsx
Reworked from single-page grid to responsive flex layout with explicit sidebar skeleton (avatar/header placeholders, detail/stat rows), main content with heatmap skeleton, 6-item repository CardSection, and two TwoColumnSection instances (issue+pr, milestone+release) with minHeight reduced from min-h-[600px] to min-h-[400px].
Update InfoBlock unit tests
frontend/__tests__/unit/components/InfoBlock.test.tsx
Removes FaCode icon import, adds className prop testing, removes label-related test cases, updates DOM/class expectations to match simplified icon (w-5/text-gray-500) and text container (text-base/text-gray-600) styling.
Update Milestones and milestone assertions across page tests
frontend/__tests__/unit/components/Milestones.test.tsx, frontend/__tests__/unit/pages/Home.test.tsx, frontend/__tests__/unit/pages/OrganizationDetails.test.tsx, frontend/__tests__/unit/pages/ProjectDetails.test.tsx, frontend/__tests__/unit/pages/RepositoryDetails.test.tsx, frontend/__tests__/unit/pages/UserDetails.test.tsx
Removes assertions for closed-issues display across all milestone rendering tests while retaining open-issues count assertions.
Update ContributionHeatmap test querying patterns
frontend/__tests__/unit/components/ContributionHeatmap.test.tsx, frontend/__tests__/a11y/components/ContributionHeatmap.a11y.test.tsx
Replaces getByTestId/findByTestId queries with getAllByTestId patterns; wraps chart presence checks in waitFor blocks; updates all edge-case, behavior, integration, and variant test assertions to use getAllByTestId(...)[0] indexing.
Update RepositoryCard tests for increased display default
frontend/__tests__/unit/components/RepositoryCard.test.tsx, frontend/__tests__/a11y/components/RepositoryCard.a11y.test.tsx
Updates repository-count threshold from "show 4" to "show 6"; verifies initial rendering of repositories 0-5 when more than 6 provided; adjusts ShowMoreButton visibility; updates archived-badge persistence test with 8-repository dataset and revised badge visibility counts; increases a11y test mock repository count to 7.
Update RecentRelease and UserDetails tests
frontend/__tests__/unit/components/RecentRelease.test.tsx, frontend/__tests__/unit/pages/UserDetails.test.tsx
Removes main card wrapper assertion in RecentRelease test; simplifies UserSummary prop wiring, removes Badges mock, deletes entire Badge Display Tests suite, adjusts avatar/class/heading assertions, changes no-recent assertions to use queryByText absence, updates bio alignment classes, changes joined-date label from Joined: to Joined :.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • OWASP/Nest#3298: Earlier integration of ContributionHeatmap into the /members/[memberKey] page that this PR builds upon with the new sidebar layout.
  • OWASP/Nest#2208: Prior changes to members page UserSummary and ContributionHeatmap rendering flow that this PR extends with the new sidebar component.
  • OWASP/Nest#2751: Related updates to ContributionHeatmap component behavior and test coverage that align with this PR's styling and test assertion changes.

Suggested labels

frontend, frontend-tests

Suggested reviewers

  • arkid15r
  • kasya
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat/revamp member profile page' is concise and directly refers to the main change: redesigning the member profile page layout.
Description check ✅ Passed The description clearly explains the purpose (resolves #4339), outlines key changes (sidebar, hierarchy improvements, skeleton updates, tests), and includes screenshots demonstrating the redesign.
Linked Issues check ✅ Passed The PR successfully implements the objectives from issue #4339: moves profile header/heatmap to main section, utilizes MemberDetailSidebar for left sidebar, improves layout hierarchy for recent items, updates skeleton design, and includes test updates.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the member profile redesign objectives. Component updates (UserSummary, ContributionHeatmap, InfoBlock, Milestones, etc.), styling adjustments, and test updates are all in scope for the GitHub-inspired layout revamp.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
frontend/src/components/Milestones.tsx (1)

41-42: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider adding a defensive null check for openIssuesCount.

The component uses null checks for other potentially nullable fields (item.createdAt on line 38, item?.repositoryName on line 44). For consistency and defensive programming, consider adding a fallback for openIssuesCount in case it's undefined or null:

🛡️ Suggested defensive check
 <div className="mr-4 flex items-center">
   <FaCircleExclamation className="mr-2 h-4 w-4" />
-  <span>{item.openIssuesCount} open</span>
+  <span>{item.openIssuesCount ?? 0} open</span>
 </div>
🤖 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 `@frontend/src/components/Milestones.tsx` around lines 41 - 42, The JSX
rendering in Milestones.tsx uses item.openIssuesCount without a null check;
update the span that displays "{item.openIssuesCount} open" to defensively
handle undefined/null (e.g., use a fallback like item.openIssuesCount ?? 0 or
conditional rendering) so it always renders a sensible value; locate the usage
of item.openIssuesCount near the FaCircleExclamation element and replace it with
the null-safe expression to preserve UI and avoid rendering "undefined".
🤖 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 `@frontend/src/app/members/`[memberKey]/page.tsx:
- Around line 26-28: UserSummary currently casts away a nullable prop
(UserSummaryProps.user) before passing to MemberDetailSidebar which can crash;
either change the UserSummaryProps type to require user: User (remove null) so
UserSummary and its export are safe, or keep the nullable type and add a runtime
guard in the UserSummary function to handle null (e.g., return null/placeholder)
before calling MemberDetailSidebar; update the UserSummary signature and any
callers (notably the existing guarded call can remain) to match the tightened
type if you choose the type-change approach.

---

Outside diff comments:
In `@frontend/src/components/Milestones.tsx`:
- Around line 41-42: The JSX rendering in Milestones.tsx uses
item.openIssuesCount without a null check; update the span that displays
"{item.openIssuesCount} open" to defensively handle undefined/null (e.g., use a
fallback like item.openIssuesCount ?? 0 or conditional rendering) so it always
renders a sensible value; locate the usage of item.openIssuesCount near the
FaCircleExclamation element and replace it with the null-safe expression to
preserve UI and avoid rendering "undefined".
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e0b4f4f6-3bd7-451d-8c1f-49bba393a212

📥 Commits

Reviewing files that changed from the base of the PR and between a547c9e and 94a1e98.

📒 Files selected for processing (11)
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/components/ContributionHeatmap.tsx
  • frontend/src/components/InfoBlock.tsx
  • frontend/src/components/ItemCardList.tsx
  • frontend/src/components/Milestones.tsx
  • frontend/src/components/RecentReleases.tsx
  • frontend/src/components/Release.tsx
  • frontend/src/components/RepositoryCard.tsx
  • frontend/src/components/cards/MemberDetailSidebar.tsx
  • frontend/src/components/cards/RepositoriesModules.tsx
  • frontend/src/components/skeletons/MemberDetailsPageSkeleton.tsx

Comment thread frontend/src/app/members/[memberKey]/page.tsx
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes May 30, 2026

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

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.

No issues found across 11 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@Saurabh-2607 Saurabh-2607 marked this pull request as ready for review June 1, 2026 15:52

@kasya kasya left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

hi @Saurabh-2607

I left some requests below, but please address Code Rabbit comment before going over these. Thanks!

Comment thread frontend/src/app/members/[memberKey]/page.tsx
Comment thread frontend/src/app/members/[memberKey]/page.tsx
Comment thread frontend/src/app/members/[memberKey]/page.tsx Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Caution

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

⚠️ Outside diff range comments (3)
frontend/__tests__/unit/pages/UserDetails.test.tsx (1)

398-404: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix fixture shape to match the page’s GraphQL contract.

This test sets recentIssues under user, but UserDetailsPage reads graphQLData.recentIssues (top-level). The current assertion can pass without exercising the intended empty-issues path.

Suggested patch
   test('handles no recent issues gracefully', async () => {
     const noIssuesData = {
+      ...mockUserDetailsData,
+      recentIssues: [],
       user: { ...mockUserDetailsData.user, recentIssues: {} },
     }
🤖 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 `@frontend/__tests__/unit/pages/UserDetails.test.tsx` around lines 398 - 404,
The test fixture in the handles no recent issues gracefully test incorrectly
nests recentIssues under the user object, but UserDetailsPage reads
graphQLData.recentIssues at the top level. Restructure the noIssuesData object
so that recentIssues is a top-level property (at the same level as user) set to
an empty object, matching the GraphQL contract that the page component expects.
This ensures the test actually exercises the empty-issues code path rather than
just passing without validating the intended behavior.
frontend/__tests__/a11y/components/ContributionHeatmap.a11y.test.tsx (1)

88-93: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add the same chart-ready wait in the second a11y test to avoid timing flakes.

Line 88 through Line 93 runs axe(container) without waiting for chart mount, while the previous test now waits explicitly. Make both tests consistent so the a11y check runs against fully rendered markup.

🤖 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 `@frontend/__tests__/a11y/components/ContributionHeatmap.a11y.test.tsx` around
lines 88 - 93, The second a11y test (the one checking accessibility violations
when title is provided) is running the axe accessibility check without waiting
for the chart component to fully mount, which differs from the previous test and
can cause timing flakes. Add an explicit wait for the chart to be ready before
calling axe(container) in this test to match the behavior of the first test and
ensure the a11y check runs against fully rendered markup.
frontend/src/components/ContributionHeatmap.tsx (1)

340-360: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Render only one chart instance to avoid duplicate heavy work.

Line 340 through Line 360 currently mounts two Chart components and hides one via CSS. Both still render and execute, which doubles chart work on every update and can degrade interaction on the member page.

Suggested direction
-        <div className="mx-auto w-max px-2 md:hidden">
-          <Chart
-            height={getChartHeight()}
-            options={options}
-            series={heatmapSeries}
-            type="heatmap"
-            width={chartWidth}
-          />
-        </div>
-        <div
-          className="hidden w-full px-2 md:block"
-          style={{ aspectRatio: `${chartWidth} / ${getChartHeight()}` }}
-        >
-          <Chart
-            height="100%"
-            options={options}
-            series={heatmapSeries}
-            type="heatmap"
-            width="100%"
-          />
-        </div>
+        <div className="mx-auto w-max min-w-full px-2">
+          <Chart
+            height={getChartHeight()}
+            options={options}
+            series={heatmapSeries}
+            type="heatmap"
+            width={chartWidth}
+          />
+        </div>
🤖 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 `@frontend/src/components/ContributionHeatmap.tsx` around lines 340 - 360, The
ContributionHeatmap component is rendering two Chart instances simultaneously
and hiding one via CSS, which causes duplicate rendering work. Instead of using
two separate Chart components with CSS display toggles (md:hidden and md:block),
use a responsive hook like useMediaQuery or a custom screen size detection hook
to conditionally render only a single Chart component based on the current
screen size. This approach will ensure only one Chart instance is mounted and
executed at any given time, eliminating the duplicate heavy work on every
update.
🤖 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.

Outside diff comments:
In `@frontend/__tests__/a11y/components/ContributionHeatmap.a11y.test.tsx`:
- Around line 88-93: The second a11y test (the one checking accessibility
violations when title is provided) is running the axe accessibility check
without waiting for the chart component to fully mount, which differs from the
previous test and can cause timing flakes. Add an explicit wait for the chart to
be ready before calling axe(container) in this test to match the behavior of the
first test and ensure the a11y check runs against fully rendered markup.

In `@frontend/__tests__/unit/pages/UserDetails.test.tsx`:
- Around line 398-404: The test fixture in the handles no recent issues
gracefully test incorrectly nests recentIssues under the user object, but
UserDetailsPage reads graphQLData.recentIssues at the top level. Restructure the
noIssuesData object so that recentIssues is a top-level property (at the same
level as user) set to an empty object, matching the GraphQL contract that the
page component expects. This ensures the test actually exercises the
empty-issues code path rather than just passing without validating the intended
behavior.

In `@frontend/src/components/ContributionHeatmap.tsx`:
- Around line 340-360: The ContributionHeatmap component is rendering two Chart
instances simultaneously and hiding one via CSS, which causes duplicate
rendering work. Instead of using two separate Chart components with CSS display
toggles (md:hidden and md:block), use a responsive hook like useMediaQuery or a
custom screen size detection hook to conditionally render only a single Chart
component based on the current screen size. This approach will ensure only one
Chart instance is mounted and executed at any given time, eliminating the
duplicate heavy work on every update.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2c293484-83b4-46a5-acbc-603d63bd8226

📥 Commits

Reviewing files that changed from the base of the PR and between 94a1e98 and b2b2c40.

📒 Files selected for processing (15)
  • frontend/__tests__/a11y/components/ContributionHeatmap.a11y.test.tsx
  • frontend/__tests__/a11y/components/RepositoryCard.a11y.test.tsx
  • frontend/__tests__/unit/components/ContributionHeatmap.test.tsx
  • frontend/__tests__/unit/components/InfoBlock.test.tsx
  • frontend/__tests__/unit/components/Milestones.test.tsx
  • frontend/__tests__/unit/components/RecentRelease.test.tsx
  • frontend/__tests__/unit/components/RepositoryCard.test.tsx
  • frontend/__tests__/unit/pages/Home.test.tsx
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx
  • frontend/__tests__/unit/pages/ProjectDetails.test.tsx
  • frontend/__tests__/unit/pages/RepositoryDetails.test.tsx
  • frontend/__tests__/unit/pages/UserDetails.test.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/components/ContributionHeatmap.tsx
  • frontend/src/components/cards/MemberDetailSidebar.tsx
💤 Files with no reviewable changes (6)
  • frontend/tests/unit/pages/Home.test.tsx
  • frontend/tests/unit/pages/OrganizationDetails.test.tsx
  • frontend/tests/unit/pages/RepositoryDetails.test.tsx
  • frontend/tests/unit/components/RecentRelease.test.tsx
  • frontend/tests/unit/pages/ProjectDetails.test.tsx
  • frontend/tests/unit/components/Milestones.test.tsx

@sonarqubecloud

Copy link
Copy Markdown

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

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.

2 issues found across 15 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread frontend/src/components/cards/MemberDetailSidebar.tsx
Comment thread frontend/src/app/members/[memberKey]/page.tsx
@Saurabh-2607

Copy link
Copy Markdown
Contributor Author

@kasya Below are the ScreenRecording of the Updated Behaviour of the Heatmap and the Member Details

Comment-1 Heatmap

C-1-Heatmap.mp4

Comment-2 Member Detail

C-2-Member_Sidebar.mp4

@Saurabh-2607 Saurabh-2607 requested a review from kasya June 15, 2026 14:59
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.

Member Profile Layout Revamp

2 participants