Skip to content

Users nic rate#2047

Merged
ragnep merged 11 commits intomainfrom
users-nic-rate
Mar 5, 2026
Merged

Users nic rate#2047
ragnep merged 11 commits intomainfrom
users-nic-rate

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Mar 4, 2026

Summary by CodeRabbit

  • New Features

    • NIC rating CTA and reusable rate button added; desktop and mobile flows include a modal with Cancel support.
    • New mobile components: tab cards, Rep content, Identity content, rep direction toggle, and avatar-builder utility.
  • UI/UX Improvements

    • Reworked mobile/desktop layouts, headers, spacing, and responsive grids for rep/identity pages.
    • Updated statement, consolidated-address item styling, category pill visuals, and several color tokens.

ragnep added 2 commits March 4, 2026 15:01
Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds NIC rating UI (CTA, button, and modal flow), wires optional onRateClick through identity headers, introduces mobile rep/identity tab components, refactors mobile rep rendering, and applies multiple layout and styling adjustments across rep and identity components.

Changes

Cohort / File(s) Summary
Rate NIC CTA
components/user/identity/header/RateNicCta.tsx
New file exporting FingerprintIcon and RateNicButton components used as the NIC CTA.
Identity header wiring
components/user/identity/header/UserPageIdentityHeader.tsx, components/user/identity/header/UserPageIdentityHeaderCIC.tsx
Added optional onRateClick prop; conditional forwarding and rendering of RateNicButton when provided and when cic contribution exists.
CIC rate form & cancel flow
components/user/identity/header/cic-rate/UserPageIdentityHeaderCICRate.tsx
Added optional onCancel prop; refactored layout and button group to support two-button flow (Rate + Cancel) and adjusted form spacing.
Mobile tab components
components/user/rep/MobileIdentityTabContent.tsx, components/user/rep/MobileRepTabContent.tsx, components/user/rep/MobileTabCards.tsx
New mobile components: tab selector and per-tab content (rep and identity) with CTA wiring, activity log integration, and prop-driven rendering.
Page-level integration & mobile refactor
components/user/rep/UserPageRep.tsx, components/user/rep/UserPageRepMobile.tsx, components/user/rep/header/UserPageRepHeader.tsx
Introduced canEditNic logic, modal-based NIC rating flow (MobileWrapperDialog + rate modal), replaced large mobile UI with new mobile components, and adjusted header/avatar and rep controls.
Helpers & avatar utilities
components/user/rep/UserPageRep.helpers.ts, components/user/rep/buildRepAvatarItems.tsx
Added getCanEditNic permission helper and buildRepAvatarItems utility to generate avatar item descriptors with tooltipContent.
Rep UI tweaks
components/user/rep/RepCategoryPill.tsx, components/user/rep/RepDirectionToggle.tsx, components/user/rep/new-rep/UserPageRepNewRepSearch.tsx
Styling/layout changes to pills, contribution label text, conditional contribution display, new RepDirectionToggle component, and minor button color tweak.
Modal/dialog refactor
components/mobile-wrapper-dialog/MobileWrapperDialog.tsx
Replaced template-string class assembly with clsx, centralized transition and container class logic.
Statements & small style edits
components/user/identity/statements/..., components/user/identity/statements/consolidated-addresses/..., assorted files
Layout/padding adjustments for statements, reduced corner radius on address item, and several color/class token updates across headers and components.
Activity log style
components/user/rep/UserPageCombinedActivityLog.tsx
Minor heading color class change.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Header as UserPageIdentityHeader
    participant CIC as UserPageIdentityHeaderCIC
    participant Rate as RateNicButton
    participant Modal as MobileWrapperDialog

    User->>Header: interacts with header (rate CTA)
    Header->>CIC: forwards onRateClick (if provided)
    CIC->>Rate: renders RateNicButton when onRateClick present
    User->>Rate: clicks RateNicButton
    Rate->>Modal: invoke onRateClick → open rating modal
    User->>Modal: submit or cancel
    Modal->>Modal: onSuccess/onCancel closes modal
Loading
sequenceDiagram
    participant User
    participant Mobile as UserPageRepMobile
    participant Cards as MobileTabCards
    participant RepTab as MobileRepTabContent
    participant IdTab as MobileIdentityTabContent

    User->>Mobile: open mobile rep view
    Mobile->>Cards: render tab selector
    Cards->>Mobile: onTabChange (rep / identity)
    Mobile->>RepTab: render rep content when active
    Mobile->>IdTab: render identity content when active (includes Rate CTA)
    User->>Cards: tap tab → switch content
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • simo6529

