Skip to content

Default to Identity tab and show contributors’ rating count in tooltip#1981

Merged
ragnep merged 4 commits intomainfrom
contributors-ratings-tooltip
Feb 24, 2026
Merged

Default to Identity tab and show contributors’ rating count in tooltip#1981
ragnep merged 4 commits intomainfrom
contributors-ratings-tooltip

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Feb 24, 2026

Summary by CodeRabbit

  • New Features

    • Top raters now show rating info in avatar tooltips.
    • Avatar items can display custom tooltip content.
  • Refactor

    • Profile links and redirects now use the user root path (no separate identity subroute).
    • Rep tab promoted to default; Brain and Rep flows split into dedicated pages.
  • Style

    • Minor responsive spacing and header layout adjustments.

Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

Consolidates the user identity subpath into the root profile path (/[user]), converts the identity page to a server-side redirect, reorders/defaults user tabs to surface Rep, and updates link targets and tests to the new routing.

Changes

Cohort / File(s) Summary
Tests (routing expectations)
__tests__/components/user/brain/UserPageBrainWrapper.test.tsx, __tests__/components/user/layout/UserPageTabs.test.tsx, __tests__/components/user/user-page-header/stats/UserPageHeaderStats.test.tsx, __tests__/components/user/utils/raters-table/ProfileRatersTableItem.test.tsx, __tests__/components/user/utils/set-up-profile/UserSetUpProfileCta.test.tsx, __tests__/pages/userPageRep.test.tsx
Updated mocked routes and assertions to expect /{user} (root profile) instead of /{user}/identity; adjusted test factory subroute inputs accordingly.
App pages / routing
app/[user]/brain/page.tsx, app/[user]/identity/page.tsx, app/[user]/page.tsx
Added app router brain page; replaced identity page with a server-side redirect to /{user}; swapped Brain → Rep tab on main user page, added rep-related types/helpers, and exported generateMetadata.
Profile link targets
components/brain/notifications/identity-rating/NotificationIdentityRating.tsx, components/user/utils/set-up-profile/UserSetUpProfileCta.tsx, components/user/utils/stats/UserStatsRow.tsx, components/user/user-page-header/name/UserPageHeaderName.tsx
Repointed links from /{user}/identity to /{user}; minor responsive spacing tweak.
Tab config & wiring
components/user/layout/userTabs.config.ts, components/react-query-wrapper/ReactQueryWrapper.tsx
Introduced new tab ordering (rep first, brain second), changed DEFAULT_USER_PAGE_TAB to rep, and updated an import path for rep types.
UI / tooltip & layout tweaks
components/common/OverlappingAvatars.tsx, components/user/rep/header/TopRaterAvatars.tsx, components/user/rep/new-rep/UserPageRepNewRepSearch.tsx, components/user/brain/UserPageBrainWrapper.tsx
Added optional tooltipContent to avatar items and populate rating tooltips; adjusted header layout to wrap; changed brain-wrapper redirect destination to /{user} when waves disabled.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • 6529-Collections/6529seize-frontend#1954: Modifies profile tab/routing and link targets (overlaps userTabs.config, redirects, and link updates).
  • 6529-Collections/6529seize-frontend#1510: Adjusts user page tab configuration and mapping (USER_PAGE_TAB_IDS / USER_PAGE_TAB_MAP), directly related to tab reorder/wiring.
  • 6529-Collections/6529seize-frontend#1539: Updates user header/stats routing to root profile route, related to the link target changes in header/stats tests.

Suggested reviewers

  • simo6529
  • prxt6529

Poem

🐰
I hopped from "/identity" to root so spry,
Rep now leads the meadow beneath the sky,
Tabs rearranged with a cheerful twitch,
Tooltips sparkle by each little stitch,
A joyful hop — the profile path's gone spry!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title describes only a subset of changes (defaulting to Identity tab and tooltip improvement) but omits major refactoring: moving Identity page to a redirect, creating new Brain tab page, restructuring the Rep tab implementation, and widespread routing path changes from /identity to root. Consider revising the title to reflect the primary change: either a comprehensive summary of the refactoring scope, or clarify if the Identity tab default and tooltip are the main objectives with routing changes as supporting infrastructure.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch contributors-ratings-tooltip

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.

Signed-off-by: ragnep <ragneinfo@gmail.com>
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.

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)
components/common/OverlappingAvatars.tsx (1)

18-120: ⚠️ Potential issue | 🟠 Major

Tooltip won’t render when only tooltipContent is provided.
showTooltip (Line 79) still checks only item.title, so tooltipContent is ignored for visibility. If callers pass tooltipContent without title, the tooltip never shows. Consider deriving visibility from the same value you render.