"🐇
I nibble lines and shape the view,
A tiny fingerprint in tow.
Tabs that flip and modals true,
I hop — the UI starts to glow. ✨"

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

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.
Title check ❓ Inconclusive The title 'Users nic rate' is vague and lacks specificity about the actual changes implemented. Provide a more descriptive title that clarifies the primary change, such as 'Add NIC rating UI components and flow' or 'Implement user NIC rating modal and mobile views'.
✅ 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 unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch users-nic-rate

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

@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: 3

🧹 Nitpick comments (4)
components/user/rep/header/UserPageRepHeader.tsx (1)

9-9: Keep render pure by moving category reset into an effect.

At Line 38, state updates during render (setPrevCategories, setVisibleCount) can add avoidable rerender churn when categories reference changes frequently. Prefer effect-based reset and drop prevCategories state.

Proposed refactor
-import { useContext, useMemo, useState } from "react";
+import { useContext, useEffect, useMemo, useState } from "react";

   const [visibleCount, setVisibleCount] = useState(5);
-  const [prevCategories, setPrevCategories] = useState(categories);
-  if (categories !== prevCategories) {
-    setPrevCategories(categories);
-    setVisibleCount(5);
-  }
+  useEffect(() => {
+    setVisibleCount(5);
+  }, [categories]);

Also applies to: 37-41

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

In `@components/user/rep/header/UserPageRepHeader.tsx` at line 9, The render
currently updates state (setPrevCategories and setVisibleCount) when the
categories prop changes, causing impure renders; refactor UserPageRepHeader to
remove prevCategories state and instead use a useEffect that watches categories
and performs the reset logic (call setVisibleCount(...) and any other reset
actions) inside that effect; ensure any derived values use useMemo or local
variables and that the effect cleans up or guards against unnecessary updates so
renders remain pure when the categories reference changes.
components/user/rep/UserPageRep.tsx (3)

189-191: Consider simplifying the conditional prop.

The spread pattern works but is verbose. A simpler approach:

✨ Simpler conditional prop
 <UserPageIdentityHeader
   profile={profile}
   cicOverview={cicOverview ?? null}
-  {...(canEditNic
-    ? { onRateClick: () => setIsNicRateOpen(true) }
-    : {})}
+  onRateClick={canEditNic ? () => setIsNicRateOpen(true) : undefined}
 />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/UserPageRep.tsx` around lines 189 - 191, Replace the
verbose spread conditional for the onRateClick prop with a direct conditional
prop: instead of {...(canEditNic ? { onRateClick: () => setIsNicRateOpen(true) }
: {})}, set onRateClick={canEditNic ? () => setIsNicRateOpen(true) : undefined}
so the prop is present only when canEditNic is true; this uses the existing
canEditNic and setIsNicRateOpen identifiers.

44-54: The canEditNic logic is duplicated in UserPageRepMobile.tsx.

This exact logic appears in both files (lines 44-54 here and lines 71-81 in UserPageRepMobile.tsx). Consider extracting this into a shared utility function similar to how getCanEditRep is used.

♻️ Suggested extraction to a helper function

Create a helper in UserPageRep.helpers.ts:

export function getCanEditNic({
  connectedProfile,
  targetProfile,
  activeProfileProxy,
  address,
}: {
  connectedProfile: ApiIdentity | null;
  targetProfile: ApiIdentity;
  activeProfileProxy: ApiProfileProxy | null;
  address: string | undefined;
}): boolean {
  if (!connectedProfile?.handle) return false;
  if (activeProfileProxy) {
    if (targetProfile.handle === activeProfileProxy.created_by.handle) return false;
    return activeProfileProxy.actions.some(
      (action) => action.action_type === ApiProfileProxyActionType.AllocateCic
    );
  }
  if (amIUser({ profile: targetProfile, address })) return false;
  return true;
}

Then use it in both components:

-const canEditNic = useMemo((): boolean => {
-  if (!connectedProfile?.handle) return false;
-  if (activeProfileProxy) {
-    if (profile.handle === activeProfileProxy.created_by.handle) return false;
-    return activeProfileProxy.actions.some(
-      (action) => action.action_type === ApiProfileProxyActionType.AllocateCic
-    );
-  }
-  if (amIUser({ profile, address })) return false;
-  return true;
-}, [connectedProfile, profile, activeProfileProxy, address]);
+const canEditNic = useMemo(
+  () => getCanEditNic({ connectedProfile, targetProfile: profile, activeProfileProxy, address }),
+  [connectedProfile, profile, activeProfileProxy, address]
+);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/UserPageRep.tsx` around lines 44 - 54, The canEditNic
useMemo logic duplicated between UserPageRep.tsx (canEditNic) and
UserPageRepMobile.tsx should be extracted into a shared helper similar to
getCanEditRep: create a function getCanEditNic that accepts { connectedProfile,
targetProfile, activeProfileProxy, address } and implements the same checks
(check connectedProfile?.handle, if activeProfileProxy then compare
targetProfile.handle to activeProfileProxy.created_by.handle and return
activeProfileProxy.actions.some(a => a.action_type ===
ApiProfileProxyActionType.AllocateCic), otherwise use amIUser({ profile:
targetProfile, address }) to decide), then replace the useMemo bodies in both
components to call getCanEditNic(…) instead of duplicating the logic.

200-225: NIC rating modal content is duplicated.

The modal content (lines 200-225) is nearly identical to UserPageRepMobile.tsx (lines 173-198). Consider extracting this into a shared NicRateModal component to reduce duplication and ensure consistency.

♻️ Suggested extraction

Create a new component:

// components/user/rep/NicRateModal.tsx
export default function NicRateModal({
  isOpen,
  onClose,
  profile,
}: {
  readonly isOpen: boolean;
  readonly onClose: () => void;
  readonly profile: ApiIdentity;
}) {
  return (
    <MobileWrapperDialog
      title="Rate NIC"
      isOpen={isOpen}
      onClose={onClose}
      tabletModal
      maxWidthClass="md:tw-max-w-md"
    >
      <div className="tw-px-4 sm:tw-px-6">
        <UserPageRateWrapper profile={profile} type={RateMatter.NIC}>
          <UserPageIdentityHeaderCICRate
            profile={profile}
            isTooltip={false}
            onSuccess={onClose}
          />
        </UserPageRateWrapper>
        <div className="tw-mt-3">
          <button
            onClick={onClose}
            type="button"
            className="tw-w-full tw-cursor-pointer tw-rounded-lg tw-border tw-border-solid tw-border-iron-700 tw-bg-iron-900 tw-px-4 tw-py-3 tw-text-sm tw-font-semibold tw-text-white tw-transition tw-duration-300 tw-ease-out hover:tw-bg-iron-800"
          >
            Cancel
          </button>
        </div>
      </div>
    </MobileWrapperDialog>
  );
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/UserPageRep.tsx` around lines 200 - 225, The NIC rating
modal UI is duplicated—extract it into a shared NicRateModal component and
replace the inline JSX in both UserPageRep (the current file) and
UserPageRepMobile with that component; create NicRateModal that accepts props {
isOpen, onClose, profile } and renders the MobileWrapperDialog,
UserPageRateWrapper (type=RateMatter.NIC) and UserPageIdentityHeaderCICRate
(pass profile, isTooltip=false, onSuccess=onClose) plus the Cancel button which
calls onClose; update UserPageRep to render <NicRateModal isOpen={isNicRateOpen}
onClose={() => setIsNicRateOpen(false)} profile={profile} /> (and similarly in
UserPageRepMobile), and add the necessary import.
🤖 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/user/rep/header/UserPageRepHeader.tsx`:
- Around line 156-163: The SVG used inside the "Grant Rep" button in
UserPageRepHeader.tsx is decorative and should be hidden from assistive tech;
update the <svg> element (the one with className "tw-h-3.5 tw-w-3.5
tw-flex-shrink-0" and attributes viewBox/fill/stroke) to include
aria-hidden="true" (and optionally focusable="false") so screen readers don't
announce the redundant icon while the button label remains the accessible name.

In `@components/user/rep/MobileTabCards.tsx`:
- Around line 32-37: The mobile tab buttons currently only convey selection
visually; update the button elements used in MobileTabCards (the button that
calls onTabChange("rep") and the sibling tab button) to expose their pressed
state to assistive tech by adding an aria-pressed attribute bound to the active
state (e.g., aria-pressed={activeTab === "rep"} for the "rep" button and the
equivalent expression for the other tab). Ensure the attribute value is a
boolean and mirrors the existing activeTab comparison so screen readers receive
the active/inactive semantics.

In `@components/user/rep/UserPageRepMobile.tsx`:
- Around line 55-59: The current reference-equality check (categories !==
prevCategories) in UserPageRepMobile causes visibleCount to reset whenever the
parent supplies a new array reference; change the equality test to a stable
comparison (for example compare categories.length and the concatenated category
IDs or use a shallow/deep equality check like comparing
JSON.stringify(categories.map(c=>c.id)) or lodash/isEqual between categories and
prevCategories) before calling setPrevCategories and resetting
setVisibleCount(5), or alternatively memoize the parent value (activeCategories)
with useMemo in UserPageRep so the categories reference only changes when their
actual content changes; update the logic around prevCategories,
setPrevCategories, and setVisibleCount accordingly.

---

Nitpick comments:
In `@components/user/rep/header/UserPageRepHeader.tsx`:
- Line 9: The render currently updates state (setPrevCategories and
setVisibleCount) when the categories prop changes, causing impure renders;
refactor UserPageRepHeader to remove prevCategories state and instead use a
useEffect that watches categories and performs the reset logic (call
setVisibleCount(...) and any other reset actions) inside that effect; ensure any
derived values use useMemo or local variables and that the effect cleans up or
guards against unnecessary updates so renders remain pure when the categories
reference changes.

In `@components/user/rep/UserPageRep.tsx`:
- Around line 189-191: Replace the verbose spread conditional for the
onRateClick prop with a direct conditional prop: instead of {...(canEditNic ? {
onRateClick: () => setIsNicRateOpen(true) } : {})}, set onRateClick={canEditNic
? () => setIsNicRateOpen(true) : undefined} so the prop is present only when
canEditNic is true; this uses the existing canEditNic and setIsNicRateOpen
identifiers.
- Around line 44-54: The canEditNic useMemo logic duplicated between
UserPageRep.tsx (canEditNic) and UserPageRepMobile.tsx should be extracted into
a shared helper similar to getCanEditRep: create a function getCanEditNic that
accepts { connectedProfile, targetProfile, activeProfileProxy, address } and
implements the same checks (check connectedProfile?.handle, if
activeProfileProxy then compare targetProfile.handle to
activeProfileProxy.created_by.handle and return
activeProfileProxy.actions.some(a => a.action_type ===
ApiProfileProxyActionType.AllocateCic), otherwise use amIUser({ profile:
targetProfile, address }) to decide), then replace the useMemo bodies in both
components to call getCanEditNic(…) instead of duplicating the logic.
- Around line 200-225: The NIC rating modal UI is duplicated—extract it into a
shared NicRateModal component and replace the inline JSX in both UserPageRep
(the current file) and UserPageRepMobile with that component; create
NicRateModal that accepts props { isOpen, onClose, profile } and renders the
MobileWrapperDialog, UserPageRateWrapper (type=RateMatter.NIC) and
UserPageIdentityHeaderCICRate (pass profile, isTooltip=false, onSuccess=onClose)
plus the Cancel button which calls onClose; update UserPageRep to render
<NicRateModal isOpen={isNicRateOpen} onClose={() => setIsNicRateOpen(false)}
profile={profile} /> (and similarly in UserPageRepMobile), and add the necessary
import.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 859db7eb-cb0f-4fe8-82b5-dd165e02cae2

📥 Commits

Reviewing files that changed from the base of the PR and between 03acc1c and 7142b8d.

📒 Files selected for processing (12)
  • components/user/identity/header/RateNicCta.tsx
  • components/user/identity/header/UserPageIdentityHeader.tsx
  • components/user/identity/header/UserPageIdentityHeaderCIC.tsx
  • components/user/identity/header/cic-rate/UserPageIdentityHeaderCICRate.tsx
  • components/user/identity/statements/UserPageIdentityStatements.tsx
  • components/user/identity/statements/consolidated-addresses/UserPageIdentityStatementsConsolidatedAddressesItem.tsx
  • components/user/rep/MobileIdentityTabContent.tsx
  • components/user/rep/MobileRepTabContent.tsx
  • components/user/rep/MobileTabCards.tsx
  • components/user/rep/UserPageRep.tsx
  • components/user/rep/UserPageRepMobile.tsx
  • components/user/rep/header/UserPageRepHeader.tsx

Comment thread components/user/rep/header/UserPageRepHeader.tsx Outdated
Comment thread components/user/rep/MobileTabCards.tsx
Comment thread components/user/rep/UserPageRepMobile.tsx
ragnep added 3 commits March 4, 2026 15:19
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
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: 2

♻️ Duplicate comments (1)
components/user/rep/UserPageRepMobile.tsx (1)

54-58: ⚠️ Potential issue | 🟡 Minor

Reference comparison may cause unnecessary visibleCount resets.

The categories !== prevCategories comparison uses reference equality. If the parent component passes a new array reference on each render (e.g., via repCategories?.data ?? []), visibleCount will reset to 5 more frequently than intended—even when the actual category data hasn't changed.

Consider comparing by a stable identifier or memoizing activeCategories in the parent.

🛡️ More robust comparison
 const [prevCategories, setPrevCategories] = useState(categories);
-if (categories !== prevCategories) {
+// Compare by length and first/last category identifiers for stability
+const categoriesChanged =
+  categories.length !== prevCategories.length ||
+  categories[0]?.category !== prevCategories[0]?.category ||
+  categories[categories.length - 1]?.category !== prevCategories[prevCategories.length - 1]?.category;
+if (categoriesChanged) {
   setPrevCategories(categories);
   setVisibleCount(5);
 }

Or memoize activeCategories in the parent (UserPageRep.tsx):

const activeCategories = useMemo(
  () => (repDirection === "received" ? repCategories?.data : repCategoriesGiven?.data) ?? [],
  [repDirection, repCategories?.data, repCategoriesGiven?.data]
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/UserPageRepMobile.tsx` around lines 54 - 58, The current
reference-equality check (categories !== prevCategories) in UserPageRepMobile
causes visibleCount to reset whenever the parent passes a new array reference;
change the logic to compare category identity instead (e.g., compare arrays of
ids: prevCategories.map(c=>c.id) vs categories.map(c=>c.id) or use a
deep-equality helper like isEqual) before calling setPrevCategories and reset
setVisibleCount(5), or alternatively rely on a memoized activeCategories from
the parent (as suggested) so categories is stable; update the useState/useEffect
block that uses prevCategories, setPrevCategories, visibleCount, and
setVisibleCount accordingly.
🤖 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/user/identity/header/RateNicCta.tsx`:
- Around line 36-42: The button in RateNicCta.tsx lacks an explicit type and may
default to submit inside forms; update the JSX button element used with the
onRateClick handler to include type="button" so clicking it only triggers
onRateClick and does not submit any enclosing form (locate the button in
RateNicCta.tsx that uses the onRateClick prop and add the type attribute).

In `@components/user/rep/header/UserPageRepHeader.tsx`:
- Around line 42-46: Remove the inline render-time state updates: delete the
prevCategories state and the if (categories !== prevCategories) { ... } block;
instead add a useEffect that depends on categories and, when categories changes,
calls setVisibleCount(5). Reference the existing symbols: remove prevCategories
and setPrevCategories usage, and add useEffect(() => { setVisibleCount(5); },
[categories]) in the UserPageRepHeader component so state updates happen in an
effect rather than during render.

---

Duplicate comments:
In `@components/user/rep/UserPageRepMobile.tsx`:
- Around line 54-58: The current reference-equality check (categories !==
prevCategories) in UserPageRepMobile causes visibleCount to reset whenever the
parent passes a new array reference; change the logic to compare category
identity instead (e.g., compare arrays of ids: prevCategories.map(c=>c.id) vs
categories.map(c=>c.id) or use a deep-equality helper like isEqual) before
calling setPrevCategories and reset setVisibleCount(5), or alternatively rely on
a memoized activeCategories from the parent (as suggested) so categories is
stable; update the useState/useEffect block that uses prevCategories,
setPrevCategories, visibleCount, and setVisibleCount accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 41222162-bbb2-4529-aad2-94c367496d17

📥 Commits

Reviewing files that changed from the base of the PR and between d027494 and 7cdc33f.

📒 Files selected for processing (17)
  • components/home/boosted/BoostedDropCardHome.tsx
  • components/mobile-wrapper-dialog/MobileWrapperDialog.tsx
  • components/user/identity/header/RateNicCta.tsx
  • components/user/identity/header/UserPageIdentityHeaderCIC.tsx
  • components/user/identity/header/cic-rate/UserPageIdentityHeaderCICRate.tsx
  • components/user/rep/MobileIdentityTabContent.tsx
  • components/user/rep/MobileRepTabContent.tsx
  • components/user/rep/MobileTabCards.tsx
  • components/user/rep/RepCategoryPill.tsx
  • components/user/rep/UserPageCombinedActivityLog.tsx
  • components/user/rep/UserPageRep.helpers.ts
  • components/user/rep/UserPageRep.tsx
  • components/user/rep/UserPageRepMobile.tsx
  • components/user/rep/header/UserPageRepHeader.tsx
  • components/user/rep/new-rep/UserPageRepNewRepSearch.tsx
  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/user/user-page-header/name/UserPageHeaderName.tsx
✅ Files skipped from review due to trivial changes (1)
  • components/user/user-page-header/name/UserPageHeaderName.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • components/user/rep/UserPageRep.tsx
  • components/user/rep/MobileTabCards.tsx
  • components/user/rep/MobileRepTabContent.tsx
  • components/user/identity/header/UserPageIdentityHeaderCIC.tsx

Comment thread components/user/identity/header/RateNicCta.tsx
Comment thread components/user/rep/header/UserPageRepHeader.tsx
ragnep added 2 commits March 5, 2026 09:25
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.

♻️ Duplicate comments (1)
components/user/rep/header/UserPageRepHeader.tsx (1)

42-46: ⚠️ Potential issue | 🟠 Major

Move render-time state updates to useEffect.

Line 42-Line 46 performs state updates during render (setPrevCategories, setVisibleCount), which is unsafe in React and can cause unstable render behavior. Please remove prevCategories state and reset visibleCount inside an effect keyed by categories.

Suggested fix
-import { useContext, useMemo, useState } from "react";
+import { useContext, useEffect, useMemo, useState } from "react";
...
-  const [prevCategories, setPrevCategories] = useState(categories);
-  if (categories !== prevCategories) {
-    setPrevCategories(categories);
-    setVisibleCount(5);
-  }
+  useEffect(() => {
+    setVisibleCount(5);
+  }, [categories]);
#!/bin/bash
# Verify the render-phase state update pattern is removed from this file.
# Expected result after fix: no matches for the old inline reset block.
rg -n -C3 'prevCategories|setPrevCategories\(|if \(categories !== prevCategories\)' components/user/rep/header/UserPageRepHeader.tsx
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/header/UserPageRepHeader.tsx` around lines 42 - 46,
Remove the render-time state updates by deleting the prevCategories state and
the if (categories !== prevCategories) { ... } block, and instead add a
useEffect that depends on categories which calls setVisibleCount(5) when
categories changes; specifically remove references to prevCategories and
setPrevCategories and create a useEffect(() => { setVisibleCount(5); },
[categories]) so updates happen after render and avoid calling setState during
render of the component that uses categories, visibleCount, setVisibleCount.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/user/rep/header/UserPageRepHeader.tsx`:
- Around line 42-46: Remove the render-time state updates by deleting the
prevCategories state and the if (categories !== prevCategories) { ... } block,
and instead add a useEffect that depends on categories which calls
setVisibleCount(5) when categories changes; specifically remove references to
prevCategories and setPrevCategories and create a useEffect(() => {
setVisibleCount(5); }, [categories]) so updates happen after render and avoid
calling setState during render of the component that uses categories,
visibleCount, setVisibleCount.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7caca4d0-5620-4ed3-bdbf-bf91cf9248e6

📥 Commits

Reviewing files that changed from the base of the PR and between 7cdc33f and 5474788.

📒 Files selected for processing (2)
  • components/user/identity/header/RateNicCta.tsx
  • components/user/rep/header/UserPageRepHeader.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/user/identity/header/RateNicCta.tsx

ragnep added 2 commits March 5, 2026 10:08
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.

♻️ Duplicate comments (2)
components/user/rep/header/UserPageRepHeader.tsx (1)

41-45: ⚠️ Potential issue | 🔴 Critical

Move category reset logic out of render.

On Line 42, state is mutated during render. In React, this can cause unstable rerender behavior (especially with frequently changing array references). Move this reset into an effect keyed by category content.

💡 Proposed fix
-import { useContext, useMemo, useState } from "react";
+import { useContext, useEffect, useMemo, useState } from "react";

   const [visibleCount, setVisibleCount] = useState(5);
-
-  const [prevCategories, setPrevCategories] = useState(categories);
-  if (categories !== prevCategories) {
-    setPrevCategories(categories);
-    setVisibleCount(5);
-  }
+  const categoriesKey = useMemo(
+    () => categories.map((c) => c.category).join("|"),
+    [categories]
+  );
+  useEffect(() => {
+    setVisibleCount(5);
+  }, [categoriesKey]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/header/UserPageRepHeader.tsx` around lines 41 - 45, The
render currently calls setPrevCategories and setVisibleCount when categories !==
prevCategories (mutating state during render); move this logic into a useEffect
that watches categories (not the prevCategories ref) and performs the reset when
the category content changes — e.g., compare contents (length and items or use a
stable deep-equality like JSON.stringify(categories)) inside a useEffect, then
call setPrevCategories(categories) and setVisibleCount(5) from that effect;
update references to prevCategories, setPrevCategories, setVisibleCount, and
categories in the effect so no state is set during render.
components/user/rep/UserPageRepMobile.tsx (1)

55-59: ⚠️ Potential issue | 🔴 Critical

Remove render-time state updates for category-change reset.

Lines 56-58 perform setState during render, which is unsafe in React and can loop/reset excessively when categories gets new references. Use an effect keyed by stable category content.

💡 Proposed fix
-import { useContext, useMemo, useState } from "react";
+import { useContext, useEffect, useMemo, useState } from "react";

   const [visibleCount, setVisibleCount] = useState(5);
   const [editCategory, setEditCategory] = useState<string | null>(null);

-  const [prevCategories, setPrevCategories] = useState(categories);
-  if (categories !== prevCategories) {
-    setPrevCategories(categories);
-    setVisibleCount(5);
-  }
+  const categoriesKey = useMemo(
+    () => categories.map((c) => c.category).join("|"),
+    [categories]
+  );
+  useEffect(() => {
+    setVisibleCount(5);
+  }, [categoriesKey]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/rep/UserPageRepMobile.tsx` around lines 55 - 59, The
component is calling setPrevCategories and setVisibleCount during render when
categories !== prevCategories (prevCategories, setPrevCategories,
setVisibleCount, categories), which is unsafe; move that logic into a useEffect
that runs when categories change and perform a stable/deep comparison (e.g.,
compare JSON.stringify(categories) or use a helper comparator) to decide when to
update prevCategories and reset visibleCount to 5; update prevCategories and
setVisibleCount inside the effect (not during render) so updates occur only
after render and avoid render loops.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/user/rep/header/UserPageRepHeader.tsx`:
- Around line 41-45: The render currently calls setPrevCategories and
setVisibleCount when categories !== prevCategories (mutating state during
render); move this logic into a useEffect that watches categories (not the
prevCategories ref) and performs the reset when the category content changes —
e.g., compare contents (length and items or use a stable deep-equality like
JSON.stringify(categories)) inside a useEffect, then call
setPrevCategories(categories) and setVisibleCount(5) from that effect; update
references to prevCategories, setPrevCategories, setVisibleCount, and categories
in the effect so no state is set during render.

In `@components/user/rep/UserPageRepMobile.tsx`:
- Around line 55-59: The component is calling setPrevCategories and
setVisibleCount during render when categories !== prevCategories
(prevCategories, setPrevCategories, setVisibleCount, categories), which is
unsafe; move that logic into a useEffect that runs when categories change and
perform a stable/deep comparison (e.g., compare JSON.stringify(categories) or
use a helper comparator) to decide when to update prevCategories and reset
visibleCount to 5; update prevCategories and setVisibleCount inside the effect
(not during render) so updates occur only after render and avoid render loops.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7a5b7ba2-281f-48e8-885a-d631c5a29af2

📥 Commits

Reviewing files that changed from the base of the PR and between 5474788 and d1794a2.

📒 Files selected for processing (7)
  • components/user/identity/header/RateNicCta.tsx
  • components/user/rep/MobileRepTabContent.tsx
  • components/user/rep/MobileTabCards.tsx
  • components/user/rep/RepDirectionToggle.tsx
  • components/user/rep/UserPageRepMobile.tsx
  • components/user/rep/buildRepAvatarItems.tsx
  • components/user/rep/header/UserPageRepHeader.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/user/identity/header/RateNicCta.tsx

ragnep added 2 commits March 5, 2026 11:28
Signed-off-by: ragnep <ragneinfo@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Mar 5, 2026

@ragnep ragnep merged commit 0fb089a into main Mar 5, 2026
7 checks passed
@ragnep ragnep deleted the users-nic-rate branch March 5, 2026 10:32
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