✅ Suggested fix
-        const showTooltip =
-          !isTouchDevice && item.title !== undefined && item.title !== "";
+        const tooltipBody = item.tooltipContent ?? item.title;
+        const showTooltip =
+          !isTouchDevice && tooltipBody !== undefined && tooltipBody !== "";
         const tooltipId = showTooltip ? `${baseId}-${index}` : undefined;
@@
-                {item.tooltipContent ?? item.title}
+                {tooltipBody}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/common/OverlappingAvatars.tsx` around lines 18 - 120, The tooltip
visibility logic currently uses the local showTooltip variable (in
OverlappingAvatars) which only checks item.title, so item.tooltipContent is
ignored; change showTooltip to true when either item.tooltipContent or
item.title is a non-empty value (e.g., item.tooltipContent !== undefined &&
item.tooltipContent !== "" || item.title !== undefined && item.title !== ""),
keep using tooltipId (derived from baseId and index) and the same conditional
that mounts <Tooltip id={tooltipId}> so tooltips render when callers provide
tooltipContent only.
🧹 Nitpick comments (1)
app/[user]/identity/page.tsx (1)

1-31: Use permanentRedirect() instead of redirect() for the retired /identity route.

redirect() returns a 307 (Temporary) HTTP redirect; for a 308 (Permanent), use permanentRedirect instead. Since /[user]/identity is being permanently retired and consolidated into /[user], a 307 misleads crawlers into re-fetching the old URL on every visit and prevents browsers from caching the redirect. permanentRedirect allows you to redirect the user to another URL and can be used in Server Components, Client Components, Route Handlers, and Server Functions.

♻️ Proposed fix
-import { redirect } from "next/navigation";
+import { permanentRedirect } from "next/navigation";

 // ... (rest of file unchanged)

-  redirect(`/${user}${qs ? `?${qs}` : ""}`);
+  permanentRedirect(`/${user}${qs ? `?${qs}` : ""}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/`[user]/identity/page.tsx around lines 1 - 31, The IdentityRedirectPage
currently calls redirect() which issues a 307; change to use permanentRedirect()
to emit a 308 permanent redirect. Update the import from next/navigation to
import permanentRedirect instead of redirect, and replace the
redirect(`/${user}${qs ? `?${qs}` : ""}`) call in the IdentityRedirectPage
function with permanentRedirect(...) while keeping the same URL construction
logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/common/OverlappingAvatars.tsx`:
- Line 18: The prop type tooltipContent uses React.ReactNode without importing
React; update OverlappingAvatars.tsx to import the type and use it directly by
adding import type { ReactNode } from "react" and change the prop declaration to
tooltipContent?: ReactNode so TypeScript resolves the type without needing the
React namespace.

---

Outside diff comments:
In `@components/common/OverlappingAvatars.tsx`:
- Around line 18-120: The tooltip visibility logic currently uses the local
showTooltip variable (in OverlappingAvatars) which only checks item.title, so
item.tooltipContent is ignored; change showTooltip to true when either
item.tooltipContent or item.title is a non-empty value (e.g.,
item.tooltipContent !== undefined && item.tooltipContent !== "" || item.title
!== undefined && item.title !== ""), keep using tooltipId (derived from baseId
and index) and the same conditional that mounts <Tooltip id={tooltipId}> so
tooltips render when callers provide tooltipContent only.

---

Nitpick comments:
In `@app/`[user]/identity/page.tsx:
- Around line 1-31: The IdentityRedirectPage currently calls redirect() which
issues a 307; change to use permanentRedirect() to emit a 308 permanent
redirect. Update the import from next/navigation to import permanentRedirect
instead of redirect, and replace the redirect(`/${user}${qs ? `?${qs}` : ""}`)
call in the IdentityRedirectPage function with permanentRedirect(...) while
keeping the same URL construction logic.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39ab644 and d81bc0e.

📒 Files selected for processing (19)
  • __tests__/components/user/brain/UserPageBrainWrapper.test.tsx
  • __tests__/components/user/layout/UserPageTabs.test.tsx
  • __tests__/components/user/user-page-header/stats/UserPageHeaderStats.test.tsx
  • __tests__/components/user/utils/raters-table/ProfileRatersTableItem.test.tsx
  • __tests__/components/user/utils/set-up-profile/UserSetUpProfileCta.test.tsx
  • __tests__/pages/userPageRep.test.tsx
  • app/[user]/brain/page.tsx
  • app/[user]/identity/page.tsx
  • app/[user]/page.tsx
  • components/brain/notifications/identity-rating/NotificationIdentityRating.tsx
  • components/common/OverlappingAvatars.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
  • components/user/brain/UserPageBrainWrapper.tsx
  • components/user/layout/userTabs.config.ts
  • components/user/rep/header/TopRaterAvatars.tsx
  • components/user/rep/new-rep/UserPageRepNewRepSearch.tsx
  • components/user/user-page-header/name/UserPageHeaderName.tsx
  • components/user/utils/set-up-profile/UserSetUpProfileCta.tsx
  • components/user/utils/stats/UserStatsRow.tsx

Comment thread components/common/OverlappingAvatars.tsx Outdated
@sonarqubecloud
Copy link
Copy Markdown

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.

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)
components/common/OverlappingAvatars.tsx (1)

79-81: ⚠️ Potential issue | 🟠 Major

showTooltip gate must also check for tooltipContent

The showTooltip condition (lines 79–80) gates the tooltip solely on item.title, but the interface allows tooltipContent to be provided independently. Any caller that supplies tooltipContent without a title will see the tooltip silently omitted — the <Tooltip> is never mounted (line 110) and line 120's fallback is unreachable. This violates the API contract suggested by the optional signature of both fields.

TopRaterAvatars mitigates this by always providing both title and tooltipContent together (or neither), so the issue is latent here. However, the component should handle tooltipContent as a first-class gate to prevent future bugs.

🐛 Proposed fix
-      const showTooltip =
-        !isTouchDevice && item.title !== undefined && item.title !== "";
+      const hasTooltipContent =
+        item.tooltipContent !== undefined ||
+        (item.title !== undefined && item.title !== "");
+      const showTooltip = !isTouchDevice && hasTooltipContent;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/common/OverlappingAvatars.tsx` around lines 79 - 81, The
showTooltip gating currently only checks item.title and thus prevents mounting
<Tooltip> when item.tooltipContent is supplied alone; update the logic that
defines showTooltip (and tooltipId usage) in OverlappingAvatars (the lines that
compute showTooltip and tooltipId) to consider tooltipContent as an alternative:
set showTooltip = !isTouchDevice && ((item.title !== undefined && item.title !==
"") || (item.tooltipContent !== undefined && item.tooltipContent !== "")), and
keep tooltipId conditional on that same showTooltip so the <Tooltip> component
and the fallback path are reachable when only tooltipContent is provided.
♻️ Duplicate comments (1)
components/common/OverlappingAvatars.tsx (1)

7-7: Import fix and interface field LGTM — resolves the previously flagged missing ReactNode import.

Also applies to: 18-18

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

In `@components/common/OverlappingAvatars.tsx` at line 7, The import statement in
OverlappingAvatars.tsx must include ReactNode so the component's interface types
compile; update the existing import line (import type { MouseEvent, ReactNode }
from "react";) or add ReactNode to it and ensure any interface/type declarations
that reference ReactNode (e.g., the props interface for OverlappingAvatars) use
that imported symbol consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/`[user]/identity/page.tsx:
- Around line 24-30: The redirect uses an unencoded path segment `user`, which
can break URLs; update the code that builds `destination` (where `user`,
`resolvedParams`, `resolvedSearchParams`, `buildQueryString`, and
`permanentRedirect` are used) to URL-encode the path segment (e.g., compute an
`encodedUser = encodeURIComponent(user)` and use `encodedUser` when composing
`destination`) so the redirect always produces a valid path; keep the
querystring logic with `buildQueryString(resolvedSearchParams)` unchanged and
pass the resulting `destination` to `permanentRedirect`.

---

Outside diff comments:
In `@components/common/OverlappingAvatars.tsx`:
- Around line 79-81: The showTooltip gating currently only checks item.title and
thus prevents mounting <Tooltip> when item.tooltipContent is supplied alone;
update the logic that defines showTooltip (and tooltipId usage) in
OverlappingAvatars (the lines that compute showTooltip and tooltipId) to
consider tooltipContent as an alternative: set showTooltip = !isTouchDevice &&
((item.title !== undefined && item.title !== "") || (item.tooltipContent !==
undefined && item.tooltipContent !== "")), and keep tooltipId conditional on
that same showTooltip so the <Tooltip> component and the fallback path are
reachable when only tooltipContent is provided.

---

Duplicate comments:
In `@components/common/OverlappingAvatars.tsx`:
- Line 7: The import statement in OverlappingAvatars.tsx must include ReactNode
so the component's interface types compile; update the existing import line
(import type { MouseEvent, ReactNode } from "react";) or add ReactNode to it and
ensure any interface/type declarations that reference ReactNode (e.g., the props
interface for OverlappingAvatars) use that imported symbol consistently.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 674712e and c53e731.

📒 Files selected for processing (3)
  • app/[user]/identity/page.tsx
  • components/common/OverlappingAvatars.tsx
  • components/user/layout/userTabs.config.ts

Comment thread app/[user]/identity/page.tsx
@ragnep ragnep merged commit c8d3033 into main Feb 24, 2026
7 checks passed
@ragnep ragnep deleted the contributors-ratings-tooltip branch February 24, 2026 12:03
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.

2 participants