Skip to content

Transfer NFTs#1528

Merged
prxt6529 merged 103 commits intomainfrom
transfer-nfts
Nov 5, 2025
Merged

Transfer NFTs#1528
prxt6529 merged 103 commits intomainfrom
transfer-nfts

Conversation

@prxt6529
Copy link
Copy Markdown
Collaborator

@prxt6529 prxt6529 commented Oct 9, 2025

Summary by CodeRabbit

  • New Features
    • Full NFT transfer UX: per-item selection, quantity controls, expandable transfer panel, single-item transfer widget, and multi-step transfer modal with connect gating.
  • Navigation
    • Current query parameters preserved across previous/next navigation and filters.
  • UI / Style
    • Thicker card borders, new shadow box, ownership badges, standardized "ETH" label, and transfer UI added across profile, collection, and token views.
  • Tests
    • Extensive transfer test coverage for selection, grouping, ERC721/ERC1155 flows, success/failure paths, and UI interactions.
  • Chores
    • Added device/media and debounced hooks, transfer state manager, new enums/constants, and typed iterative data fetching.

Signed-off-by: prxt6529 <prxt@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Oct 9, 2025

Walkthrough

Adds a transfer subsystem (state, selection UI, panel, modal, per-item components) integrated across collected/token pages; rewrites iterative paginated API helper with generics; introduces new constants, enums, hooks, scrollable tabs/filters refactors, and broad test/provider updates.

Changes

Cohort / File(s) Summary
Transfer Core & State
components/nft-transfer/TransferState.tsx, components/react-query-wrapper/ReactQueryWrapper.tsx
New TransferProvider context, useTransfer, buildTransferKey, TransferItem type; added PROFILE_COLLECTED_TRANSFER query key.
Transfer UI
components/nft-transfer/TransferModal.tsx, components/nft-transfer/TransferModalPfp.tsx, components/nft-transfer/TransferPanel.tsx, components/nft-transfer/TransferToggle.tsx, components/nft-transfer/TransferSingle.tsx
New client components: multi-step TransferModal (on‑chain flows), TransferModalPfp avatar helper, bottom TransferPanel with drawer and modal integration, TransferToggle (connect-aware), and TransferSingle (per-item registration, qty controls).
Collected / Cards Integration
components/user/collected/UserPageCollected.tsx, components/user/collected/cards/UserPageCollectedCard.tsx, components/user/collected/cards/UserPageCollectedCards.tsx, components/user/collected/filters/UserPageCollectedFilters.tsx
Wire dataTransfer and isTransferLoading; card components gain interactive/select modes, selection and qty props/handlers; filters/tabs adopt new scrollable container and TransferToggle integration.
Page Factory & Flag
app/[user]/_lib/userTabPageFactory.tsx, app/[user]/collected/page.tsx
FactoryArgs gains enableTransfer?: boolean; Tab may be wrapped with TransferProvider; collected page enables transfer flag.
Per-page Token Integrations
components/the-memes/*, components/memelab/*, components/6529Gradient/*, components/nextGen/.../NextGenToken.tsx
Connected-address ownership checks added; TransferSingle inserted where owner detected; collection→contract and contract-type mappings used; wallet extraction refactored.
API / Pagination
services/6529api.ts
Rewrite fetchAllPages to fetchAllPages<T>(startUrl) iterative loop with getNextUrl handling absolute/relative next links and page increments; stronger typing and error handling.
Constants, Types & Enums
constants.ts, enums.ts, entities/IProfile.ts
New exported constants (MEMELAB_CONTRACT, NULL_ADDRESS, NULL_DEAD_ADDRESS, MANIFOLD), ContractType enum, and mappings COLLECTED_COLLECTION_TYPE_TO_CONTRACT / ..._TO_CONTRACT_TYPE.
Hooks & UI plumbing
hooks/useMediaQuery.ts, hooks/useDebouncedValue.ts, components/nft-navigation/NftNavigation.tsx, components/user/layout/UserPageTabs.tsx
Add useMediaQuery, useDebouncedValue; NftNavigation preserves query params; tabs refactored to scroll container with ResizeObserver and arrow controls (memoized getTabsToShow).
Tests & Provider Updates
__tests__/**, __tests__/components/nft-transfer/**
Many new/expanded tests for transfer components/state; tests updated to render with TransferProvider, SeizeConnectProvider, WagmiProvider, and QueryClientProvider; extensive mocks for contracts/wallets and integration scenarios.
Misc / Styling / Minor
components/layout/WebLayout.tsx, components/user/utils/level/UserLevel.tsx, styles/Home.module.scss, app/network/tdh/*.tsx, various fetchAllPages call sites
WebLayout/WebSidebar prop adjustments, minor JSX/SVG formatting tweaks, new .shadowBox css, TDH border-thickness updates, and many fetchAllPages call sites switched to generic typed calls.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant UI as Transfer UI\n(Toggle/Single/Panel)
    participant State as TransferState\n(Context)
    participant Modal as TransferModal
    participant Chain as Smart Contract
    participant Connect as SeizeConnect

    User->>UI: Click Transfer Toggle
    alt not connected
        UI->>Connect: seizeConnect()
        Connect-->>UI: connected
    end
    UI->>State: setEnabled(true)
    User->>UI: Select items / adjust qty
    UI->>State: toggleSelect / incQty / decQty
    State-->>UI: selection & totals update
    User->>UI: Click Continue
    UI->>Modal: open(selected items)
    Modal->>Modal: recipient selection & review
    User->>Modal: confirm transfer
    Modal->>Chain: submit ERC721/ERC1155 tx(s)
    Chain-->>Modal: tx hash / receipt
    Modal->>UI: onClose({completed:true})
    UI->>State: clear() / setEnabled(false)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

  • Focus areas needing extra attention:
    • components/nft-transfer/TransferModal.tsx — complex async on‑chain grouping, transaction submission, wagmi/viem interactions.
    • components/nft-transfer/TransferState.tsx — key building, ordering guarantees, qty clamping and edge cases.
    • services/6529api.ts — iterative pagination logic and absolute/relative next URL handling.
    • components/user/collected/* & cards — accessibility, selection/qty wiring and URL/query synchronization.
    • Tests — many new/modified tests with cross-provider and contract mocks.

Possibly related PRs

Suggested reviewers

  • ragnep

Poem

🐇 I hopped through code with twitchy nose,
I stacked the cards in tidy rows.
A toggle, panel, modal bright,
I nudged the counts until they're right.
🥕 Off they go — a rabbit's byte.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Transfer NFTs' is vague and generic, failing to convey the specific nature of changes made throughout the PR. Clarify the title to indicate the primary change: e.g., 'Add NFT transfer functionality to collected items UI' or 'Implement transfer UI for collected NFTs on user profile'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch transfer-nfts

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 128b1dd and 021bec0.

📒 Files selected for processing (1)
  • components/nft-transfer/TransferState.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Files:

  • components/nft-transfer/TransferState.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Files:

  • components/nft-transfer/TransferState.tsx
🧠 Learnings (2)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferState.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferState.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)

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: 5

🧹 Nitpick comments (6)
components/user/collected/transfer/TransferState.tsx (1)

45-45: Mark component props as readonly

Add readonly to TransferProvider props to follow project conventions.

As per coding guidelines

-export function TransferProvider({ children }: { children: React.ReactNode }) {
+export function TransferProvider({ children }: { readonly children: React.ReactNode }) {
components/user/collected/UserPageCollected.tsx (1)

471-471: Remove JSX comments in TSX files

Guideline: no comments in TS/TSX. Remove these inline comments.

As per coding guidelines

-          {/* small control bar with Transfer toggle */}
           <div className="tw-mt-3 tw-flex tw-justify-end">
             <TransferToggle />
           </div>
@@
-            {/* appears only when transfer is enabled */}
             <TransferPanel />

Also applies to: 488-488

components/user/collected/transfer/TransferPanel.tsx (1)

14-17: Remove unused helper

keyToLabel is unused. Delete to avoid dead code.

-  const keyToLabel = (key: string) => {
-    const [collection, tokenId] = key.split(":");
-    return `${collection} #${tokenId}`;
-  };
components/user/collected/cards/UserPageCollectedCard.tsx (3)

131-144: Add visible focus styles for keyboard users on the selectable wrapper

Improve accessibility by adding focus-visible ring to the role="button" wrapper.

-      <div
-        className="tw-no-underline"
+      <div
+        className="tw-no-underline tw-outline-none focus:tw-ring-2 focus:tw-ring-emerald-400/60"
         role="button"
         tabIndex={0}

59-63: Improve image a11y and performance

Use a descriptive alt and enable lazy loading.

-            <img
-              src={card.img}
-              alt={card.collection}
-              className="tw-bg-transparent tw-max-w-full tw-max-h-full tw-h-auto tw-w-auto tw-mx-auto tw-object-contain"
-            />
+            <img
+              src={card.img}
+              alt={`${collectionMeta.label} #${card.token_id} — ${card.token_name}`}
+              loading="lazy"
+              decoding="async"
+              className="tw-bg-transparent tw-max-w-full tw-max-h-full tw-h-auto tw-w-auto tw-mx-auto tw-object-contain"
+            />

Optional: consider next/image for optimization if compatible with your image sources.


18-22: Make onToggle required in select mode via discriminated union props

Enforce at the type level that onToggle and selected are provided when interactiveMode is "select".

type BaseProps = {
  readonly card: CollectedCard;
  readonly showDataRow: boolean;
  readonly copiesMax?: number;
  readonly qtySelected?: number;
};

type LinkProps = BaseProps & {
  readonly interactiveMode?: "link";
};

type SelectProps = BaseProps & {
  readonly interactiveMode: "select";
  readonly selected: boolean;
  readonly onToggle: () => void;
};

export default function UserPageCollectedCard(props: LinkProps | SelectProps) {
  // narrow with props.interactiveMode === 'select'
}

As per coding guidelines

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d92c95 and 31a8ad5.

📒 Files selected for processing (7)
  • components/user/collected/UserPageCollected.tsx (3 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
  • components/user/collected/cards/UserPageCollectedCards.tsx (2 hunks)
  • components/user/collected/transfer/TransferPanel.tsx (1 hunks)
  • components/user/collected/transfer/TransferState.tsx (1 hunks)
  • components/user/collected/transfer/TransferToggle.tsx (1 hunks)
  • services/auth/auth.utils.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • services/auth/auth.utils.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • components/user/collected/transfer/TransferState.tsx
  • components/user/collected/transfer/TransferToggle.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/cards/UserPageCollectedCards.tsx
  • components/user/collected/transfer/TransferPanel.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • components/user/collected/transfer/TransferState.tsx
  • components/user/collected/transfer/TransferToggle.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/cards/UserPageCollectedCards.tsx
  • components/user/collected/transfer/TransferPanel.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
🧬 Code graph analysis (5)
components/user/collected/transfer/TransferToggle.tsx (1)
components/user/collected/transfer/TransferState.tsx (1)
  • useTransfer (157-161)
components/user/collected/UserPageCollected.tsx (4)
components/user/collected/transfer/TransferState.tsx (1)
  • TransferProvider (45-155)
components/user/collected/transfer/TransferToggle.tsx (1)
  • TransferToggle (5-23)
components/user/collected/cards/UserPageCollectedCards.tsx (1)
  • UserPageCollectedCards (9-83)
components/user/collected/transfer/TransferPanel.tsx (1)
  • TransferPanel (8-128)
components/user/collected/cards/UserPageCollectedCards.tsx (2)
components/user/collected/transfer/TransferState.tsx (2)
  • useTransfer (157-161)
  • buildTransferKey (164-175)
components/user/collected/cards/UserPageCollectedCard.tsx (1)
  • UserPageCollectedCard (6-154)
components/user/collected/transfer/TransferPanel.tsx (1)
components/user/collected/transfer/TransferState.tsx (1)
  • useTransfer (157-161)
components/user/collected/cards/UserPageCollectedCard.tsx (2)
entities/IProfile.ts (1)
  • CollectedCard (382-391)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (117-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
components/user/collected/cards/UserPageCollectedCards.tsx (1)

24-65: Transfer-state wiring looks good

Clean integration: stable key, selected/qty derivation, and responsive grid are correct.

Comment thread components/user/collected/cards/UserPageCollectedCard.tsx Outdated
Comment thread components/user/collected/cards/UserPageCollectedCard.tsx
Comment thread components/user/collected/cards/UserPageCollectedCard.tsx Outdated
Comment thread components/user/collected/transfer/TransferPanel.tsx Outdated
Comment thread components/user/collected/transfer/TransferToggle.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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: 9

Caution

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

⚠️ Outside diff range comments (1)
app/[user]/_lib/userTabPageFactory.tsx (1)

14-21: Add readonly before props per coding guidelines.

The coding guidelines state "Always add readonly before props" for TypeScript files.
As per coding guidelines.

Apply this diff:

-type TabProps = { profile: ApiIdentity };
+type TabProps = { readonly profile: ApiIdentity };

 type FactoryArgs = {
-  subroute: string;
-  metaLabel: string;
-  Tab: (props: TabProps) => React.JSX.Element;
-  enableTransfer?: boolean;
+  readonly subroute: string;
+  readonly metaLabel: string;
+  readonly Tab: (props: TabProps) => React.JSX.Element;
+  readonly enableTransfer?: boolean;
 };
♻️ Duplicate comments (6)
components/user/collected/transfer/TransferToggle.tsx (1)

29-49: Restore the FontAwesome toggle icon and expose pressed state

The toggle still renders a raw ⇄ glyph and lacks aria-pressed, violating our TSX guidelines (FontAwesome only, accessible state). Please reinstate the FontAwesome import/usage and bind aria-pressed={t.enabled} so assistive tech reads the toggle correctly.

 import { useEffect, useRef } from "react";
 import { useTransfer } from "./TransferState";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faRightLeft } from "@fortawesome/free-solid-svg-icons";
@@
-    <button
-      type="button"
-      onClick={() => {
+    <button
+      type="button"
+      aria-pressed={t.enabled}
+      onClick={() => {
@@
-      <span aria-hidden>⇄</span>
+      <FontAwesomeIcon
+        icon={faRightLeft}
+        aria-hidden="true"
+        className="tw-h-4 tw-w-4"
+      />
components/user/collected/transfer/TransferPanel.tsx (1)

84-114: Swap text glyphs for FontAwesome icons in quantity & remove controls

Per the repo rule, we must not ship raw “-”, “+”, or “×” glyphs. The quantity stepper and remove button need FontAwesome icons (and we already import that library elsewhere). Please update all three controls accordingly.

-import { useEffect, useState } from "react";
-import TransferModal from "./TransferModal";
-import { useTransfer } from "./TransferState";
+import { useEffect, useState } from "react";
+import TransferModal from "./TransferModal";
+import { useTransfer } from "./TransferState";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+  faMinus,
+  faPlus,
+  faXmark,
+} from "@fortawesome/free-solid-svg-icons";
@@
-                      <button
+                      <button
                         type="button"
                         className="tw-inline-flex tw-items-center tw-justify-center tw-h-6 tw-w-6 tw-rounded-full tw-bg-white tw-text-black tw-font-medium hover:tw-bg-[#ddd] tw-text-lg tw-p-0 tw-border-0 disabled:tw-opacity-50 disabled:tw-cursor-not-allowed"
                         onClick={() => t.decQty(it.key)}
                         disabled={qty <= 1}
                         aria-label="Decrease">
-                        -
+                        <FontAwesomeIcon icon={faMinus} aria-hidden="true" />
                       </button>
@@
-                      <button
+                      <button
                         type="button"
                         className="tw-inline-flex tw-items-center tw-justify-center tw-h-6 tw-w-6 tw-rounded-full tw-bg-white tw-text-black tw-font-medium hover:tw-bg-[#ddd] tw-text-lg tw-p-0 tw-border-0 disabled:tw-opacity-50 disabled:tw-cursor-not-allowed"
                         onClick={() => t.incQty(it.key)}
                         disabled={qty >= max}
                         aria-label="Increase">
-                        +
+                        <FontAwesomeIcon icon={faPlus} aria-hidden="true" />
                       </button>
@@
-                  <button
+                  <button
                     type="button"
                     className="tw-inline-flex tw-items-center tw-justify-center tw-h-6 tw-w-6 tw-rounded-full tw-bg-[#ef4444] tw-font-medium tw-text-white hover:tw-bg-[#d92b2b] tw-text-lg tw-p-0 tw-border-0"
                     onClick={() => t.unselect(it.key)}
                     aria-label="Remove">
-                    &times;
+                    <FontAwesomeIcon icon={faXmark} aria-hidden="true" />
                   </button>
components/user/collected/cards/UserPageCollectedCards.tsx (1)

51-80: Coalesce seized_count passed to the formatter

card.seized_count is number | null, so the current call violates the formatter signature and can crash when the value is null. Coalesce before passing it in.

-              const max = Math.max(1, Number(card.seized_count ?? 1));
+              const max = Math.max(1, Number(card.seized_count ?? 1));
@@
-                  copiesMax={max}
+                  copiesMax={max}
components/user/collected/cards/UserPageCollectedCard.tsx (3)

49-134: Fix checkbox toggle bugs & align with Tailwind prefix

Clicking the checkbox fires twice (wrapper onClick + checkbox bubbling) and the classes ignore our tw- prefix. Drop onSelect, stop propagation on the checkbox/label, and use the tw- utilities so selection works.

-          {interactiveMode === "select" && (
+          {interactiveMode === "select" && (
             <div className="tw-pt-2 tw-flex tw-items-center tw-justify-center tw-gap-x-2">
               <input
                 checked={selected}
                 id={`${card.collection}-${card.token_id}`}
                 type="checkbox"
-                className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
-                onSelect={onToggle}
-                onChange={onToggle}
+                className="tw-w-4 tw-h-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded-sm focus:tw-ring-2 focus:tw-ring-blue-500 dark:tw-focus:tw-ring-blue-600 dark:tw-ring-offset-gray-800 dark:tw-bg-gray-700 dark:tw-border-gray-600"
+                onChange={onToggle}
+                onClick={(e) => e.stopPropagation()}
               />
-              {contractType === ContractType.ERC1155 ? (
-                <span className="tw-text-sm tw-font-medium">
+              {contractType === ContractType.ERC1155 ? (
+                <label
+                  htmlFor={`${card.collection}-${card.token_id}`}
+                  className="tw-text-sm tw-font-medium"
+                  onClick={(e) => e.stopPropagation()}>
                   {selected
                     ? `Selected ${qtySelected} / ${copiesMax}`
                     : copiesMax > 1
                     ? `Select (up to ${copiesMax})`
                     : "Select"}
-                </span>
+                </label>
               ) : (
-                <span className="tw-text-sm tw-font-medium">
-                  {selected ? "Selected" : "Select"}
-                </span>
+                <label
+                  htmlFor={`${card.collection}-${card.token_id}`}
+                  className="tw-text-sm tw-font-medium"
+                  onClick={(e) => e.stopPropagation()}>
+                  {selected ? "Selected" : "Select"}
+                </label>
               )}
             </div>
           )}

81-87: Pass a number to formatNumberWithCommasOrDash

card.seized_count can be null; the helper expects a number and will misbehave. Coalesce before formatting.

-              <span className="tw-text-sm min-[1200px]:tw-text-md tw-font-medium tw-text-iron-400">
-                {formatNumberWithCommasOrDash(card.seized_count)}x
-              </span>
+              <span className="tw-text-sm min-[1200px]:tw-text-md tw-font-medium tw-text-iron-400">
+                {formatNumberWithCommasOrDash(card.seized_count ?? 0)}x
+              </span>

49-147: Remove inline comments per TSX guideline

Lines like // shared card body violate the “no comments in TS/TSX” rule. Delete the inline comments; rely on descriptive naming instead.

🧹 Nitpick comments (8)
constants.ts (1)

7-7: Remove commented-out code.

Commented-out code should be removed rather than left in the codebase. Version control preserves the history if needed.

Apply this diff:

-// const MANIFOLD_PROXY = "0x26bbea7803dcac346d5f5f135b57cf2c752a02be";
entities/IProfile.ts (1)

387-395: Use ContractType instead of string for stronger type safety.

The value type should be ContractType rather than string to leverage the enum and catch type errors at compile time.

Apply this diff:

 export const COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE: Record<
   CollectedCollectionType,
-  string
+  ContractType
 > = {
   [CollectedCollectionType.MEMES]: ContractType.ERC1155,
   [CollectedCollectionType.NEXTGEN]: ContractType.ERC721,
   [CollectedCollectionType.GRADIENTS]: ContractType.ERC721,
   [CollectedCollectionType.MEMELAB]: ContractType.ERC1155,
 };
components/user/collected/transfer/TransferModalPfp.tsx (1)

16-21: Consider handling stale updates from async IPFS resolution.

If the src prop changes while the previous async resolveIpfsUrl call is in flight, the state update from the old call could overwrite the newer resolution. While unlikely to cause issues in practice for this use case, consider tracking whether the effect is still current.

Example pattern:

 useEffect(() => {
+  let cancelled = false;
   (async () => {
     const newSrc = await resolveIpfsUrl(src);
-    setResolved(newSrc);
+    if (!cancelled) setResolved(newSrc);
   })();
+  return () => { cancelled = true; };
 }, [src]);
components/user/collected/transfer/TransferModal.tsx (5)

311-318: Remove any-cast “walletClientLocal” shim; use walletClient directly

The extra destructuring via any is unnecessary and brittle. Use walletClient as returned by useWalletClient.

-      const { data: walletClientLocal } = { data: walletClient } as any;
-
-      if (!walletClientLocal) {
+      if (!walletClient) {
         setErrorMsg("Wallet not ready. Please reconnect.");
         setFlow("error");
         setRetryable(true);
         return;
       }
-          const hash = await walletClientLocal.writeContract(request);
+          const hash = await walletClient.writeContract(request);
-            const hash = await walletClientLocal.writeContract(request);
+            const hash = await walletClient.writeContract(request);

Also applies to: 340-344, 358-363


370-377: Wait for receipts in parallel to improve UX

Waiting sequentially extends total wait time. Use Promise.all.

-      // Wait for all receipts
-      for (const h of hashes) {
-        await publicClient.waitForTransactionReceipt({
-          hash: h.hash as `0x${string}`,
-        });
-      }
+      await Promise.all(
+        hashes.map((h) =>
+          publicClient.waitForTransactionReceipt({
+            hash: h.hash as `0x${string}`,
+          })
+        )
+      );

378-392: Retryable detection can be stale due to state read

Using txHashes.length from state inside catch may not reflect hashes produced earlier in the try. Prefer deriving from local progress (e.g., track a boolean when at least one write returns) or move hashes declaration outside try/catch.

If you want to verify current behavior, add a temporary console trace around the writeContract calls and the catch to confirm whether txHashes is still 0 when an error occurs after some writes.


697-713: Optional: dedupe block explorer link rendering

The three list renderings for submitted/success/error are nearly identical. Consider extracting a small helper to render the list to reduce duplication.

Also applies to: 715-737, 738-759


404-443: Optional: Add Escape-to-close to improve accessibility

Handle Escape key to close when allowed (not during wallet/submitted).

useEffect(() => {
  if (!open) return;
  const onKey = (e: KeyboardEvent) => {
    if (e.key === "Escape" && flow !== "wallet" && flow !== "submitted") handleClose();
  };
  window.addEventListener("keydown", onKey);
  return () => window.removeEventListener("keydown", onKey);
}, [open, flow, handleClose]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31a8ad5 and 974c050.

📒 Files selected for processing (14)
  • app/[user]/_lib/userTabPageFactory.tsx (3 hunks)
  • app/[user]/collected/page.tsx (1 hunks)
  • components/user/collected/UserPageCollected.tsx (9 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
  • components/user/collected/cards/UserPageCollectedCards.tsx (2 hunks)
  • components/user/collected/transfer/TransferModal.tsx (1 hunks)
  • components/user/collected/transfer/TransferModalPfp.tsx (1 hunks)
  • components/user/collected/transfer/TransferPanel.tsx (1 hunks)
  • components/user/collected/transfer/TransferState.tsx (1 hunks)
  • components/user/collected/transfer/TransferToggle.tsx (1 hunks)
  • constants.ts (1 hunks)
  • entities/IProfile.ts (2 hunks)
  • enums.ts (1 hunks)
  • next.config.mjs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • app/[user]/collected/page.tsx
  • components/user/collected/cards/UserPageCollectedCards.tsx
  • entities/IProfile.ts
  • components/user/collected/transfer/TransferModal.tsx
  • enums.ts
  • app/[user]/_lib/userTabPageFactory.tsx
  • components/user/collected/transfer/TransferPanel.tsx
  • constants.ts
  • components/user/collected/transfer/TransferModalPfp.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/transfer/TransferToggle.tsx
  • components/user/collected/transfer/TransferState.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • app/[user]/collected/page.tsx
  • components/user/collected/cards/UserPageCollectedCards.tsx
  • components/user/collected/transfer/TransferModal.tsx
  • app/[user]/_lib/userTabPageFactory.tsx
  • components/user/collected/transfer/TransferPanel.tsx
  • components/user/collected/transfer/TransferModalPfp.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/transfer/TransferToggle.tsx
  • components/user/collected/transfer/TransferState.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
{app,pages}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use NextJS features that match the current version

Files:

  • app/[user]/collected/page.tsx
  • app/[user]/_lib/userTabPageFactory.tsx
app/**

📄 CodeRabbit inference engine (AGENTS.md)

All new Next.js pages must be created under the app/ directory

Files:

  • app/[user]/collected/page.tsx
  • app/[user]/_lib/userTabPageFactory.tsx
app/**/{page,layout}.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Routes in app/ should export a generateMetadata function using getAppMetadata

Files:

  • app/[user]/collected/page.tsx
🧬 Code graph analysis (9)
components/user/collected/cards/UserPageCollectedCards.tsx (3)
components/user/collected/transfer/TransferState.tsx (2)
  • useTransfer (158-162)
  • buildTransferKey (165-176)
components/user/collected/cards/UserPageCollectedCard.tsx (1)
  • UserPageCollectedCard (7-160)
entities/IProfile.ts (2)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE (387-395)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT (377-385)
entities/IProfile.ts (1)
constants.ts (4)
  • MEMES_CONTRACT (5-5)
  • NEXTGEN_CONTRACT (6-6)
  • GRADIENT_CONTRACT (10-10)
  • MEMELAB_CONTRACT (11-11)
components/user/collected/transfer/TransferModal.tsx (5)
components/user/collected/transfer/TransferState.tsx (1)
  • useTransfer (158-162)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/user/collected/transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (7-36)
app/[user]/_lib/userTabPageFactory.tsx (2)
components/user/collected/transfer/TransferState.tsx (1)
  • TransferProvider (46-156)
components/user/layout/UserPageLayout.tsx (1)
  • UserPageLayout (17-73)
components/user/collected/transfer/TransferPanel.tsx (3)
components/user/collected/transfer/TransferState.tsx (1)
  • useTransfer (158-162)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/user/collected/transfer/TransferModal.tsx (1)
  • TransferModal (53-814)
components/user/collected/transfer/TransferModalPfp.tsx (1)
components/ipfs/IPFSContext.tsx (1)
  • resolveIpfsUrl (67-77)
components/user/collected/UserPageCollected.tsx (7)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/user/collected/transfer/TransferState.tsx (1)
  • useTransfer (158-162)
components/user/collected/transfer/TransferToggle.tsx (1)
  • TransferToggle (7-52)
components/user/collected/cards/UserPageCollectedCards.tsx (1)
  • UserPageCollectedCards (14-99)
components/user/collected/transfer/TransferPanel.tsx (1)
  • TransferPanel (9-154)
components/user/collected/transfer/TransferToggle.tsx (2)
components/user/collected/transfer/TransferState.tsx (1)
  • useTransfer (158-162)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/user/collected/cards/UserPageCollectedCard.tsx (2)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (117-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (13)
constants.ts (1)

11-14: LGTM!

The new exported constants are correctly formatted and will support the transfer functionality introduced in this PR.

components/user/collected/transfer/TransferState.tsx (5)

6-15: LGTM!

The TransferItem type is well-structured with appropriate optional fields for transfer metadata.


42-44: LGTM!

The clamp utility is correctly implemented and will ensure quantity values stay within bounds.


52-151: LGTM!

The transfer state management API is comprehensive and correctly implemented:

  • Selection state uses immutable Map updates
  • Quantity operations properly clamp to [1, max]
  • Max defaults to at least 1 to prevent division by zero or invalid ranges
  • Memoization on [enabled, selected] is appropriate

158-162: LGTM!

The hook correctly enforces usage within a TransferProvider by throwing an error when context is null.


164-176: LGTM!

The key-building logic handles null/undefined values appropriately and provides stable keys for the transfer state.

app/[user]/collected/page.tsx (1)

8-8: LGTM!

Enabling transfer functionality for the Collected page is straightforward and aligns with the broader transfer feature set introduced in this PR.

next.config.mjs (1)

123-123: LGTM!

Adding the IPFS domain to the image optimization whitelist enables rendering of IPFS-hosted assets in the transfer UI components.

enums.ts (1)

189-192: LGTM!

The ContractType enum provides type-safe references to the two token standards used in the transfer workflow.

entities/IProfile.ts (2)

1-7: LGTM!

The import updates correctly bring in the new contract constants and ContractType enum needed for the mappings.


377-385: LGTM!

The mapping from collection types to contract addresses is correctly implemented and aligns with the constants defined in constants.ts.

app/[user]/_lib/userTabPageFactory.tsx (1)

60-68: LGTM!

The conditional rendering logic correctly wraps the Tab component with TransferProvider when transfer functionality is enabled.

components/user/collected/transfer/TransferModalPfp.tsx (1)

23-35: LGTM!

The loading placeholder and image rendering logic is correctly implemented, providing a smooth user experience during IPFS URL resolution.

Comment thread components/user/collected/transfer/TransferModal.tsx Outdated
Comment thread components/nft-transfer/TransferModal.tsx
Comment thread components/user/collected/transfer/TransferModal.tsx Outdated
Comment thread components/nft-transfer/TransferModal.tsx
Comment thread components/nft-transfer/TransferModal.tsx Outdated
Comment thread components/user/collected/transfer/TransferModal.tsx Outdated
Comment thread components/user/collected/transfer/TransferModalPfp.tsx Outdated
Comment thread components/user/collected/transfer/TransferPanel.tsx
Comment thread components/user/collected/UserPageCollected.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
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: 7

Caution

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

⚠️ Outside diff range comments (1)
components/user/collected/cards/UserPageCollectedCard.tsx (1)

45-51: Fix rank display condition (checks wrong field).

Use rank to decide rendering, not tdh.

   const getRankDisplay = () => {
     if (card.collection === CollectedCollectionType.MEMELAB) {
       return "N/A";
     } else {
-      return card.tdh ? formatNumberWithCommasOrDash(card.rank ?? 0) : "-";
+      return card.rank != null ? formatNumberWithCommasOrDash(card.rank) : "-";
     }
   };
♻️ Duplicate comments (7)
components/nft-transfer/TransferModal.tsx (3)

534-540: Fix close control semantics (button, not SVG) and remove invalid prop

Wrap the icon in a button for keyboard accessibility; FontAwesomeIcon doesn’t accept type="button".

-          {(flow === "review" || flow === "success" || flow === "error") && (
-            <FontAwesomeIcon
-              icon={faXmarkCircle}
-              type="button"
-              onClick={handleClose}
-              size="xl"
-            />
-          )}
+          {(flow === "review" || flow === "success" || flow === "error") && (
+            <button
+              type="button"
+              aria-label="Close"
+              onClick={handleClose}
+              className="tw-text-white hover:tw-text-white/80"
+            >
+              <FontAwesomeIcon icon={faXmarkCircle} size="xl" />
+            </button>
+          )}

55-61: Make props readonly to match codebase guidelines

Props must be immutable. Update the signature.

-export default function TransferModal({
-  open,
-  onClose,
-}: {
-  open: boolean;
-  onClose: (opts?: { completed?: boolean }) => void;
-}) {
+export default function TransferModal(
+  { open, onClose }: Readonly<{
+    open: boolean;
+    onClose: (opts?: { completed?: boolean }) => void;
+  }>
+) {

280-287: Guard against missing destination (selectedWallet) at confirm

Avoid sending requests without a recipient; show a clear error.

   const handleConfirm = useCallback(async () => {
-    if (!publicClient || !address) {
+    if (!publicClient || !address) {
       setErrorMsg("Client not ready. Please reconnect.");
       setFlow("error");
       setRetryable(true);
       return;
     }
+    if (!selectedWallet) {
+      setErrorMsg("Please select a destination wallet.");
+      setFlow("error");
+      setRetryable(true);
+      return;
+    }
components/user/collected/UserPageCollected.tsx (1)

242-271: Guard address forcing to avoid redundant router.replace loops

Only replace when the target differs from the current URL to prevent re-render loops.

     if (transferEnabled) {
       if (!hadForcedRef.current) {
         previousAddressRef.current = currentParamAddress;
       }
       hadForcedRef.current = true;
 
-      // Force to connected wallet
-      updateFields([
-        { name: "address", value: connected },
-        { name: "page", value: "1" },
-      ]);
+      if (currentParamAddress !== connected) {
+        updateFields([
+          { name: "address", value: connected },
+          { name: "page", value: "1" },
+        ]);
+      }
     } else if (hadForcedRef.current) {
       const restore = previousAddressRef.current;
       previousAddressRef.current = null;
       hadForcedRef.current = false;
 
-      updateFields([
-        { name: "address", value: restore },
-        { name: "page", value: "1" },
-      ]);
+      if (restore !== currentParamAddress) {
+        updateFields([
+          { name: "address", value: restore },
+          { name: "page", value: "1" },
+        ]);
+      }
     }
components/user/collected/cards/UserPageCollectedCard.tsx (3)

87-91: Type-safety: coalesce seized_count before formatting.

Avoid passing number | null to a formatter expecting number.

-                {formatNumberWithCommasOrDash(card.seized_count)}x
+                {formatNumberWithCommasOrDash(card.seized_count ?? 0)}x

As per coding guidelines


112-129: Checkbox: add onChange, stopPropagation, and align Tailwind prefix.

Prevents React controlled-input warning and bubbling; also standardize to tw- classes and use a label for a11y.

-              <input
-                checked={selected}
-                id={`${card.collection}-${card.token_id}`}
-                type="checkbox"
-                className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
-              />
+              <input
+                checked={selected}
+                id={`${card.collection}-${card.token_id}`}
+                type="checkbox"
+                className="tw-w-4 tw-h-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded-sm focus:tw-ring-2 focus:tw-ring-blue-500 dark:tw-focus:tw-ring-blue-600 dark:tw-ring-offset-gray-800 dark:tw-bg-gray-700 dark:tw-border-gray-600"
+                onChange={onToggle}
+                onClick={(e) => e.stopPropagation()}
+              />
               {contractType === ContractType.ERC1155 ? (
                 <>
-                  <span className="tw-text-sm tw-font-medium">
+                  <label
+                    htmlFor={`${card.collection}-${card.token_id}`}
+                    className="tw-text-sm tw-font-medium"
+                    onClick={(e) => e.stopPropagation()}
+                  >
                     {selected
                       ? `Selected ${
                           copiesMax === 1 ? `${qtySelected} / ${copiesMax}` : ""
                         }`
                       : copiesMax > 1
                       ? `Select (up to ${copiesMax})`
                       : "Select"}
-                  </span>
+                  </label>
                 </>
               ) : (
-                <span className="tw-text-sm tw-font-medium">
+                <label
+                  htmlFor={`${card.collection}-${card.token_id}`}
+                  className="tw-text-sm tw-font-medium"
+                  onClick={(e) => e.stopPropagation()}
+                >
                   {selected ? "Selected" : "Select"}
-                </span>
+                </label>
               )}

As per coding guidelines

Also applies to: 161-166


53-55: Remove inline TSX comment.

TS/TSX files should not contain code comments.

-  // shared card body

As per coding guidelines

🧹 Nitpick comments (5)
components/nft-transfer/TransferModalPfp.tsx (1)

47-53: Consider adding error handling for Image loading failures.

The Next.js Image component may fail to load due to network issues, invalid URLs, or CORS problems. Consider adding error handling to gracefully fallback to the placeholder or show an error state.

You can add an onError handler to the Image component:

const [imageError, setImageError] = useState(false);

// In the render:
{(!resolved || imageError) ? (
  // placeholder render
) : (
  <Image
    src={resolved}
    alt={alt ?? ""}
    width={size}
    height={size}
    className="tw-rounded-full tw-object-cover"
    onError={() => setImageError(true)}
  />
)}
components/nft-transfer/TransferModal.tsx (3)

131-167: Use react-query for recipient search (per project guideline)

Replace manual fetch/debounce with react-query (caching, retries, cancelation).

Example pattern (adapt to local QueryKey):

const q = query.trim().toLowerCase();
const { data: searchResults = [], isFetching: isSearching } = useQuery({
  queryKey: ["community-members", q],
  queryFn: async () =>
    q
      ? await (await fetch(`https://api.6529.io/api/community-members?param=${encodeURIComponent(q)}`)).json()
      : [],
  enabled: open && q.length > 0,
  staleTime: 30_000,
  gcTime: 5 * 60_000,
});
useEffect(() => {
  if (!open) return;
  setSelectedProfile(null);
  setSelectedWallet(null);
  setResults(searchResults);
}, [open, searchResults]);

As per coding guidelines


376-383: Remove unnecessary walletClientLocal indirection

Use walletClient directly; simplifies typing and intent.

-      const { data: walletClientLocal } = { data: walletClient } as any;
-
-      if (!walletClientLocal) {
+      if (!walletClient) {
         setErrorMsg("Wallet not ready. Please reconnect.");
         setFlow("error");
         setRetryable(true);
         return;
       }
-          const hash = await walletClientLocal.writeContract(request);
+          const hash = await walletClient.writeContract(request);
-            const hash = await walletClientLocal.writeContract(request);
+            const hash = await walletClient.writeContract(request);

Also applies to: 405-405, 423-423


435-441: Wait for receipts concurrently to reduce total time

Parallelize waits for better UX.

-      for (const h of hashes) {
-        await publicClient.waitForTransactionReceipt({
-          hash: h.hash as `0x${string}`,
-        });
-      }
-
-      setFlow("success");
+      await Promise.all(
+        hashes.map((h) =>
+          publicClient.waitForTransactionReceipt({
+            hash: h.hash as `0x${string}`,
+          })
+        )
+      );
+      setFlow("success");
components/nft-transfer/TransferToggle.tsx (1)

27-47: Optional: add aria-pressed for toggle state

Improves accessibility by conveying pressed/on state.

-    <button
+    <button
       type="button"
+      aria-pressed={t.enabled}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 974c050 and 4e81eb0.

📒 Files selected for processing (10)
  • app/[user]/_lib/userTabPageFactory.tsx (3 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferModalPfp.tsx (1 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferState.tsx (1 hunks)
  • components/nft-transfer/TransferToggle.tsx (1 hunks)
  • components/user/collected/UserPageCollected.tsx (9 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
  • components/user/collected/cards/UserPageCollectedCards.tsx (2 hunks)
  • components/user/utils/level/UserLevel.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/[user]/_lib/userTabPageFactory.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/user/collected/cards/UserPageCollectedCards.tsx
  • components/nft-transfer/TransferState.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/nft-transfer/TransferPanel.tsx
  • components/user/utils/level/UserLevel.tsx
  • components/nft-transfer/TransferToggle.tsx
  • components/nft-transfer/TransferModalPfp.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/user/collected/cards/UserPageCollectedCards.tsx
  • components/nft-transfer/TransferState.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/nft-transfer/TransferPanel.tsx
  • components/user/utils/level/UserLevel.tsx
  • components/nft-transfer/TransferToggle.tsx
  • components/nft-transfer/TransferModalPfp.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (7)
components/user/collected/cards/UserPageCollectedCard.tsx (2)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (117-120)
components/user/collected/cards/UserPageCollectedCards.tsx (3)
components/nft-transfer/TransferState.tsx (2)
  • useTransfer (164-168)
  • buildTransferKey (170-181)
components/user/collected/cards/UserPageCollectedCard.tsx (1)
  • UserPageCollectedCard (7-197)
entities/IProfile.ts (2)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE (387-395)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT (377-385)
components/nft-transfer/TransferModal.tsx (5)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-60)
components/user/collected/UserPageCollected.tsx (7)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
components/nft-transfer/TransferToggle.tsx (1)
  • TransferToggle (9-49)
components/user/collected/cards/UserPageCollectedCards.tsx (1)
  • UserPageCollectedCards (17-104)
components/nft-transfer/TransferPanel.tsx (1)
  • TransferPanel (11-222)
components/nft-transfer/TransferPanel.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (55-895)
components/nft-transfer/TransferToggle.tsx (2)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModalPfp.tsx (1)
components/ipfs/IPFSContext.tsx (1)
  • resolveIpfsUrl (67-77)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
components/nft-transfer/TransferModalPfp.tsx (1)

7-11: LGTM!

The level-based color mapping is clear and uses appropriate thresholds for visual differentiation.

components/user/utils/level/UserLevel.tsx (1)

36-39: LGTM

No functional changes; adheres to readonly props and styling conventions.

components/nft-transfer/TransferToggle.tsx (1)

27-47: LGTM

Toggle logic is sound; integrates with connect flow and TransferState correctly.

components/user/collected/cards/UserPageCollectedCards.tsx (1)

32-37: LGTM

Transfer integration and per-card selection/qty wiring look correct.

Also applies to: 42-86

Comment thread components/nft-transfer/TransferModalPfp.tsx
Comment thread components/nft-transfer/TransferModalPfp.tsx Outdated
Comment thread components/nft-transfer/TransferModalPfp.tsx Outdated
Comment thread components/nft-transfer/TransferPanel.tsx Outdated
Comment thread components/nft-transfer/TransferState.tsx
Comment thread components/nft-transfer/TransferState.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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 (8)
components/user/collected/cards/UserPageCollectedCard.tsx (3)

55-55: Remove inline comment (regression from resolved issue)

This inline comment violates the repository guideline that TS/TSX files should not contain code comments. This was previously flagged and marked as resolved, but the comment has been reintroduced.

Apply this diff:

-  // shared card body
   const CardBody = (

As per coding guidelines


91-91: Type-safety: coalesce seized_count before formatting (regression)

card.seized_count is typed as number | null, but formatNumberWithCommasOrDash expects number. This type mismatch was previously flagged and marked resolved, but the fix appears to have been lost.

Apply this diff:

-                {formatNumberWithCommasOrDash(card.seized_count)}x
+                {formatNumberWithCommasOrDash(card.seized_count ?? 0)}x

118-118: Use "tw-" Tailwind prefix on checkbox className (regression)

The checkbox's className uses unprefixed Tailwind utilities (e.g., w-4, h-4), inconsistent with the rest of the codebase which uses the tw- prefix. This was previously flagged and marked resolved, but the fix appears to have been lost.

Apply this diff:

-                className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
+                className="tw-w-4 tw-h-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded-sm focus:tw-ring-2 focus:tw-ring-blue-500 dark:focus:tw-ring-blue-600 dark:tw-ring-offset-gray-800 dark:tw-bg-gray-700 dark:tw-border-gray-600"
components/nft-transfer/TransferPanel.tsx (2)

34-42: Remove inline comments from TSX

TSX must be comment-free per repo rules. Delete or move them to surrounding TS code/doc.

As per coding guidelines

Also applies to: 68-76, 71-81, 211-213


102-105: Replace invalid Tailwind class "tw-border-1" with "tw-border"

"tw-border-1" isn’t a default Tailwind class.

-              className="tw-text-sm tw-rounded-lg tw-bg-white tw-text-black tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]">
+              className="tw-text-sm tw-rounded-lg tw-bg-white tw-text-black tw-py-1 tw-border tw-border-solid tw-border-[#444]">
...
-            className="tw-flex-1 tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/20 tw-text-white tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]">
+            className="tw-flex-1 tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/20 tw-text-white tw-py-1 tw-border tw-border-solid tw-border-[#444]">
...
-            className="tw-flex-1 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border-1 tw-border-solid tw-border-[#444]">
+            className="tw-flex-1 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border tw-border-solid tw-border-[#444]">

As per coding guidelines

Also applies to: 198-205

components/nft-transfer/TransferModal.tsx (3)

56-62: Make props readonly

Apply readonly props per repo guideline.

-export default function TransferModal({
-  open,
-  onClose,
-}: {
-  open: boolean;
-  onClose: (opts?: { completed?: boolean }) => void;
-}) {
+export default function TransferModal(
+  { open, onClose }: Readonly<{
+    open: boolean;
+    onClose: (opts?: { completed?: boolean }) => void;
+  }>
+) {

As per coding guidelines


566-573: Fix close control semantics (wrap icon in a button, remove invalid prop)

FontAwesomeIcon doesn’t accept type="button" and isn’t focusable. Wrap it in a button.

-            {(flow === "review" || flow === "success" || flow === "error") && (
-              <FontAwesomeIcon
-                icon={faXmarkCircle}
-                type="button"
-                onClick={handleClose}
-                size="xl"
-              />
-            )}
+            {(flow === "review" || flow === "success" || flow === "error") && (
+              <button
+                type="button"
+                aria-label="Close"
+                onClick={handleClose}
+                className="tw-text-white hover:tw-text-white/80"
+              >
+                <FontAwesomeIcon icon={faXmarkCircle} size="xl" />
+              </button>
+            )}

288-294: Guard against missing selectedWallet in confirm path

Add a runtime check to prevent sending with null destination.

-  const handleConfirm = useCallback(async () => {
-    if (!publicClient || !address) {
-      setErrorMsg("Client not ready. Please reconnect.");
+  const handleConfirm = useCallback(async () => {
+    if (!publicClient || !address || !selectedWallet) {
+      setErrorMsg(!selectedWallet ? "Please select a destination wallet." : "Client not ready. Please reconnect.");
       setFlow("error");
       setRetryable(true);
       return;
     }
🧹 Nitpick comments (18)
components/user/collected/cards/UserPageCollectedCard.tsx (1)

123-130: Clean up trailing space in selection text

When copiesMax > 1 and the item is selected, the text renders as "Selected " with a trailing space because the template literal embeds an empty string. Consider removing the space or restructuring the conditional for cleaner output.

Apply this diff:

                   <span className="tw-text-sm tw-font-medium">
-                    {selected
-                      ? `Selected ${
-                          copiesMax === 1 ? `${qtySelected} / ${copiesMax}` : ""
-                        }`
-                      : copiesMax > 1
-                      ? `Select (up to ${copiesMax})`
-                      : "Select"}
+                    {selected ? (
+                      copiesMax === 1 ? `Selected ${qtySelected} / ${copiesMax}` : "Selected"
+                    ) : (
+                      copiesMax > 1 ? `Select (up to ${copiesMax})` : "Select"
+                    )}
                   </span>
__tests__/components/nft-transfer/TransferModalPfp.test.tsx (2)

1-9: Mock next/image to avoid Jest environment quirks

Without mocking next/image, tests can be flaky or fail under jsdom. Add a lightweight mock here.

Apply:

 import { render, screen, waitFor } from "@testing-library/react";
 
 import TransferModalPfp from "@/components/nft-transfer/TransferModalPfp";
 
 const mockResolveIpfsUrl = jest.fn();
 jest.mock("@/components/ipfs/IPFSContext", () => ({
   resolveIpfsUrl: (...args: unknown[]) => mockResolveIpfsUrl(...args),
 }));
+jest.mock("next/image", () => ({
+  __esModule: true,
+  default: ({ alt = "", src, ...rest }: any) => <img src={src} alt={alt} {...rest} />,
+}));

23-31: Also assert resolution call for stronger test

Validate the resolver is invoked with the provided IPFS URL.

   it("loads and displays the resolved image", async () => {
     mockResolveIpfsUrl.mockResolvedValue("https://cdn.test/pfp.png");
 
     render(<TransferModalPfp level={45} src="ipfs://hash" alt="Profile" />);
 
+    expect(mockResolveIpfsUrl).toHaveBeenCalledWith("ipfs://hash");
     await waitFor(() =>
       expect(screen.getByRole("img", { name: "Profile" })).toBeInTheDocument()
     );
   });
components/the-memes/MemePageYourCards.tsx (1)

226-244: Redundant contractType prop; ensure contract mapping matches key

TransferSingle derives contractType from collectionType internally and doesn’t use the passed contractType. Keeping it may confuse future readers. Consider removing this prop across component definition and all call sites in a follow-up.

Also, since the selection key uses the contract prop while the selected item’s contract uses the mapping, please verify MEMES mapping equals MEMES_CONTRACT to avoid key/contract divergence.

components/memelab/MemeLabPage.tsx (1)

685-701: Align contractType usage and verify mapping equals MEMES_CONTRACT

As with the other page, TransferSingle computes contractType from collectionType. Passing it is redundant. Consider simplifying the prop surface later. Also confirm the MEMES mapping address equals MEMES_CONTRACT so the key (built from contract) and the stored item contract remain consistent.

__tests__/components/nft-transfer/TransferPanel.test.tsx (1)

1-1: Prefer user-event over fireEvent

Use @testing-library/user-event to better simulate real user interactions (clicks respect disabled state).

-import { fireEvent, render, screen } from "@testing-library/react";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";

And replace fireEvent.click(...) with await userEvent.click(...) inside async tests.

__tests__/components/nft-transfer/TransferSingle.test.tsx (1)

147-159: Optional: prefer user-event for clicks

Use user-event for better fidelity.

-import { cleanup, fireEvent, render, screen } from "@testing-library/react";
+import { cleanup, render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
...
-  fireEvent.click(minus);
-  fireEvent.click(plus);
+  await userEvent.click(minus);
+  await userEvent.click(plus);
__tests__/components/nft-transfer/TransferToggle.test.tsx (1)

1-1: Prefer userEvent for realistic interactions in tests

Adopt @testing-library/user-event for clicks to align with testing best practices and repo guidelines.

- import { fireEvent, render, screen } from "@testing-library/react";
+ import { render, screen } from "@testing-library/react";
+ import userEvent from "@testing-library/user-event";
...
-  it("requests connection before enabling transfer", () => {
+  it("requests connection before enabling transfer", async () => {
+    const user = userEvent.setup();
...
-    fireEvent.click(screen.getByRole("button", { name: /transfer/i }));
+    await user.click(screen.getByRole("button", { name: /transfer/i }));
...
-  it("disables transfer and clears selections when toggled off", () => {
+  it("disables transfer and clears selections when toggled off", async () => {
+    const user = userEvent.setup();
...
-    fireEvent.click(screen.getByRole("button", { name: /exit transfer/i }));
+    await user.click(screen.getByRole("button", { name: /exit transfer/i }));

As per coding guidelines

Also applies to: 40-43, 67-70

__tests__/components/nft-transfer/TransferModal.test.tsx (2)

18-22: Fix mock shape for default exports

Return an object with __esModule and default to avoid ESM interop issues in Jest.

-jest.mock("@/components/nft-transfer/TransferModalPfp", () => {
-  const MockTransferModalPfp = () => <div data-testid="pfp" />;
-  MockTransferModalPfp.displayName = "MockTransferModalPfp";
-  return MockTransferModalPfp;
-});
+jest.mock("@/components/nft-transfer/TransferModalPfp", () => ({
+  __esModule: true,
+  default: () => <div data-testid="pfp" />,
+}));
...
-jest.mock("@/components/distribution-plan-tool/common/CircleLoader", () => {
-  const MockCircleLoader = () => <div data-testid="loader" />;
-  MockCircleLoader.displayName = "MockCircleLoader";
-  return MockCircleLoader;
-});
+jest.mock("@/components/distribution-plan-tool/common/CircleLoader", () => ({
+  __esModule: true,
+  default: () => <div data-testid="loader" />,
+}));

If your Jest config already handles synthetic default imports, confirm tests pass as-is; otherwise apply the change. Based on learnings

Also applies to: 23-27


1-7: Use userEvent for typing and clicks

Switch to @testing-library/user-event for input and button interactions.

-import {
-  act,
-  fireEvent,
-  render,
-  screen,
-  waitFor,
-} from "@testing-library/react";
+import { act, render, screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
...
-  async function selectRecipientFlow() {
+  async function selectRecipientFlow() {
+    const user = userEvent.setup();
...
-    const input = screen.getByPlaceholderText(/search by handle/i);
-    fireEvent.change(input, { target: { value: "rec" } });
+    const input = screen.getByPlaceholderText(/search by handle/i);
+    await user.type(input, "rec");
...
-    fireEvent.click(screen.getByRole("button", { name: /recipient/i }));
-    fireEvent.click(
+    await user.click(screen.getByRole("button", { name: /recipient/i }));
+    await user.click(
       screen.getByRole("button", { name: /recipient\s+0xrecipient/i })
     );
...
-    fireEvent.click(screen.getByRole("button", { name: /^transfer$/i }));
+    const user = userEvent.setup();
+    await user.click(screen.getByRole("button", { name: /^transfer$/i }));
...
-    fireEvent.click(screen.getByRole("button", { name: /^transfer$/i }));
+    const user = userEvent.setup();
+    await user.click(screen.getByRole("button", { name: /^transfer$/i }));

As per coding guidelines

Also applies to: 147-149, 157-161, 188-197, 204-210

components/nft-transfer/TransferPanel.tsx (1)

151-169: Use semantic buttons for +/- controls

Wrap icons in buttons for keyboard/a11y; keep icons inside.

-                      <FontAwesomeIcon
-                        icon={faMinusCircle}
-                        onClick={() => t.decQty(it.key)}
-                        className="tw-size-6 tw-cursor-pointer"
-                        color={qty <= 1 ? "#60606C" : "#fff"}
-                        aria-disabled={qty <= 1}
-                      />
+                      <button
+                        type="button"
+                        onClick={() => t.decQty(it.key)}
+                        disabled={qty <= 1}
+                        className="tw-inline-flex tw-items-center disabled:tw-opacity-60"
+                        aria-label="Decrease quantity">
+                        <FontAwesomeIcon
+                          icon={faMinusCircle}
+                          className="tw-size-6"
+                          color={qty <= 1 ? "#60606C" : "#fff"}
+                        />
+                      </button>
...
-                      <FontAwesomeIcon
-                        icon={faPlusCircle}
-                        onClick={() => t.incQty(it.key)}
-                        className="tw-size-6 tw-cursor-pointer"
-                        color={qty >= max ? "#60606C" : "#fff"}
-                        aria-disabled={qty >= max}
-                      />
+                      <button
+                        type="button"
+                        onClick={() => t.incQty(it.key)}
+                        disabled={qty >= max}
+                        className="tw-inline-flex tw-items-center disabled:tw-opacity-60"
+                        aria-label="Increase quantity">
+                        <FontAwesomeIcon
+                          icon={faPlusCircle}
+                          className="tw-size-6"
+                          color={qty >= max ? "#60606C" : "#fff"}
+                        />
+                      </button>
components/nft-transfer/TransferSingle.tsx (3)

107-111: Replace invalid Tailwind class "tw-border-1" with "tw-border"

Use Tailwind’s tw-border for 1px borders.

-          className="tw-w-full tw-py-2 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border-1 tw-border-solid tw-border-[#444] tw-text-lg tw-font-semibold"
+          className="tw-w-full tw-py-2 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border tw-border-solid tw-border-[#444] tw-text-lg tw-font-semibold"

As per coding guidelines


20-36: Align contract/contractType sources or remove unused props

Props include contract/contractType, but selection uses mappings from collectionType instead, while the key uses the contract prop. This can confuse readers and produce odd labels from key.

Options:

  • Use the contract/contractType props in t.select, or
  • Drop those props and derive both from collectionType consistently.

Example applying props in select:

-    t.select({
-      key,
-      contract: COLLECTED_COLLECTION_TYPE_TO_CONTRACT[collectionType],
-      contractType: COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE[
-        collectionType
-      ] as ContractType,
+    t.select({
+      key,
+      contract,
+      contractType,
       tokenId,
       max,
       thumbUrl,
       title,
     });

Also applies to: 48-60


80-100: Use semantic buttons for +/- controls

Mirror the a11y pattern used in the panel by wrapping icons in buttons.

components/nft-transfer/TransferModal.tsx (4)

727-735: Replace invalid Tailwind class "tw-border-1" with "tw-border"

Use Tailwind’s tw-border for 1px borders.

-                      className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]"
+                      className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border tw-border-solid tw-border-[#444]"
...
-                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">
...
-                className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
+                className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">

As per coding guidelines

Also applies to: 879-887


540-575: Remove inline comments from TSX

Delete JSX comments to comply with no-comments-in-TSX rule. Move notes to surrounding TS code or doc if needed.

As per coding guidelines

Also applies to: 577-581, 635-643, 801-805, 872-920


139-175: Prefer react-query for search instead of local fetch/debounce

Replace in-component fetch with a useQuery keyed by the query string (enabled when q length > 0). Use a debounced state or a custom hook to debounce q.

As per coding guidelines


384-391: Simplify wallet client handling

You already have walletClient from useWalletClient(); avoid re-wrapping to extract data again.

-      const { data: walletClientLocal } = { data: walletClient } as any;
-
-      if (!walletClientLocal) {
+      const walletClientLocal = walletClient;
+      if (!walletClientLocal) {
         setErrorMsg("Wallet not ready. Please reconnect.");
         setFlow("error");
         setRetryable(true);
         return;
       }

Also applies to: 413-417, 431-436

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e81eb0 and 18b5256.

📒 Files selected for processing (13)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferPanel.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferSingle.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferState.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferToggle.test.tsx (1 hunks)
  • components/memelab/MemeLabPage.tsx (3 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
  • components/the-memes/MemePageYourCards.tsx (2 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
  • styles/Home.module.scss (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • components/memelab/MemeLabPage.tsx
  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • components/nft-transfer/TransferPanel.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/the-memes/MemePageYourCards.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • components/nft-transfer/TransferSingle.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • components/memelab/MemeLabPage.tsx
  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • components/nft-transfer/TransferPanel.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/the-memes/MemePageYourCards.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • components/nft-transfer/TransferSingle.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

{**/__tests__/**,**/*.test.{ts,tsx}}: If coverage on a modified file is below 80%, add meaningful tests to raise it to at least 80%
Mock external dependencies and APIs in tests

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
**/__tests__/**

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in __tests__/ directories when organizing standalone test suites

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
**/*.test.tsx

📄 CodeRabbit inference engine (AGENTS.md)

When co-locating tests with components, name them ComponentName.test.tsx

Files:

  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (12)
__tests__/components/nft-transfer/TransferToggle.test.tsx (1)
components/nft-transfer/TransferToggle.tsx (1)
  • TransferToggle (9-49)
__tests__/components/nft-transfer/TransferModalPfp.test.tsx (1)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-60)
components/memelab/MemeLabPage.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-162)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (20-115)
constants.ts (1)
  • MEMES_CONTRACT (5-5)
components/nft-transfer/TransferModal.tsx (5)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-60)
__tests__/components/nft-transfer/TransferPanel.test.tsx (1)
components/nft-transfer/TransferPanel.tsx (1)
  • TransferPanel (16-224)
__tests__/components/nft-transfer/TransferSingle.test.tsx (2)
components/nft-transfer/TransferState.tsx (2)
  • buildTransferKey (170-181)
  • useTransfer (164-168)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (20-115)
components/nft-transfer/TransferPanel.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (56-924)
components/user/collected/cards/UserPageCollectedCard.tsx (2)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (117-120)
components/the-memes/MemePageYourCards.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-162)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (20-115)
constants.ts (1)
  • MEMES_CONTRACT (5-5)
__tests__/components/nft-transfer/TransferState.test.tsx (1)
components/nft-transfer/TransferState.tsx (3)
  • useTransfer (164-168)
  • TransferProvider (46-162)
  • buildTransferKey (170-181)
components/nft-transfer/TransferSingle.tsx (2)
components/nft-transfer/TransferState.tsx (2)
  • useTransfer (164-168)
  • buildTransferKey (170-181)
entities/IProfile.ts (2)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT (377-385)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE (387-395)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (56-924)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
styles/Home.module.scss (1)

161-173: New shadow container styling looks solid.

Matches existing theme variables and gives us a reusable dark card treatment. Nicely done.

__tests__/components/nft-transfer/TransferState.test.tsx (1)

15-22: Good coverage of initial state

Assertions match provider defaults and totals. Looks solid.

Comment thread __tests__/components/nft-transfer/TransferPanel.test.tsx Outdated
Comment thread __tests__/components/nft-transfer/TransferSingle.test.tsx Outdated
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: 10

♻️ Duplicate comments (5)
components/user/collected/cards/UserPageCollectedCard.tsx (2)

91-91: Coalesce seized_count to ensure type safety.

card.seized_count is number | null but formatNumberWithCommasOrDash expects number. Pass a coalesced value to maintain type safety.

Apply this diff:

-                {formatNumberWithCommasOrDash(card.seized_count)}x
+                {formatNumberWithCommasOrDash(card.seized_count ?? 0)}x

114-120: Apply tw- prefix to checkbox Tailwind classes.

The checkbox uses unprefixed Tailwind utilities (w-4 h-4 text-blue-600 bg-gray-100 etc.), which is inconsistent with the repository's Tailwind configuration requiring the tw- prefix.

Apply this diff:

               <input
                 checked={selected}
                 id={`${card.collection}-${card.token_id}`}
                 type="checkbox"
-                className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
+                className="tw-w-4 tw-h-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded-sm focus:tw-ring-blue-500 dark:focus:tw-ring-blue-600 dark:tw-ring-offset-gray-800 focus:tw-ring-2 dark:tw-bg-gray-700 dark:tw-border-gray-600"
                 readOnly
               />
components/nft-transfer/TransferPanel.tsx (1)

34-42: Remove inline comments from TS/TSX per repo rules.

No comments allowed in TS/TSX files. Delete these comment lines (and any others), or move explanations to variable names or separate docs.

As per coding guidelines

Also applies to: 57-61, 68-76, 78-82, 211-211

components/nft-transfer/TransferModal.tsx (2)

58-64: Make props readonly.

Props must be readonly per repo rules.

-export default function TransferModal({
-  open,
-  onClose,
-}: {
-  open: boolean;
-  onClose: (opts?: { completed?: boolean }) => void;
-}) {
+export default function TransferModal(
+  { open, onClose }: Readonly<{
+    open: boolean;
+    onClose: (opts?: { completed?: boolean }) => void;
+  }>
+) {

As per coding guidelines


580-585: Fix close control semantics (wrap icon in a button).

FontAwesomeIcon isn't a button and doesn't accept type. Wrap in a semantic button.

-              <FontAwesomeIcon
-                icon={faXmarkCircle}
-                type="button"
-                onClick={handleClose}
-                size="xl"
-              />
+              <button
+                type="button"
+                aria-label="Close"
+                onClick={handleClose}
+                className="tw-text-white hover:tw-text-white/80"
+              >
+                <FontAwesomeIcon icon={faXmarkCircle} size="xl" />
+              </button>
🧹 Nitpick comments (6)
components/the-memes/MemePageYourCards.tsx (1)

234-239: Optional: Remove redundant optional chaining.

After the guard at line 226, props.nft is guaranteed to exist and have an id. Optional chaining on lines 234, 237, and 239 is redundant.

-                          tokenId={props.nft?.id}
+                          tokenId={props.nft.id}
                           max={props.nftBalance}
                           title={
-                            props.nft?.name ?? `The Memes #${props.nft?.id}`
+                            props.nft.name ?? `The Memes #${props.nft.id}`
                           }
-                          thumbUrl={props.nft?.thumbnail}
+                          thumbUrl={props.nft.thumbnail}
components/memelab/MemeLabPage.tsx (1)

685-701: Optional: Remove redundant optional chaining.

Line 693 uses nft?.id but the outer condition on line 685 already ensures nft?.id is truthy, making the optional chaining redundant. While defensive programming is acceptable, you can simplify:

                 {nftBalance > 0 && nft?.id && (
                   <Row className="pt-5">
                     <Col>
                       <TransferProvider>
                         <TransferSingle
                           collectionType={CollectedCollectionType.MEMES}
                           contractType={ContractType.ERC1155}
                           contract={MEMES_CONTRACT}
-                          tokenId={nft?.id}
+                          tokenId={nft.id}
                           max={nftBalance}
                           title={nft?.name ?? `The Memes #${nft?.id}`}
                           thumbUrl={nft?.thumbnail}
                         />
                       </TransferProvider>
                     </Col>
                   </Row>
                 )}
__tests__/components/nft-transfer/TransferModal.test.tsx (1)

127-161: Ensure timer cleanup in selectRecipientFlow helper.

The selectRecipientFlow helper uses jest.useFakeTimers() (line 128) and jest.useRealTimers() (line 155). If an assertion fails between these calls, the test will exit without restoring real timers, potentially affecting subsequent tests.

While afterEach (line 115) includes cleanup, it's safer to use a try-finally block in the helper.

Apply this diff:

   async function selectRecipientFlow() {
     jest.useFakeTimers();
+    try {
+      (global.fetch as jest.Mock).mockResolvedValue({
+        ok: true,
+        json: jest.fn().mockResolvedValue([
+          {
+            profile_id: "1",
+            handle: "recipient",
+            display: "Recipient",
+            wallet: "0xrecipient",
+            level: 10,
+            tdh: 100,
+            pfp: null,
+          },
+        ]),
+      });

-    (global.fetch as jest.Mock).mockResolvedValue({
-      ok: true,
-      json: jest.fn().mockResolvedValue([
-        {
-          profile_id: "1",
-          handle: "recipient",
-          display: "Recipient",
-          wallet: "0xrecipient",
-          level: 10,
-          tdh: 100,
-          pfp: null,
-        },
-      ]),
-    });
-
-    openModal();
-
-    const input = screen.getByPlaceholderText(/search by handle/i);
-    fireEvent.change(input, { target: { value: "rec" } });
-
-    await act(async () => {
-      jest.advanceTimersByTime(400);
-    });
-
-    await waitFor(() => expect(global.fetch).toHaveBeenCalled());
-    jest.useRealTimers();
-
-    fireEvent.click(screen.getByRole("button", { name: /recipient/i }));
-    fireEvent.click(
-      screen.getByRole("button", { name: /recipient\s+0xrecipient/i })
-    );
+      openModal();
+
+      const input = screen.getByPlaceholderText(/search by handle/i);
+      fireEvent.change(input, { target: { value: "rec" } });
+
+      await act(async () => {
+        jest.advanceTimersByTime(400);
+      });
+
+      await waitFor(() => expect(global.fetch).toHaveBeenCalled());
+
+      fireEvent.click(screen.getByRole("button", { name: /recipient/i }));
+      fireEvent.click(
+        screen.getByRole("button", { name: /recipient\s+0xrecipient/i })
+      );
+    } finally {
+      jest.useRealTimers();
+    }
   }
components/nft-transfer/TransferPanel.tsx (1)

151-170: Make plus/minus controls keyboard-accessible.

Wrap FontAwesome icons in s with aria-label and disabled to support keyboard/a11y.

-                      <FontAwesomeIcon
-                        icon={faMinusCircle}
-                        onClick={() => t.decQty(it.key)}
-                        className="tw-size-6 tw-cursor-pointer"
-                        color={qty <= 1 ? "#60606C" : "#fff"}
-                        aria-disabled={qty <= 1}
-                      />
+                      <button
+                        type="button"
+                        onClick={() => t.decQty(it.key)}
+                        aria-label="Decrease quantity"
+                        disabled={qty <= 1}
+                        className="tw-inline-flex tw-items-center tw-justify-center disabled:tw-opacity-50"
+                      >
+                        <FontAwesomeIcon
+                          icon={faMinusCircle}
+                          className="tw-size-6"
+                          color={qty <= 1 ? "#60606C" : "#fff"}
+                        />
+                      </button>
...
-                      <FontAwesomeIcon
-                        icon={faPlusCircle}
-                        onClick={() => t.incQty(it.key)}
-                        className="tw-size-6 tw-cursor-pointer"
-                        color={qty >= max ? "#60606C" : "#fff"}
-                        aria-disabled={qty >= max}
-                      />
+                      <button
+                        type="button"
+                        onClick={() => t.incQty(it.key)}
+                        aria-label="Increase quantity"
+                        disabled={qty >= max}
+                        className="tw-inline-flex tw-items-center tw-justify-center disabled:tw-opacity-50"
+                      >
+                        <FontAwesomeIcon
+                          icon={faPlusCircle}
+                          className="tw-size-6"
+                          color={qty >= max ? "#60606C" : "#fff"}
+                        />
+                      </button>

components/nft-transfer/TransferSingle.tsx (1)

80-100: Make plus/minus controls keyboard-accessible.

Wrap icons in buttons with aria-label/disabled.

-          <FontAwesomeIcon
-            icon={faMinusCircle}
-            onClick={() => t.decQty(key)}
-            className="tw-size-6 tw-cursor-pointer"
-            color={selectedQty <= 1 ? "#60606C" : "#fff"}
-            aria-disabled={selectedQty <= 1}
-            data-testid="transfer-single-minus"
-          />
+          <button
+            type="button"
+            onClick={() => t.decQty(key)}
+            aria-label="Decrease quantity"
+            disabled={selectedQty <= 1}
+            className="tw-inline-flex tw-items-center tw-justify-center disabled:tw-opacity-50"
+            data-testid="transfer-single-minus"
+          >
+            <FontAwesomeIcon
+              icon={faMinusCircle}
+              className="tw-size-6"
+              color={selectedQty <= 1 ? "#60606C" : "#fff"}
+            />
+          </button>
...
-          <FontAwesomeIcon
-            icon={faPlusCircle}
-            onClick={() => t.incQty(key)}
-            className="tw-size-6 tw-cursor-pointer"
-            color={selectedQty >= max ? "#60606C" : "#fff"}
-            aria-disabled={selectedQty >= max}
-            data-testid="transfer-single-plus"
-          />
+          <button
+            type="button"
+            onClick={() => t.incQty(key)}
+            aria-label="Increase quantity"
+            disabled={selectedQty >= max}
+            className="tw-inline-flex tw-items-center tw-justify-center disabled:tw-opacity-50"
+            data-testid="transfer-single-plus"
+          >
+            <FontAwesomeIcon
+              icon={faPlusCircle}
+              className="tw-size-6"
+              color={selectedQty >= max ? "#60606C" : "#fff"}
+            />
+          </button>
components/nft-transfer/TransferModal.tsx (1)

148-185: Use react-query for search instead of manual fetch/debounce.

Replace the custom debounce/AbortController with a useQuery keyed by the query, with enabled: open && trimmedQuery.length >= MIN_SEARCH_LENGTH. Improves consistency and caching.

As per coding guidelines

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e81eb0 and e9f3511.

📒 Files selected for processing (14)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferPanel.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferSingle.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferState.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferToggle.test.tsx (1 hunks)
  • components/memelab/MemeLabPage.tsx (3 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferModalPfp.tsx (1 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
  • components/the-memes/MemePageYourCards.tsx (2 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
  • styles/Home.module.scss (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • styles/Home.module.scss
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/nft-transfer/TransferModalPfp.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • components/nft-transfer/TransferPanel.tsx
  • components/the-memes/MemePageYourCards.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • components/memelab/MemeLabPage.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • components/nft-transfer/TransferSingle.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • components/nft-transfer/TransferModal.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • components/nft-transfer/TransferPanel.tsx
  • components/the-memes/MemePageYourCards.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • components/memelab/MemeLabPage.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • components/nft-transfer/TransferSingle.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
  • components/nft-transfer/TransferModal.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

{**/__tests__/**,**/*.test.{ts,tsx}}: If coverage on a modified file is below 80%, add meaningful tests to raise it to at least 80%
Mock external dependencies and APIs in tests

Files:

  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
**/__tests__/**

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in __tests__/ directories when organizing standalone test suites

Files:

  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
**/*.test.tsx

📄 CodeRabbit inference engine (AGENTS.md)

When co-locating tests with components, name them ComponentName.test.tsx

Files:

  • __tests__/components/nft-transfer/TransferModalPfp.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/nft-transfer/TransferToggle.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferState.test.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (12)
components/nft-transfer/TransferPanel.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (58-941)
components/the-memes/MemePageYourCards.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-162)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (20-115)
constants.ts (1)
  • MEMES_CONTRACT (5-5)
components/user/collected/cards/UserPageCollectedCard.tsx (2)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (117-120)
__tests__/components/nft-transfer/TransferModalPfp.test.tsx (1)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
components/memelab/MemeLabPage.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-162)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (20-115)
constants.ts (1)
  • MEMES_CONTRACT (5-5)
__tests__/components/nft-transfer/TransferPanel.test.tsx (1)
components/nft-transfer/TransferPanel.tsx (1)
  • TransferPanel (16-224)
__tests__/components/nft-transfer/TransferSingle.test.tsx (2)
components/nft-transfer/TransferState.tsx (2)
  • buildTransferKey (170-181)
  • useTransfer (164-168)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (20-115)
__tests__/components/nft-transfer/TransferToggle.test.tsx (1)
components/nft-transfer/TransferToggle.tsx (1)
  • TransferToggle (9-49)
components/nft-transfer/TransferSingle.tsx (3)
components/nft-transfer/TransferState.tsx (2)
  • useTransfer (164-168)
  • buildTransferKey (170-181)
entities/IProfile.ts (2)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT (377-385)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE (387-395)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (58-941)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (58-941)
__tests__/components/nft-transfer/TransferState.test.tsx (1)
components/nft-transfer/TransferState.tsx (3)
  • useTransfer (164-168)
  • TransferProvider (46-162)
  • buildTransferKey (170-181)
components/nft-transfer/TransferModal.tsx (6)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
components/the-memes/MemePageYourCards.tsx (1)

226-226: Use explicit existence check for nft.id
props.nft?.id is falsy for 0, preventing valid token IDs. Replace with an explicit check and confirm if id = 0 is ever used:

- {props.nftBalance > 0 && props.myOwner && props.nft?.id && (
+ {props.nftBalance > 0 && props.myOwner && props.nft?.id !== undefined && (
components/nft-transfer/TransferModal.tsx (1)

415-452: No chain propagation changes required publicClient and walletClient are instantiated with a chain at creation, so simulateContract/writeContract inherit the correct chain.

Comment thread __tests__/components/nft-transfer/TransferPanel.test.tsx Outdated
Comment thread __tests__/components/nft-transfer/TransferSingle.test.tsx Outdated
Comment thread components/nft-transfer/TransferModal.tsx Outdated
Comment thread components/nft-transfer/TransferModal.tsx Outdated
Comment thread components/nft-transfer/TransferModal.tsx Outdated
Comment thread components/nft-transfer/TransferPanel.tsx Outdated
Comment thread components/nft-transfer/TransferSingle.tsx
Comment thread components/nft-transfer/TransferSingle.tsx
Comment thread components/user/collected/cards/UserPageCollectedCard.tsx Outdated
Comment thread components/user/collected/cards/UserPageCollectedCard.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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

Caution

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

⚠️ Outside diff range comments (1)
__tests__/components/user/collected/UserPageCollected.test.tsx (1)

77-80: Use wallets array in mockProfile to match ApiIdentity
In tests/components/user/collected/UserPageCollected.test.tsx replace the single wallet field with a wallets array—e.g.:

const mockProfile = {
  handle: "testuser",
  wallets: [{ wallet: "0x123" }],
} as ApiIdentity;

This ensures the mock aligns with the interface and satisfies the profile.wallets?.some(…) check.

♻️ Duplicate comments (7)
components/nft-transfer/TransferModal.tsx (5)

58-64: Make props readonly to match project rules
Props must be immutable. Update signature as below.

As per coding guidelines

-export default function TransferModal({
-  open,
-  onClose,
-}: {
-  open: boolean;
-  onClose: (opts?: { completed?: boolean }) => void;
-}) {
+export default function TransferModal(
+  { open, onClose }: Readonly<{
+    open: boolean;
+    onClose: (opts?: { completed?: boolean }) => void;
+  }>
+) {

1-926: Remove comments from TSX per project rules
TS/TSX must be comment-free. Remove inline comments and JSX comments (e.g., lines 23-26, 97-101, 206-216, 217-223, 538-573, 575-586, 633-641, 741-797, 874-922).

As per coding guidelines


565-571: Fix close control semantics (wrap icon in a button)
FontAwesomeIcon isn’t a button and type="button" is invalid on it. Wrap it for a11y.

-            {(flow === "review" || flow === "success" || flow === "error") && (
-              <FontAwesomeIcon
-                icon={faXmarkCircle}
-                type="button"
-                onClick={handleClose}
-                size="xl"
-              />
-            )}
+            {(flow === "review" || flow === "success" || flow === "error") && (
+              <button
+                type="button"
+                aria-label="Close"
+                onClick={handleClose}
+                className="tw-text-white hover:tw-text-white/80"
+              >
+                <FontAwesomeIcon icon={faXmarkCircle} size="xl" />
+              </button>
+            )}

729-736: Replace invalid Tailwind class "tw-border-1" with "tw-border"
tw-border-1 isn’t valid; use tw-border (or tw-border-[1px]).

-                    className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]"
+                    className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border tw-border-solid tw-border-[#444]"
@@
-                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">
@@
-                className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
+                className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
@@
-                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">

Also applies to: 879-891, 900-906


670-694: Avoid potential null React keys in results list
profile_id can be null. Use a stable non-null fallback.

-                    {results.map((r: CommunityMemberMinimal) => (
+                    {results.map((r: CommunityMemberMinimal) => (
                       <button
-                        key={r.profile_id}
+                        key={r.profile_id ?? r.wallet}
components/nft-transfer/TransferPanel.tsx (2)

34-41: Remove comments from TSX
Delete inline and JSX comments to comply.

As per coding guidelines

Also applies to: 55-62, 68-76, 213-213


102-105: Replace invalid Tailwind class "tw-border-1" with "tw-border"
Fix on Clear/Cancel/Continue buttons.

-              className="tw-text-sm tw-rounded-lg tw-bg-white tw-text-black tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]">
+              className="tw-text-sm tw-rounded-lg tw-bg-white tw-text-black tw-py-1 tw-border tw-border-solid tw-border-[#444]">
@@
-            className="tw-flex-1 tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/20 tw-text-white tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]">
+            className="tw-flex-1 tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/20 tw-text-white tw-py-1 tw-border tw-border-solid tw-border-[#444]">
@@
-            className="tw-flex-1 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border-1 tw-border-solid tw-border-[#444]">
+            className="tw-flex-1 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border tw-border-solid tw-border-[#444]">

Also applies to: 200-208

🧹 Nitpick comments (8)
__tests__/components/memelab/MemeLabPage.test.tsx (1)

365-377: Test setup correctly provides Wagmi context for transfer UI.

The mock Wagmi configuration and provider wrapper are appropriate for testing the "your cards" tab, which conditionally renders the transfer UI based on NFT balance and tab focus.

Consider moving WagmiProvider to the renderWithQueryClient wrapper function for consistency across all tests:

 const renderWithQueryClient = (component: React.ReactElement) => {
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
         retry: false,
       },
     },
   });
+  const mockWagmiConfig = createConfig({
+    chains: [mainnet],
+    transports: {
+      [mainnet.id]: http(),
+    },
+  });
   return render(
-    <QueryClientProvider client={queryClient}>{component}</QueryClientProvider>
+    <QueryClientProvider client={queryClient}>
+      <WagmiProvider config={mockWagmiConfig}>
+        {component}
+      </WagmiProvider>
+    </QueryClientProvider>
   );
 };

Then simplify the test call:

 await act(async () => {
-  renderWithQueryClient(
-    <WagmiProvider config={mockWagmiConfig}>
-      <MemeLabPageComponent nftId="1" />
-    </WagmiProvider>
-  );
+  renderWithQueryClient(<MemeLabPageComponent nftId="1" />);
 });

This ensures all tests have Wagmi context available, making the test suite more robust if component requirements change or new tests exercise the transfer UI code paths.

__tests__/components/the-memes/MemePageYourCards.test.tsx (2)

11-39: Consider using Partial types instead of as any.

While as any is acceptable in tests, using Partial<NFT>, Partial<ConsolidatedTDH>, and Partial<Transaction[]> would provide better type safety and catch potential type mismatches.

Apply this diff to improve type safety:

-const mockNFT = {
+const mockNFT: Partial<NFT> = {
   id: 123,
   name: "Test Meme",
   artist: "Test Artist",
-} as any;
+};

-const mockConsolidatedTDH = {
+const mockConsolidatedTDH: Partial<ConsolidatedTDH> = {
   wallets: ["0x123"],
   balance: 5,
   tdh: 1000,
   dense_rank_balance: 10,
-} as any;
+};

-const mockTransactions = [
+const mockTransactions: Partial<Transaction>[] = [
   {
     transaction_date: new Date("2023-01-01"),
     from_address: "0x0000000000000000000000000000000000000000",
     to_address: "0x456",
     value: 0,
     token_count: 1,
   },
   {
     transaction_date: new Date("2023-01-02"),
     from_address: "0x789",
     to_address: "0x456",
     value: 1.5,
     token_count: 2,
   },
-] as any[];
+];

56-208: Consider adding tests for additional transaction categories.

The test suite has good coverage of core scenarios, and the selective use of renderWithProviders is correct (only when TransferSingle would render). However, consider adding tests for:

  • Transferred in cards (non-zero value transfers from other addresses)
  • Transferred out cards (transfers from user wallets)
  • Sold cards (positive value transfers from user wallets)
  • Edge cases with multiple token counts in transactions

Example additional test:

it("should categorize transferred in cards", () => {
  const txWithTransferIn = [
    {
      transaction_date: new Date("2023-01-01"),
      from_address: "0x789",
      to_address: "0x456",
      value: 0,
      token_count: 1,
    },
  ];
  
  renderWithQueryAndWagmiProviders(
    <MemePageYourCardsRightMenu
      show={true}
      transactions={txWithTransferIn}
      wallets={["0x456"]}
      nft={mockNFT}
      nftBalance={1}
      myOwner={mockConsolidatedTDH}
      myTDH={undefined}
      myRank={undefined}
    />
  );

  expect(screen.getByText("1 card transferred in")).toBeInTheDocument();
});
__tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx (1)

22-34: Reset shared mock state between tests to avoid leakage

paginationProps is module-scoped and retains values across tests. Reset it in beforeEach to keep tests isolated.

+beforeEach(() => {
+  for (const k of Object.keys(paginationProps)) delete (paginationProps as any)[k];
+});
components/nft-transfer/TransferModal.tsx (1)

304-311: Remove unused variable
wroteTransaction is set but unused.

-  let wroteTransaction = false;
   try {
@@
-          wroteTransaction = true;
@@
-            wroteTransaction = true;
__tests__/components/nft-transfer/TransferModal.test.tsx (1)

175-209: Strengthen assertions to catch ERC721 vs ERC1155 mixups
Also assert functionName/ABI per call to ensure correct contract paths.

-    await waitFor(() => expect(simulateContract).toHaveBeenCalledTimes(2));
+    await waitFor(() => expect(simulateContract).toHaveBeenCalledTimes(2));
+    const calls = (simulateContract as jest.Mock).mock.calls;
+    expect(calls.some(([, , args]) => (args ?? calls[0])[0]?.functionName === "safeBatchTransferFrom")).toBe(true);
+    expect(calls.some(([, , args]) => (args ?? calls[0])[0]?.functionName === "safeTransferFrom")).toBe(true);
components/nft-transfer/TransferPanel.tsx (2)

151-171: Use buttons for +/- controls for keyboard a11y
Wrap icons in with disabled state.

-                      <FontAwesomeIcon
-                        icon={faMinusCircle}
-                        onClick={() => t.decQty(it.key)}
-                        className="tw-size-6 tw-cursor-pointer"
-                        color={qty <= 1 ? "#60606C" : "#fff"}
-                        aria-disabled={qty <= 1}
-                        data-testid="transfer-panel-minus"
-                      />
+                      <button
+                        type="button"
+                        onClick={() => t.decQty(it.key)}
+                        disabled={qty <= 1}
+                        aria-label="Decrease quantity"
+                        className="tw-text-white disabled:tw-text-[#60606C]"
+                        data-testid="transfer-panel-minus"
+                      >
+                        <FontAwesomeIcon icon={faMinusCircle} className="tw-size-6" />
+                      </button>
@@
-                      <FontAwesomeIcon
-                        icon={faPlusCircle}
-                        onClick={() => t.incQty(it.key)}
-                        className="tw-size-6 tw-cursor-pointer"
-                        color={qty >= max ? "#60606C" : "#fff"}
-                        aria-disabled={qty >= max}
-                        data-testid="transfer-panel-plus"
-                      />
+                      <button
+                        type="button"
+                        onClick={() => t.incQty(it.key)}
+                        disabled={qty >= max}
+                        aria-label="Increase quantity"
+                        className="tw-text-white disabled:tw-text-[#60606C]"
+                        data-testid="transfer-panel-plus"
+                      >
+                        <FontAwesomeIcon icon={faPlusCircle} className="tw-size-6" />
+                      </button>

174-181: Use FontAwesome for the remove icon
Replace × with FontAwesome for consistency and a11y.

-import {
-  faAnglesDown,
-  faAnglesUp,
-  faMinusCircle,
-  faPlusCircle,
-} from "@fortawesome/free-solid-svg-icons";
+import {
+  faAnglesDown,
+  faAnglesUp,
+  faMinusCircle,
+  faPlusCircle,
+  faXmark,
+} from "@fortawesome/free-solid-svg-icons";
@@
-                  <button
+                  <button
                     type="button"
-                    className="tw-inline-flex tw-items-center tw-justify-center tw-h-6 tw-w-6 tw-rounded-full tw-bg-[#ef4444] tw-font-medium tw-text-white hover:tw-bg-[#d92b2b] tw-text-lg tw-p-0 tw-border-0"
+                    className="tw-inline-flex tw-items-center tw-justify-center tw-h-6 tw-w-6 tw-rounded-full tw-bg-[#ef4444] tw-text-white hover:tw-bg-[#d92b2b] tw-p-0 tw-border-0"
                     onClick={() => t.unselect(it.key)}
                     aria-label="Remove">
-                    &times;
+                    <FontAwesomeIcon icon={faXmark} />
                   </button>

Also applies to: 5-9

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9f3511 and 24f10ff.

📒 Files selected for processing (8)
  • __tests__/components/memelab/MemeLabPage.test.tsx (2 hunks)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferPanel.test.tsx (1 hunks)
  • __tests__/components/the-memes/MemePageYourCards.test.tsx (9 hunks)
  • __tests__/components/user/collected/UserPageCollected.test.tsx (13 hunks)
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx (2 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/components/nft-transfer/TransferPanel.test.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • components/nft-transfer/TransferPanel.tsx
  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • components/nft-transfer/TransferPanel.tsx
  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

{**/__tests__/**,**/*.test.{ts,tsx}}: If coverage on a modified file is below 80%, add meaningful tests to raise it to at least 80%
Mock external dependencies and APIs in tests

Files:

  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
**/__tests__/**

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in __tests__/ directories when organizing standalone test suites

Files:

  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
**/*.test.tsx

📄 CodeRabbit inference engine (AGENTS.md)

When co-locating tests with components, name them ComponentName.test.tsx

Files:

  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx
  • __tests__/components/memelab/MemeLabPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
🧠 Learnings (2)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (6)
components/nft-transfer/TransferPanel.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (58-926)
__tests__/components/user/collected/UserPageCollected.test.tsx (2)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-162)
components/user/collected/UserPageCollected.tsx (1)
  • UserPageCollected (79-554)
__tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx (2)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-162)
components/user/collected/cards/UserPageCollectedCards.tsx (1)
  • UserPageCollectedCards (17-104)
components/nft-transfer/TransferModal.tsx (6)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (164-168)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (58-926)
__tests__/components/the-memes/MemePageYourCards.test.tsx (2)
__tests__/utils/testContexts.tsx (1)
  • renderWithProviders (52-63)
components/the-memes/MemePageYourCards.tsx (2)
  • MemePageYourCardsRightMenu (18-254)
  • MemePageYourCardsSubMenu (256-291)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
__tests__/components/memelab/MemeLabPage.test.tsx (1)

6-7: LGTM! Wagmi imports added for test context.

The imports correctly bring in the necessary Wagmi utilities to set up the provider context required by the transfer UI functionality in the "your cards" tab.

__tests__/components/the-memes/MemePageYourCards.test.tsx (3)

1-9: LGTM!

The imports are well-organized and include all necessary testing utilities, React Query, and Wagmi dependencies.


232-246: LGTM! Good pattern for extending mock data.

The approach of extending mockTransactions with additional required fields (gas, contract, transaction, etc.) is a clean pattern that ensures the mock data matches the full Transaction type while reusing base test data.


210-229: LGTM!

The test suite appropriately covers the component's show/hide logic and conditional rendering based on transaction presence.

__tests__/components/user/collected/UserPageCollected.test.tsx (2)

1-1: LGTM! Clean TransferProvider integration.

The introduction of TransferProvider wrapping via the renderWithTransferProvider helper is a clean pattern that ensures all tests run within the transfer context. The SeizeConnectContext mock provides the necessary authentication state for transfer-enabled UI logic.

Also applies to: 58-64


125-125: Verify transfer integration tests and coverage in UserPageCollected

  • Dedicated transfer tests live under __tests__/components/nft-transfer/; confirm if UserPageCollected suite needs its own integration tests for transfer flows
  • Ensure UserPageCollected.tsx test coverage meets the 80% threshold
__tests__/components/user/collected/cards/UserPageCollectedCards.test.tsx (1)

83-86: LGTM: Provider-wrapped render and explicit mocks make tests robust

Wrapper via TransferProvider and focused component mocks look good; assertions reflect pagination/empty states correctly.

Also applies to: 90-99, 112-121, 127-136

__tests__/components/nft-transfer/TransferModal.test.tsx (1)

96-121: LGTM: Comprehensive mocks and E2E flow coverage
Mocks for wagmi, identity, image, and provider-less hook usage are set up cleanly; core success/error paths are covered.

Also applies to: 128-135

Comment thread __tests__/components/the-memes/MemePageYourCards.test.tsx Outdated
Comment thread components/nft-transfer/TransferModal.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
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

♻️ Duplicate comments (8)
components/nft-transfer/TransferModalPfp.tsx (1)

28-56: Use react-query for IPFS resolution (avoid race conditions, follow guideline)

Replace useEffect + local state with a useQuery-based hook (e.g., useResolvedIpfsUrl) keyed by src.

As per coding guidelines

components/nft-transfer/TransferState.tsx (1)

28-38: Remove inline comments from TS/TSX per repo rules

Delete the comment lines to comply.

As per coding guidelines

-  /** quantity controls */
   setQty: (key: string, qty: number) => void;
   incQty: (key: string) => void;
   decQty: (key: string) => void;
 
   clear: () => void;
-  /** number of distinct items selected */
   count: number;
-  /** total units selected (sum of qty across items) */
   totalQty: number;
components/nft-transfer/TransferModal.tsx (6)

575-581: Fix close control semantics and a11y

Wrap the icon in a button; FontAwesomeIcon doesn’t accept type="button" and isn’t focusable.

-            {flow === "review" && enableMockTransfers && (
+            {flow === "review" && enableMockTransfers && (
               <div className="tw-flex tw-items-center tw-gap-2 tw-text-[12px] tw-opacity-80">
                 ...
               </div>
             )}
             {(flow === "review" || flow === "success" || flow === "error") && (
-              <FontAwesomeIcon
-                icon={faXmarkCircle}
-                type="button"
-                onClick={handleClose}
-                size="xl"
-              />
+              <button
+                type="button"
+                aria-label="Close"
+                onClick={handleClose}
+                className="tw-text-white hover:tw-text-white/80">
+                <FontAwesomeIcon icon={faXmarkCircle} size="xl" />
+              </button>
             )}

762-785: Fix potential null React key in results list

profile_id can be null; use a non-null fallback (e.g., wallet).

-                      <button
-                        key={r.profile_id}
+                      <button
+                        key={r.profile_id ?? r.wallet}
                         type="button"

673-686: Replace invalid Tailwind class "tw-border-1" with "tw-border"

"tw-border-1" is invalid. Use "tw-border".

-                      className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]"
+                      className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border tw-border-solid tw-border-[#444]"
...
-                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">
...
-                className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
+                className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
...
-                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">

Also applies to: 876-887, 898-904


297-303: Early-guard selectedWallet to avoid spurious wallet flow

Prevent switching to "wallet" when no destination selected; set proper error and stay in review.

-  const handleConfirm = useCallback(async () => {
-    if (!publicClient || !address) {
-      setErrorMsg("Client not ready. Please reconnect.");
+  const handleConfirm = useCallback(async () => {
+    if (!publicClient || !address || !selectedWallet) {
+      setErrorMsg(!selectedWallet ? "Please select a destination wallet." : "Client not ready. Please reconnect.");
       setFlow("error");
       return;
     }

23-26: Remove comments from TSX

Repo rule forbids comments in TS/TSX. Delete these comment lines (and any others).

As per coding guidelines

-// DEMO: set to true to simulate transfers locally without opening wallet or sending txs
...
-  // UI-driven mock controls (default to constants above)
...
-    // Initial check
...
-    // Re-check on window resize
-    // Attach scroll listeners to each scrollable container
...
-        {/* header */}
...
-        {/* body */}
...
-        {/* footer */}

Also applies to: 97-102, 217-223, 548-548, 585-585, 872-872


333-337: Critical: contractType comparison uses string, not enum

Comparing to "ERC1155" will fail if ContractType is an enum. Use the enum constant.

+import { ContractType } from "@/enums";
...
-        byContract.set(it.contract, {
-          is1155: it.contractType === "ERC1155",
+        byContract.set(it.contract, {
+          is1155: it.contractType === ContractType.ERC1155,
           items: [it],
           label: it.label,
         });
🧹 Nitpick comments (3)
__tests__/components/nft-transfer/TransferModal.test.tsx (2)

175-209: Strengthen assertions to catch wrong ABI/contract calls

Add expectations for simulateContract args to ensure ERC1155 uses safeBatchTransferFrom and ERC721 uses safeTransferFrom on correct contracts. This would catch regressions.

-    await waitFor(() => expect(simulateContract).toHaveBeenCalledTimes(2));
+    await waitFor(() => expect(simulateContract).toHaveBeenCalledTimes(2));
+    const calls = simulateContract.mock.calls;
+    expect(calls[0][0]).toMatchObject({
+      abi: expect.arrayContaining([expect.objectContaining({ name: "safeBatchTransferFrom" })]),
+      functionName: "safeBatchTransferFrom",
+      address: "0x1155",
+    });
+    expect(calls[1][0]).toMatchObject({
+      abi: expect.arrayContaining([expect.objectContaining({ name: "safeTransferFrom" })]),
+      functionName: "safeTransferFrom",
+      address: "0x721",
+    });

131-135: Optional: prefer user-event over fireEvent

For more realistic interactions (typing/click), use @testing-library/user-event.

Also applies to: 211-222

components/nft-transfer/TransferModal.tsx (1)

473-512: Optional: replace emoji with FontAwesome icons

To align with “use FontAwesome for icons,” consider swapping static emoji images for FontAwesome equivalents (e.g., faCircleCheck/faCircleExclamation).

As per coding guidelines

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24f10ff and cb4578a.

📒 Files selected for processing (6)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferPanel.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferState.test.tsx (1 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferModalPfp.tsx (1 hunks)
  • components/nft-transfer/TransferState.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/components/nft-transfer/TransferState.test.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Follow existing code style and naming conventions

Files:

  • components/nft-transfer/TransferState.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/nft-transfer/TransferModalPfp.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks for UI components

Files:

  • components/nft-transfer/TransferState.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/nft-transfer/TransferModalPfp.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

{**/__tests__/**,**/*.test.{ts,tsx}}: If coverage on a modified file is below 80%, add meaningful tests to raise it to at least 80%
Mock external dependencies and APIs in tests

Files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
**/__tests__/**

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in __tests__/ directories when organizing standalone test suites

Files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
**/*.test.tsx

📄 CodeRabbit inference engine (AGENTS.md)

When co-locating tests with components, name them ComponentName.test.tsx

Files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • __tests__/components/nft-transfer/TransferPanel.test.tsx
🧠 Learnings (2)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferState.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/nft-transfer/TransferModalPfp.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (4)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (58-924)
__tests__/components/nft-transfer/TransferPanel.test.tsx (1)
components/nft-transfer/TransferPanel.tsx (1)
  • TransferPanel (16-226)
components/nft-transfer/TransferModal.tsx (6)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
components/nft-transfer/TransferModalPfp.tsx (1)
components/ipfs/IPFSContext.tsx (1)
  • resolveIpfsUrl (67-77)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
__tests__/components/nft-transfer/TransferPanel.test.tsx (1)

67-118: LGTM — tests align with current component behavior

Covers empty, list, and continue flows; mocking TransferModal is appropriate.

Comment thread components/nft-transfer/TransferModal.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

♻️ Duplicate comments (4)
components/user/collected/cards/UserPageCollectedCard.tsx (4)

91-91: Fix type safety: coalesce seized_count before formatting.

The formatNumberWithCommasOrDash function signature expects number, but card.seized_count is number | null. While the function handles null internally, this creates a TypeScript type mismatch.

Apply this diff to ensure type safety:

-                {formatNumberWithCommasOrDash(card.seized_count)}x
+                {formatNumberWithCommasOrDash(card.seized_count ?? 0)}x

123-137: Fix inconsistent ERC1155 selection text display.

The selection text logic shows quantity only when copiesMax === 1 but displays just "Selected" for multi-copy tokens (copiesMax > 1). This prevents users from seeing how many copies they selected.

Apply this diff to display quantity for all selected items:

                   <span className="tw-text-sm tw-font-medium">
-                    {(() => {
-                      if (selected) {
-                        if (copiesMax === 1) {
-                          return `Selected ${qtySelected} / ${copiesMax}`;
-                        }
-                        return "Selected";
-                      }
-
-                      if (copiesMax > 1) {
-                        return `Select (up to ${copiesMax})`;
-                      }
-
-                      return "Select";
-                    })()}
+                    {selected
+                      ? `Selected ${qtySelected} / ${copiesMax}`
+                      : copiesMax > 1
+                      ? `Select (up to ${copiesMax})`
+                      : "Select"}
                   </span>

114-120: Use tw- prefix for Tailwind classes to match codebase style.

The checkbox classes lack the tw- prefix used throughout the codebase. While the readOnly approach prevents event conflicts, class naming should be consistent.

As per coding guidelines

Apply this diff:

               <input
                 checked={selected}
                 id={`${card.collection}-${card.token_id}`}
                 type="checkbox"
-                className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
+                className="tw-w-4 tw-h-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded-sm focus:tw-ring-blue-500 dark:focus:tw-ring-blue-600 dark:tw-ring-offset-gray-800 focus:tw-ring-2 dark:tw-bg-gray-700 dark:tw-border-gray-600"
                 readOnly
               />

141-166: Replace icon-based controls with accessible button elements.

The plus/minus icons lack proper accessibility: no role="button", no aria-label, and onClick on non-interactive elements bypasses keyboard navigation. aria-disabled on icons doesn't provide the same functionality as the disabled prop on buttons.

Apply this diff to wrap icons in semantic button elements:

                   {copiesMax > 1 && qtySelected > 0 && (
                     <div className="tw-flex tw-items-center tw-gap-1">
-                      <FontAwesomeIcon
-                        icon={faMinusCircle}
-                        onClick={(e) => {
-                          e.preventDefault();
-                          e.stopPropagation();
-                          onDecQty?.();
-                        }}
-                        className="tw-size-5 tw-cursor-pointer"
-                        color={qtySelected <= 1 ? "#60606C" : "#fff"}
-                        aria-disabled={qtySelected <= 1}
-                      />
+                      <button
+                        type="button"
+                        onClick={(e) => {
+                          e.preventDefault();
+                          e.stopPropagation();
+                          onDecQty?.();
+                        }}
+                        disabled={qtySelected <= 1}
+                        aria-label="Decrease quantity"
+                        className="tw-bg-transparent tw-border-none tw-p-0 tw-cursor-pointer disabled:tw-cursor-not-allowed">
+                        <FontAwesomeIcon
+                          icon={faMinusCircle}
+                          className="tw-size-5"
+                          color={qtySelected <= 1 ? "#60606C" : "#fff"}
+                        />
+                      </button>
                       <div className="tw-min-w-[2ch] tw-text-center tw-text-xs tw-tabular-nums tw-select-none">
                         {qtySelected}
                       </div>
-                      <FontAwesomeIcon
-                        icon={faPlusCircle}
-                        onClick={(e) => {
-                          e.preventDefault();
-                          e.stopPropagation();
-                          onIncQty?.();
-                        }}
-                        className="tw-size-5 tw-cursor-pointer"
-                        color={qtySelected >= copiesMax ? "#60606C" : "#fff"}
-                        aria-disabled={qtySelected >= copiesMax}
-                      />
+                      <button
+                        type="button"
+                        onClick={(e) => {
+                          e.preventDefault();
+                          e.stopPropagation();
+                          onIncQty?.();
+                        }}
+                        disabled={qtySelected >= copiesMax}
+                        aria-label="Increase quantity"
+                        className="tw-bg-transparent tw-border-none tw-p-0 tw-cursor-pointer disabled:tw-cursor-not-allowed">
+                        <FontAwesomeIcon
+                          icon={faPlusCircle}
+                          className="tw-size-5"
+                          color={qtySelected >= copiesMax ? "#60606C" : "#fff"}
+                        />
+                      </button>
                     </div>
                   )}
🧹 Nitpick comments (1)
components/user/collected/cards/UserPageCollectedCard.tsx (1)

43-43: Simplify number formatting with Math.round().

The current approach converts to string with toFixed(0), then back to number with unary +. Use Math.round() directly for cleaner code.

Apply this diff:

-      return formatNumberWithCommasOrDash(+(card.tdh ?? 0).toFixed(0));
+      return formatNumberWithCommasOrDash(Math.round(card.tdh ?? 0));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e08782 and cb94d0d.

📒 Files selected for processing (3)
  • __tests__/components/nft-transfer/TransferSingle.test.tsx (1 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/components/nft-transfer/TransferSingle.test.tsx
  • components/nft-transfer/TransferModal.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

**/*.{ts,tsx}: Use TypeScript for source code and follow existing code style and naming conventions
Adhere to clean code standards as measured by SonarQube

Files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Implement React components as functional components using hooks (no class components)

Files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
🧬 Code graph analysis (1)
components/user/collected/cards/UserPageCollectedCard.tsx (2)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (117-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)

Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

Caution

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

⚠️ Outside diff range comments (1)
components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx (1)

56-65: Fix effect dependency: depends on token.id, not owner

The TDH fetch uses props.token.id; depend on id to refetch correctly.

Apply this diff:

-  }, [props.token.owner]);
+  }, [props.token.id]);
♻️ Duplicate comments (8)
__tests__/components/nft-transfer/TransferSingle.test.tsx (1)

162-170: Good fix: correct +/- test IDs used

Selectors now match component’s data-testids, addressing prior feedback.

components/nft-transfer/TransferModal.tsx (6)

570-576: Fix close control semantics; wrap icon in a button

FontAwesomeIcon doesn’t accept type and isn’t keyboard-focusable. Wrap with a button for a11y.

Apply this diff:

-            {(flow === "review" || flow === "success" || flow === "error") && (
-              <FontAwesomeIcon
-                icon={faXmarkCircle}
-                type="button"
-                onClick={handleClose}
-                size="xl"
-              />
-            )}
+            {(flow === "review" || flow === "success" || flow === "error") && (
+              <button
+                type="button"
+                aria-label="Close"
+                onClick={handleClose}
+                className="tw-text-white hover:tw-text-white/80"
+              >
+                <FontAwesomeIcon icon={faXmarkCircle} size="xl" />
+              </button>
+            )}

669-680: Replace invalid Tailwind class "tw-border-1" with "tw-border"

"tw-border-1" is not a valid Tailwind class.

Apply this diff:

-                      className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border-1 tw-border-solid tw-border-[#444]"
+                      className="tw-text-xs tw-rounded-md tw-bg-white/10 hover:tw-bg-white/15 tw-px-2 tw-py-1 tw-border tw-border-solid tw-border-[#444]"
@@
-                    className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                    className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">
@@
-                    className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
+                    className="tw-rounded-lg tw-bg-white tw-text-black tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444] disabled:tw-opacity-60 disabled:tw-cursor-not-allowed">
@@
-                    className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border-1 tw-border-solid tw-border-[#444]">
+                    className="tw-rounded-lg tw-bg-white/10 hover:tw-bg-white/15 tw-px-4 tw-py-2 tw-border tw-border-solid tw-border-[#444]">

Also applies to: 884-897, 915-926


23-26: Remove comments from TSX files

Project rule: no comments in TS/TSX. Delete inline and JSX comments.

As per coding guidelines

Also applies to: 97-101, 543-543, 580-581, 878-878


147-184: Refactor search to react-query with debounced key

Replace manual debounce/effect with useQuery keyed by debounced trimmedQuery (enabled when open and length ≥ MIN). Improves cancellation/cache and reduces effect complexity.

As per coding guidelines


768-791: Fix potential null React key for results

profile_id can be null; use a non-null fallback (e.g., wallet).

Apply this diff:

-                      <button
-                        key={r.profile_id}
+                      <button
+                        key={r.profile_id ?? r.wallet}
                         type="button"

316-321: Contract type check uses string literal; compare to enum constant

Comparing to "ERC1155" can misclassify when ContractType is an enum. Use ContractType.ERC1155 instead.

Apply this diff:

+import { ContractType } from "@/enums";
@@
-        byContract.set(it.contract, {
-          is1155: it.contractType === "ERC1155",
+        byContract.set(it.contract, {
+          is1155: it.contractType === ContractType.ERC1155,
           items: [it],
           label: it.label,
         });
components/user/collected/UserPageCollected.tsx (1)

239-274: Guard address forcing to avoid redundant router.replace loops (duplicate of past review)

This issue was previously flagged and remains unresolved. When transfer is enabled, the effect calls updateFields on every render even if the URL already contains the connected address, resulting in repeated router.replace calls. Since searchParams is in the effect dependencies and updateFields modifies the URL (which updates searchParams), this creates a loop.

Add guards to only call updateFields when the target address/page actually differs:

   if (transferEnabled) {
     if (!hadForcedRef.current) {
       previousAddressRef.current = currentParamAddress;
     }
     hadForcedRef.current = true;

-    // Force to connected wallet
-    updateFields([
-      { name: "address", value: connected },
-      { name: "page", value: "1" },
-    ]);
+    if (currentParamAddress !== connected) {
+      updateFields([
+        { name: "address", value: connected },
+        { name: "page", value: "1" },
+      ]);
+    }
   } else if (hadForcedRef.current) {
     const restore = previousAddressRef.current;
     previousAddressRef.current = null;
     hadForcedRef.current = false;

-    updateFields([
-      { name: "address", value: restore },
-      { name: "page", value: "1" },
-    ]);
+    if (restore !== currentParamAddress) {
+      updateFields([
+        { name: "address", value: restore },
+        { name: "page", value: "1" },
+      ]);
+    }
   }
🧹 Nitpick comments (4)
__tests__/components/nft-transfer/TransferSingle.test.tsx (1)

196-201: Prefer user-event over fireEvent for clicks

Adopt @testing-library/user-event for realistic user interactions (click, type). Replace fireEvent.click with userEvent.click.

As per coding guidelines

components/nft-transfer/TransferToggle.tsx (1)

33-53: Add aria-pressed for toggle accessibility

Expose pressed state for assistive tech.

Apply this diff:

-    <button
+    <button
       type="button"
+      aria-pressed={t.enabled}
components/user/collected/UserPageCollected.tsx (2)

240-241: Remove comment per coding guidelines

The coding guidelines specify no comments in TypeScript/TSX files.

Apply this diff:

-  useEffect(() => {
-    // Only enforce if transfer is available on this profile (owns wallet & not mobile)
-    if (!showTransfer) return;
+  useEffect(() => {
+    if (!showTransfer) return;

Based on coding guidelines.


544-544: Remove comment per coding guidelines

The coding guidelines specify no comments in TypeScript/TSX files.

Apply this diff:

-          {/* appears only when transfer is enabled */}
           {showTransfer && transferEnabled && <TransferPanel />}

Based on coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb94d0d and 146c509.

📒 Files selected for processing (8)
  • __tests__/components/nft-transfer/TransferSingle.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferToggle.test.tsx (1 hunks)
  • components/6529Gradient/GradientPage.tsx (5 hunks)
  • components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx (11 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
  • components/nft-transfer/TransferToggle.tsx (1 hunks)
  • components/user/collected/UserPageCollected.tsx (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/components/nft-transfer/TransferToggle.test.tsx
  • components/nft-transfer/TransferSingle.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

**/*.{ts,tsx}: Use TypeScript for source code and follow existing code style and naming conventions
Adhere to clean code standards as measured by SonarQube

Files:

  • components/user/collected/UserPageCollected.tsx
  • components/nft-transfer/TransferToggle.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/6529Gradient/GradientPage.tsx
  • components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Implement React components as functional components using hooks (no class components)

Files:

  • components/user/collected/UserPageCollected.tsx
  • components/nft-transfer/TransferToggle.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/6529Gradient/GradientPage.tsx
  • components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
{**/__tests__/**,**/*.test.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in tests directories or alongside components as ComponentName.test.tsx

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Use react-query for data fetching

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (6)
components/user/collected/UserPageCollected.tsx (6)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
components/nft-transfer/TransferToggle.tsx (1)
  • TransferToggle (10-55)
components/user/collected/cards/UserPageCollectedCards.tsx (1)
  • UserPageCollectedCards (17-104)
components/nft-transfer/TransferPanel.tsx (1)
  • TransferPanel (16-226)
components/nft-transfer/TransferToggle.tsx (3)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
__tests__/components/nft-transfer/TransferSingle.test.tsx (3)
components/nft-transfer/TransferState.tsx (2)
  • buildTransferKey (174-185)
  • useTransfer (168-172)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (22-155)
components/nft-transfer/TransferModal.tsx (6)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-42)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
components/6529Gradient/GradientPage.tsx (5)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-166)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (22-155)
constants.ts (1)
  • GRADIENT_CONTRACT (10-10)
components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx (1)
components/you-own-nft-badge/YouOwnNftBadge.tsx (1)
  • YouOwnNftBadge (5-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
components/nft-transfer/TransferToggle.tsx (1)

10-16: Integration and flow look solid

Connect-first handling, clear-on-disable, and mobile guard are correct.

components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx (1)

153-155: Nice: renders ownership badge for connected owner

Good UX detail; consistent with badge component.

components/6529Gradient/GradientPage.tsx (2)

156-170: Solid integration of TransferSingle for owner-only flows

Provider scoping and props are correct; conditional render based on connected owner is appropriate.


66-69: Accurate owner check for connected address

areEqualAddresses guard is correct and efficient.

Signed-off-by: prxt6529 <prxt@6529.io>
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

Caution

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

⚠️ Outside diff range comments (2)
components/the-memes/MemePageYourCards.tsx (2)

17-26: Add readonly keyword to props parameter.

The props parameter should be declared as readonly to comply with the coding guidelines for TypeScript files.

As per coding guidelines.

Apply this diff:

-export function MemePageYourCardsRightMenu(props: {
+export function MemePageYourCardsRightMenu(props: Readonly<{
   show: boolean;
   transactions: Transaction[];
   wallets: string[];
   nft: NFT | undefined;
   nftBalance: number;
   myOwner: ConsolidatedTDH | undefined;
   myTDH: NftTDH | undefined;
   myRank: NftRank | undefined;
-}) {
+}>) {

253-255: Add readonly keyword to props parameter.

The props parameter should be declared as readonly to comply with the coding guidelines for TypeScript files.

As per coding guidelines.

Apply this diff:

-export function MemePageYourCardsSubMenu(props: {
+export function MemePageYourCardsSubMenu(props: Readonly<{
   show: boolean;
   transactions: Transaction[];
-}) {
+}>) {
♻️ Duplicate comments (7)
components/nft-transfer/TransferSingle.tsx (2)

164-167: Fix invalid Tailwind and duplicate padding

Replace tw-border-1 with tw-border and remove duplicate tw-py-* as previously noted.

-  className="tw-w-full tw-py-2 tw-rounded-lg tw-bg-white tw-text-black tw-py-1 disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border-1 tw-border-solid tw-border-[#444] tw-text-lg tw-font-semibold"
+  className="tw-w-full tw-py-2 tw-rounded-lg tw-bg-white tw-text-black disabled:tw-opacity-75 disabled:tw-cursor-not-allowed tw-border tw-border-solid tw-border-[#444] tw-text-lg tw-font-semibold"

71-83: Bug: Ignores provided contract/contractType props; uses mapping instead

This can register the wrong contract if mappings diverge. Use the props.

   useEffect(() => {
-    t.select({
-      key,
-      contract: COLLECTED_COLLECTION_TYPE_TO_CONTRACT[collectionType],
-      contractType: COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE[
-        collectionType
-      ] as ContractType,
-      tokenId,
-      max,
-      thumbUrl,
-      title,
-    });
+    t.select({
+      key,
+      contract,
+      contractType,
+      tokenId,
+      max,
+      thumbUrl,
+      title,
+    });

Also add contract/contractType to the effect deps:

-  }, [key, collectionType, tokenId, max, thumbUrl, title]);
+  }, [key, contract, contractType, tokenId, max, thumbUrl, title]);
components/nft-transfer/TransferModal.tsx (5)

690-699: Replace invalid Tailwind class "tw-border-1" with "tw-border"

Also used in footer buttons.

-  className="... tw-border-1 tw-border-solid tw-border-[#444] ..."
+  className="... tw-border tw-border-solid tw-border-[#444] ..."

Also applies to: 919-927


232-270: Use react-query for search instead of manual debounce/fetch

Guideline: use react-query for data fetching. Replace the effect with useQuery keyed by debounced trimmedQuery and enabled when open && len>=MIN_SEARCH_LENGTH. Improves caching, cancellation, and simplifies state.
As per coding guidelines


26-29: Remove comments from TSX per project rules

TS/TSX must not contain comments. Delete inline comments across this file (examples in these ranges).
As per coding guidelines

Also applies to: 100-105, 127-133, 180-186, 207-215, 217-230, 538-546, 561-566, 599-606


787-795: Fix potential null React key for results

profile_id can be null; fall back to wallet.

-                      <button
-                        key={r.profile_id}
+                      <button
+                        key={r.profile_id ?? r.wallet}

138-146: Compare contractType using enum, not string

Use ContractType.ERC1155 to avoid misclassification.

+import { ContractType } from "@/enums";
...
-        by.set(it.contract, {
-          is1155: it.contractType === "ERC1155",
+        by.set(it.contract, {
+          is1155: it.contractType === ContractType.ERC1155,
           items: [it],
           label: it.label,
         });
🧹 Nitpick comments (4)
components/the-memes/MemePageYourCards.tsx (1)

137-153: Simplify redundant condition check.

The condition at line 137 checks props.nftBalance > 0 && props.myOwner again, but this block is already nested inside the condition at line 119 that performs the same checks. Only the props.nft?.id check is new.

Apply this diff to simplify:

-                    {props.nftBalance > 0 && props.myOwner && props.nft?.id && (
+                    {props.nft?.id && (
                       <Row className="mb-2">
components/nextGen/collections/nextgenToken/NextGenToken.tsx (2)

169-174: Avoid brittle URL .replace for prev/next navigation

Replacing the token id in window.location.href can misfire if the id appears elsewhere (query, other path segs). Build the next path explicitly.

Example:

-const currentHref = window.location.href;
-const prevHref = currentHref.replace(
-  props.token.id.toString(),
-  (props.token.id - 1).toString()
-);
-router.push(prevHref, { scroll: false });
+const url = new URL(window.location.href);
+url.pathname = url.pathname.replace(/\/(\d+)(\/?)$/, `/${props.token.id - 1}$2`);
+router.push(url.toString(), { scroll: false });

Apply similarly for next token.

Also applies to: 212-217


186-193: Tooltip behavior consistency

Prev tooltip lacks delayShow unlike next. Consider adding the same delay for UX parity.

-<Tooltip
-  id={`prev-token-${props.token.id}`}
-  variant="light"
+<Tooltip
+  id={`prev-token-${props.token.id}`}
+  delayShow={250}
+  variant="light"
components/nft-transfer/TransferModal.tsx (1)

540-547: Add role for modal semantics

Set role="dialog" on the overlay or the modal container for better a11y.

-    <div
+    <div
       className={[ /* ... */ ].join(" ")}
       onMouseDown={(e) => { /* ... */ }}
       aria-modal="true"
+      role="dialog"
       aria-label="Transfer dialog">
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 146c509 and 7fc39e1.

📒 Files selected for processing (7)
  • components/6529Gradient/GradientPage.tsx (5 hunks)
  • components/distribution-plan-tool/common/CircleLoader.tsx (1 hunks)
  • components/nextGen/collections/nextgenToken/NextGenToken.tsx (5 hunks)
  • components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx (13 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
  • components/the-memes/MemePageYourCards.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/distribution-plan-tool/common/CircleLoader.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/6529Gradient/GradientPage.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

**/*.{ts,tsx}: Use TypeScript for source code and follow existing code style and naming conventions
Adhere to clean code standards as measured by SonarQube

Files:

  • components/nextGen/collections/nextgenToken/NextGenToken.tsx
  • components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/the-memes/MemePageYourCards.tsx
  • components/nft-transfer/TransferSingle.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Implement React components as functional components using hooks (no class components)

Files:

  • components/nextGen/collections/nextgenToken/NextGenToken.tsx
  • components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/the-memes/MemePageYourCards.tsx
  • components/nft-transfer/TransferSingle.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Use react-query for data fetching

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (5)
components/nextGen/collections/nextgenToken/NextGenToken.tsx (4)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (36-42)
constants.ts (1)
  • NEXTGEN_CONTRACT (6-6)
components/nextGen/collections/nextgenToken/NextGenTokenAbout.tsx (3)
components/auth/Auth.tsx (1)
  • useAuth (95-97)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/you-own-nft-badge/YouOwnNftBadge.tsx (1)
  • YouOwnNftBadge (5-24)
components/nft-transfer/TransferModal.tsx (6)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-39)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
components/the-memes/MemePageYourCards.tsx (2)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (36-42)
constants.ts (1)
  • MEMES_CONTRACT (5-5)
components/nft-transfer/TransferSingle.tsx (5)
components/nft-transfer/TransferState.tsx (3)
  • TransferProvider (46-166)
  • useTransfer (168-172)
  • buildTransferKey (174-185)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
entities/IProfile.ts (2)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT (377-385)
  • COLLECTED_COLLECTION_TYPE_TO_CONTRACT_TYPE (387-395)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (61-975)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
components/the-memes/MemePageYourCards.tsx (2)

1-15: LGTM! Import additions support the new transfer functionality.

The new imports for TransferSingle, constants (MEMES_CONTRACT, NULL_ADDRESS), types (CollectedCollectionType, ConsolidatedTDH, Transaction, ContractType), and react-bootstrap components are properly organized and align with the transfer UI integration.


171-176: Summary inconsistency: Rank row is still present.

The AI summary indicates that a Rank row was removed from the Cards table, but the Rank row is clearly present in the current code. This suggests the summary may not accurately reflect the actual changes.

Comment thread components/nft-transfer/TransferModal.tsx Outdated
Comment thread components/nft-transfer/TransferSingle.tsx
Comment thread components/nft-transfer/TransferSingle.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
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

Caution

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

⚠️ Outside diff range comments (2)
__tests__/components/6529Gradient/GradientPage.test.tsx (1)

264-304: Inconsistent test setup: missing SeizeConnectProvider wrapper.

This test renders the component directly without using the renderPage() helper, which means it doesn't wrap the component with SeizeConnectProvider while all other tests do. This creates inconsistent test setup and may not accurately reflect the component's behavior in production.

Apply this diff to use consistent test setup:

   it("handles wallet connection state changes", async () => {
-    const { rerender } = render(
-      <TitleProvider>
-        <AuthContext.Provider value={{ connectedProfile: null } as any}>
-          <CookieConsentProvider>
-            <GradientPageComponent id="1" />
-          </CookieConsentProvider>
-        </AuthContext.Provider>
-      </TitleProvider>
-    );
+    jest.clearAllMocks();
+    const collection = mockGradientCollection(3);
+    collection[0].owner = "0x1";
+    (fetchUrl as jest.Mock)
+      .mockResolvedValueOnce({ data: collection })
+      .mockResolvedValueOnce({ data: [tx] });
+
+    const { rerender } = render(
+      <TitleProvider>
+        <AuthContext.Provider value={{ connectedProfile: null } as any}>
+          <CookieConsentProvider>
+            <SeizeConnectProvider>
+              <GradientPageComponent id="1" />
+            </SeizeConnectProvider>
+          </CookieConsentProvider>
+        </AuthContext.Provider>
+      </TitleProvider>
+    );

     await waitFor(() => expect(fetchUrl).toHaveBeenCalledTimes(2));

     // Should show as non-owner when no connected profile
     await waitFor(() =>
       expect(screen.getByTestId("image")).toBeInTheDocument()
     );
     await waitFor(() =>
       expect(screen.queryByTestId("owner-badge")).not.toBeInTheDocument()
     );

     // Rerender with connected profile
     rerender(
       <TitleProvider>
         <AuthContext.Provider
           value={{ connectedProfile: { wallets: [{ wallet: "0x1" }] } } as any}>
           <CookieConsentProvider>
+            <SeizeConnectProvider>
               <GradientPageComponent id="1" />
+            </SeizeConnectProvider>
           </CookieConsentProvider>
         </AuthContext.Provider>
       </TitleProvider>
     );

     // Should now show as owner
     await waitFor(() =>
       expect(screen.getByTestId("image")).toBeInTheDocument()
     );
     await waitFor(() =>
       expect(screen.getByTestId("owner-badge")).toBeInTheDocument()
     );
   });
components/nextGen/collections/nextgenToken/NextGenToken.tsx (1)

159-174: Accessibility: make navigation icons real buttons

Icons with onClick are not keyboard-accessible and lack semantics. Use a button with aria-label and disabled state.

-    const prev = (
-      <FontAwesomeIcon
-        icon={faChevronCircleLeft}
-        data-tooltip-id={
-          hasPreviousToken ? `prev-token-${props.token.id}` : undefined
-        }
-        onClick={() => {
+    const prev = (
+      <button
+        type="button"
+        aria-label="Previous token"
+        data-tooltip-id={hasPreviousToken ? `prev-token-${props.token.id}` : undefined}
+        disabled={!hasPreviousToken}
+        onClick={() => {
           if (!hasPreviousToken) {
             return;
           }
           const url = new URL(window.location.href);
           url.pathname = url.pathname.replace(
             /\/(\d+)(\/?)$/,
             `/${props.token.id - 1}$2`
           );
-          router.push(url.toString(), { scroll: false });
-        }}
-        style={{
-          height: "35px",
-          color: hasPreviousToken ? "#fff" : "#9a9a9a",
-          cursor: hasPreviousToken ? "pointer" : "default",
-        }}
-      />
+          router.push(`${url.pathname}${url.search}${url.hash}`, { scroll: false });
+        }}
+        style={{
+          height: "35px",
+          color: hasPreviousToken ? "#fff" : "#9a9a9a",
+          cursor: hasPreviousToken ? "pointer" : "default",
+          background: "transparent",
+          border: "none",
+          padding: 0
+        }}
+      >
+        <FontAwesomeIcon icon={faChevronCircleLeft} />
+      </button>
     );

Do the analogous change for the “next” button.

Also applies to: 203-218

♻️ Duplicate comments (4)
__tests__/components/the-memes/MemePageYourCards.test.tsx (1)

56-71: This issue was previously flagged and remains unresolved.

The renderWithProviders helper still has the naming conflict with __tests__/utils/testContexts.tsx and the QueryClient is not configured for optimal test performance. Please refer to the previous review comment for the suggested fix.

components/user/collected/UserPageCollected.tsx (1)

239-279: Guarded address forcing avoids router.replace loops.

The equality checks before updateFields prevent redirect churn. Good fix.

components/nft-transfer/TransferPanel.tsx (1)

34-41: Remove all inline comments from TSX.

TSX must be comment-free. Delete these comments (and any others in the file).

As per coding guidelines

Also applies to: 57-61, 68-76, 213-213

components/nft-transfer/TransferModal.tsx (1)

27-31: Remove all comments in this TSX file.

Project rule forbids comments in TS/TSX. Remove the DEMO note and section comments (“header”, “body”, “footer”, etc.).

As per coding guidelines

Also applies to: 855-871, 879-904, 905-989, 990-1056

🧹 Nitpick comments (5)
__tests__/components/6529Gradient/GradientPage.test.tsx (1)

62-74: Consider making the mock more configurable for different test scenarios.

The current mock pattern works but has limitations:

  • The SeizeConnectProvider mock doesn't provide the mocked context; it relies on module-level hook mocking
  • All tests share the same mock return values (e.g., address: undefined, isAuthenticated: false)
  • Tests that need different connection states would require re-mocking

Consider this more flexible pattern:

+const mockSeizeConnect = jest.fn();
+const mockSeizeAcceptConnection = jest.fn();
+let mockContextValue = {
+  isAuthenticated: false,
+  seizeConnect: mockSeizeConnect,
+  seizeAcceptConnection: mockSeizeAcceptConnection,
+  address: undefined,
+  hasInitializationError: false,
+  initializationError: null,
+};
+
 jest.mock("@/components/auth/SeizeConnectContext", () => ({
-  useSeizeConnectContext: jest.fn(() => ({
-    isAuthenticated: false,
-    seizeConnect: jest.fn(),
-    seizeAcceptConnection: jest.fn(),
-    address: undefined,
-    hasInitializationError: false,
-    initializationError: null,
-  })),
+  useSeizeConnectContext: jest.fn(() => mockContextValue),
   SeizeConnectProvider: ({ children }: { children: React.ReactNode }) => (
     <>{children}</>
   ),
 }));

Then tests can update mockContextValue as needed:

it("shows transfer button when connected as owner", () => {
  mockContextValue.address = "0x1";
  mockContextValue.isAuthenticated = true;
  renderPage();
  // assertions...
});
components/nft-transfer/TransferModal.tsx (1)

590-629: Refactor search to react-query with debounce.

Repo rule: use react-query for data fetching. Replace manual setTimeout/AbortController with a debounced query + useQuery (enabled on open and length >= MIN_SEARCH_LENGTH) for caching/cancellation.

As per coding guidelines

Example approach:

  • Track debouncedQuery via useEffect/useState (350ms).
  • useQuery([QueryKey.COMMUNITY_MEMBERS, debouncedQuery], fetchFn, { enabled: open && debouncedQuery.length >= MIN_SEARCH_LENGTH })
  • Derive isSearching from isFetching; setResults from data.
components/nextGen/collections/nextgenToken/NextGenToken.tsx (3)

168-174: Use relative href with router.push to keep client-side routing

Passing an absolute URL can bypass Next.js router optimizations. Push a relative path (preserving query/hash).

-          router.push(url.toString(), { scroll: false });
+          router.push(`${url.pathname}${url.search}${url.hash}`, { scroll: false });

Also applies to: 212-218


103-103: Styling: prefer Tailwind utilities in new code

Newly added classes use Bootstrap utilities (pt-4/pb-4, d-md-none, d-none d-md-block). Our TSX guideline is Tailwind for styling; consider Tailwind equivalents (py-4, md:hidden, hidden md:block) where feasible.

As this file mixes React-Bootstrap extensively, confirm whether a local Tailwind-only change is acceptable or whether to defer until a broader styling pass. Based on coding guidelines

Also applies to: 106-117


48-51: Optional: drop useMemo for a simple boolean

useMemo here doesn’t save meaningful work; a direct comparison each render is trivial.

-  const isConnectedAddressOwner = useMemo(() => {
-    return areEqualAddresses(connectedAddress, props.token.owner);
-  }, [props.token.owner, connectedAddress]);
+  const isConnectedAddressOwner = areEqualAddresses(
+    connectedAddress,
+    props.token.owner
+  );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7fc39e1 and 69f5cc6.

📒 Files selected for processing (12)
  • __tests__/components/6529Gradient/GradientPage.test.tsx (3 hunks)
  • __tests__/components/memelab/MemeLabPage.test.tsx (3 hunks)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferSingle.test.tsx (1 hunks)
  • __tests__/components/the-memes/MemePageYourCards.test.tsx (9 hunks)
  • app/network/tdh/historic-boosts/page.client.tsx (1 hunks)
  • app/network/tdh/page.client.tsx (3 hunks)
  • components/nextGen/collections/nextgenToken/NextGenToken.tsx (7 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
  • components/user/collected/UserPageCollected.tsx (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/components/memelab/MemeLabPage.test.tsx
  • components/nft-transfer/TransferSingle.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

**/*.{ts,tsx}: Use TypeScript for source code and follow existing code style and naming conventions
Adhere to clean code standards as measured by SonarQube

Files:

  • components/nextGen/collections/nextgenToken/NextGenToken.tsx
  • components/nft-transfer/TransferPanel.tsx
  • app/network/tdh/historic-boosts/page.client.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/user/collected/UserPageCollected.tsx
  • app/network/tdh/page.client.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/6529Gradient/GradientPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Implement React components as functional components using hooks (no class components)

Files:

  • components/nextGen/collections/nextgenToken/NextGenToken.tsx
  • components/nft-transfer/TransferPanel.tsx
  • app/network/tdh/historic-boosts/page.client.tsx
  • components/nft-transfer/TransferModal.tsx
  • components/user/collected/UserPageCollected.tsx
  • app/network/tdh/page.client.tsx
  • __tests__/components/the-memes/MemePageYourCards.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/6529Gradient/GradientPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
{app,pages}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use NextJS features that match the current version

Files:

  • app/network/tdh/historic-boosts/page.client.tsx
  • app/network/tdh/page.client.tsx
app/**

📄 CodeRabbit inference engine (AGENTS.md)

Add all new Next.js production routes under the app/ router (do not add routes under pages/)

Files:

  • app/network/tdh/historic-boosts/page.client.tsx
  • app/network/tdh/page.client.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/the-memes/MemePageYourCards.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/6529Gradient/GradientPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/the-memes/MemePageYourCards.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/6529Gradient/GradientPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
{**/__tests__/**,**/*.test.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in tests directories or alongside components as ComponentName.test.tsx

Files:

  • __tests__/components/the-memes/MemePageYourCards.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/6529Gradient/GradientPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/the-memes/MemePageYourCards.test.tsx
  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/6529Gradient/GradientPage.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
🧠 Learnings (4)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Use react-query for data fetching

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-10-14T05:39:48.871Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: AGENTS.md:0-0
Timestamp: 2025-10-14T05:39:48.871Z
Learning: Applies to {**/__tests__/**,**/*.test.{ts,tsx}} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/6529Gradient/GradientPage.test.tsx
🧬 Code graph analysis (8)
components/nextGen/collections/nextgenToken/NextGenToken.tsx (4)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (32-38)
constants.ts (1)
  • NEXTGEN_CONTRACT (6-6)
components/nft-transfer/TransferPanel.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (420-1056)
components/nft-transfer/TransferModal.tsx (6)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-39)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
components/user/collected/UserPageCollected.tsx (6)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
components/nft-transfer/TransferToggle.tsx (1)
  • TransferToggle (10-55)
components/user/collected/cards/UserPageCollectedCards.tsx (1)
  • UserPageCollectedCards (17-104)
components/nft-transfer/TransferPanel.tsx (1)
  • TransferPanel (16-226)
__tests__/components/the-memes/MemePageYourCards.test.tsx (3)
__tests__/utils/testContexts.tsx (1)
  • renderWithProviders (52-63)
components/auth/SeizeConnectContext.tsx (1)
  • SeizeConnectProvider (339-616)
components/the-memes/MemePageYourCards.tsx (2)
  • MemePageYourCardsRightMenu (17-251)
  • MemePageYourCardsSubMenu (253-288)
__tests__/components/nft-transfer/TransferSingle.test.tsx (2)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (32-38)
__tests__/components/6529Gradient/GradientPage.test.tsx (2)
components/auth/SeizeConnectContext.tsx (1)
  • SeizeConnectProvider (339-616)
components/6529Gradient/GradientPage.tsx (1)
  • GradientPageComponent (40-309)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (420-1056)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (10)
app/network/tdh/page.client.tsx (1)

55-55: LGTM! Consistent border styling improvements.

The border thickness increase from tw-border-1 to tw-border-2 across these three card containers improves visual consistency and hierarchy. These purely cosmetic changes align with the broader UI standardization effort in the PR.

Also applies to: 219-219, 229-229

__tests__/components/6529Gradient/GradientPage.test.tsx (2)

107-109: LGTM!

The SeizeConnectProvider wrapper is correctly positioned in the component tree and enables testing of authentication-related UI states.


116-305: Add test coverage for transfer functionality.

The PR objectives mention "Transfer NFTs" and "integrates transfer controls into collected and product pages," but there are no tests verifying the transfer UI. Based on the component code (lines 123-134 in GradientPage.tsx), the TransferSingle component is conditionally rendered when isConnectedAddressOwner is true.

Add tests to verify:

  1. Transfer button/component is shown when connected address matches NFT owner
  2. Transfer component is hidden when connected address doesn't match owner
  3. Transfer component receives correct props

Example test structure:

it("shows transfer UI when connected address owns the NFT", async () => {
  // Mock useSeizeConnectContext to return the owner address
  (useSeizeConnectContext as jest.Mock).mockReturnValue({
    address: "0x1",
    isAuthenticated: true,
  });
  
  renderPage("0x1");
  await waitFor(() => expect(fetchUrl).toHaveBeenCalledTimes(2));
  
  // Verify TransferSingle is rendered (add data-testid to TransferSingle mock)
  expect(screen.getByTestId("transfer-single")).toBeInTheDocument();
});

it("hides transfer UI when connected address doesn't own the NFT", async () => {
  (useSeizeConnectContext as jest.Mock).mockReturnValue({
    address: "0x2",
    isAuthenticated: true,
  });
  
  renderPage("0x1");
  await waitFor(() => expect(fetchUrl).toHaveBeenCalledTimes(2));
  
  expect(screen.queryByTestId("transfer-single")).not.toBeInTheDocument();
});

Note: You'll also need to add a mock for TransferSingle component with a testid, and update the mock configuration to allow per-test customization as suggested in the earlier comment.

__tests__/components/the-memes/MemePageYourCards.test.tsx (1)

73-277: Test structure and provider usage look good.

The tests correctly distinguish between scenarios that require the provider context (when TransferSingle would be rendered) and those that don't. The test coverage appropriately exercises the component's conditional rendering logic.

app/network/tdh/historic-boosts/page.client.tsx (1)

10-10: LGTM: border class fix is correct.

tw-border-2 is valid Tailwind and matches the intended visual change.

__tests__/components/nft-transfer/TransferModal.test.tsx (1)

56-231: Solid coverage of success and error flows.

Mocks and assertions exercise ERC1155/721 paths and wallet-unavailable error. Looks good.

__tests__/components/nft-transfer/TransferSingle.test.tsx (1)

128-258: Tests read well and align with component behavior.

Covers mount/unmount selection, qty bounds, modal flow, and rerender key updates.

components/nextGen/collections/nextgenToken/NextGenToken.tsx (3)

46-51: Ownership gating looks correct

Derives ownership from connected address and token.owner; safe null handling via areEqualAddresses.


58-66: Verified TransferSingle props
TransferSingleProps defines max: number, title: string, and optional thumbUrl?: string, matching their usage here.


186-190: Variant and delayShow props are supported react-tooltip v5.28.1 (v5) supports variant="light" and delayShow={250}.

Comment thread components/nextGen/collections/nextgenToken/NextGenToken.tsx
Comment thread components/nft-transfer/TransferModal.tsx Outdated
Comment thread components/user/collected/UserPageCollected.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
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 (3)
components/nextGen/collections/nextgenToken/NextGenToken.tsx (1)

106-117: Avoid mounting TransferSingle twice; render a single instance conditionally

Rendering the same element in two breakpoints mounts it twice. Render one instance based on a media query.

Example fix:

-              <Col xs={12} className="d-md-none">
-                {transferSingle}
-              </Col>
+              <Col xs={12}>
+                {!isMdUp ? transferSingle : null}
+              </Col>
@@
-              <Col sm={12} md={6}>
-                <div className="d-none d-md-block">{transferSingle}</div>
+              <Col sm={12} md={6}>
+                {isMdUp ? transferSingle : null}
                 <NextgenTokenTraits

Add a simple hook and usage:

function useMediaQuery(query: string) {
  const [matches, setMatches] = useState(false);
  useEffect(() => {
    const m = window.matchMedia(query);
    setMatches(m.matches);
    const handler = (e: MediaQueryListEvent) => setMatches(e.matches);
    m.addEventListener("change", handler);
    return () => m.removeEventListener("change", handler);
  }, [query]);
  return matches;
}

const isMdUp = useMediaQuery("(min-width: 768px)");
components/nft-transfer/TransferModal.tsx (2)

485-485: Remove comments in TS/TSX to match project rules

Project rule: no comments in TS/TSX. Delete inline and JSX comments across the file.

As per coding guidelines

Also applies to: 869-869, 977-977, 1076-1076, 1140-1140, 1192-1192, 1275-1275, 1310-1310, 1321-1321, 1355-1355


346-347: Make prop readonly (consistency with props policy)

Mark searchInputRef as readonly to align with the “always readonly” guideline.

As per coding guidelines

-  searchInputRef: React.RefObject<HTMLInputElement | null>;
+  readonly searchInputRef: React.RefObject<HTMLInputElement | null>;
🧹 Nitpick comments (3)
components/memelab/MemeLabPage.tsx (1)

63-65: Clean up import after removing wrapper

Remove TransferProvider import since TransferSingle already provides context.

-import TransferSingle from "../nft-transfer/TransferSingle";
-import { TransferProvider } from "../nft-transfer/TransferState";
+import TransferSingle from "../nft-transfer/TransferSingle";
components/nft-transfer/TransferModal.tsx (2)

790-800: Remove duplicate MANIFOLD_CORE_ABI; reuse the top-level constant

The ABI is defined at Lines 72-81 and again inside groupByContractAndOriginator. Keep a single definition.

-      // minimal Manifold reads
-      const MANIFOLD_CORE_ABI = [
-        {
-          type: "function",
-          name: "tokenExtension",
-          stateMutability: "view",
-          inputs: [{ name: "tokenId", type: "uint256" }],
-          outputs: [{ type: "address" }],
-        },
-      ] as const;

And keep using MANIFOLD_CORE_ABI from the module scope.

Also applies to: 72-81


907-909: Avoid console. in production paths*

Minimize console.log/warn/error or gate behind a debug flag to keep logs clean.

Also applies to: 938-940, 1074-1074, 1178-1190

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69f5cc6 and b626c11.

📒 Files selected for processing (8)
  • __tests__/components/NftNavigation.test.tsx (2 hunks)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/nft-transfer/TransferSingle.test.tsx (1 hunks)
  • components/memelab/MemeLabPage.tsx (4 hunks)
  • components/nextGen/collections/nextgenToken/NextGenToken.tsx (7 hunks)
  • components/nft-navigation/NftNavigation.tsx (4 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
  • components/the-memes/MemePage.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

**/*.{ts,tsx}: Use TypeScript for source code and follow existing code style and naming conventions
Adhere to clean code standards as measured by SonarQube

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • components/memelab/MemeLabPage.tsx
  • components/nextGen/collections/nextgenToken/NextGenToken.tsx
  • components/nft-navigation/NftNavigation.tsx
  • components/the-memes/MemePage.tsx
  • __tests__/components/NftNavigation.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • components/nft-transfer/TransferModal.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Implement React components as functional components using hooks (no class components)

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • components/memelab/MemeLabPage.tsx
  • components/nextGen/collections/nextgenToken/NextGenToken.tsx
  • components/nft-navigation/NftNavigation.tsx
  • components/the-memes/MemePage.tsx
  • __tests__/components/NftNavigation.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
  • components/nft-transfer/TransferModal.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/NftNavigation.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/NftNavigation.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
{**/__tests__/**,**/*.test.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place tests in tests directories or alongside components as ComponentName.test.tsx

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/NftNavigation.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
{**/__tests__/**,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (AGENTS.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/nft-transfer/TransferSingle.test.tsx
  • __tests__/components/NftNavigation.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Use react-query for data fetching

Applied to files:

  • components/nft-transfer/TransferModal.tsx
🧬 Code graph analysis (6)
__tests__/components/nft-transfer/TransferSingle.test.tsx (2)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (21-77)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (32-38)
components/memelab/MemeLabPage.tsx (3)
components/nft-transfer/TransferState.tsx (1)
  • TransferProvider (46-166)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (32-38)
constants.ts (1)
  • MEMES_CONTRACT (5-5)
components/nextGen/collections/nextgenToken/NextGenToken.tsx (4)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
helpers/Helpers.ts (1)
  • areEqualAddresses (145-150)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (32-38)
constants.ts (1)
  • NEXTGEN_CONTRACT (6-6)
__tests__/components/NftNavigation.test.tsx (2)
helpers/Helpers.ts (2)
  • enterArtFullScreen (168-191)
  • fullScreenSupported (152-166)
components/nft-navigation/NftNavigation.tsx (1)
  • NftNavigation (12-66)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (723-1369)
components/nft-transfer/TransferModal.tsx (7)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-39)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (13-83)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (168-172)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
services/api/common-api.ts (1)
  • commonApiFetch (18-45)
helpers/server.helpers.ts (1)
  • getUserProfile (10-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (28)
components/the-memes/MemePage.tsx (1)

352-352: Query param preservation — LGTM

Passing searchParams to NftNavigation aligns with the new params API.

components/memelab/MemeLabPage.tsx (1)

1191-1192: NftNavigation params — LGTM

Passing searchParams to preserve query across navigation is correct.

components/nft-transfer/TransferModal.tsx (2)

1116-1127: Good guard for destination wallet

Early-returning with a clear error when selectedWallet is missing/invalid is correct.


515-525: Close control semantics — LGTM

Accessible button wrapping the icon is correct; no invalid props on FontAwesomeIcon.

__tests__/components/NftNavigation.test.tsx (1)

69-86: Tests for query param preservation — LGTM

Covers the new params prop behavior effectively.

components/nft-navigation/NftNavigation.tsx (3)

1-10: LGTM!

The new imports (ReadonlyURLSearchParams and useMemo) are correctly used to support query parameter preservation in navigation links.


12-21: LGTM!

The optional params prop is correctly typed and follows Next.js conventions for passing search parameters.


49-66: LGTM!

The query string is correctly appended to both previous and next navigation links, preserving URL parameters across navigation.

__tests__/components/nft-transfer/TransferModal.test.tsx (7)

1-53: LGTM!

Comprehensive mock setup covering all external dependencies. The displayName properties on mocked components are a good practice for debugging.


54-114: LGTM!

Test data is well-structured with both ERC1155 and ERC721 items, providing comprehensive coverage for different contract types.


115-174: LGTM!

Thorough test setup and cleanup. The useRealTimers call in afterEach ensures proper cleanup of fake timers used in tests.


176-205: LGTM!

The selectRecipientFlow helper effectively encapsulates a common test flow with proper fake timer management for debounce testing.


207-211: LGTM!

Clear test verifying the UX constraint that prevents transfers without wallet selection.


213-257: LGTM!

Comprehensive end-to-end test covering both ERC1155 batch and ERC721 individual transfers with proper wagmi mock interactions and UI verification.


259-274: LGTM!

Solid error path testing for wallet unavailability. The broad error message regex on line 271 provides flexibility but ensure it doesn't inadvertently pass with unrelated error messages.

__tests__/components/nft-transfer/TransferSingle.test.tsx (13)

1-20: LGTM!

Appropriate mock setup for component testing with proper isolation of external dependencies.


22-54: LGTM!

Comprehensive TransferState mock providing full control over state and functions for testing.


56-85: LGTM!

The SeizeConnectContext mock pattern using exported __state provides good test controllability, though it's tightly coupled to test needs.


87-98: LGTM!

Clean mock setup for device detection with appropriate TypeScript typing.


100-115: LGTM!

Thorough reset function ensuring proper test isolation by resetting all mock state and functions.


117-137: LGTM!

Well-structured test suite with proper lifecycle management and clear baseline rendering test.


139-143: LGTM!

Clear test verifying the component correctly returns null on mobile devices.


145-157: LGTM!

Important lifecycle test verifying proper state management during mount/unmount with correct composite key handling.


159-167: LGTM!

Correct test verifying +/- controls are hidden when max = 1. The test IDs have been properly fixed as noted in past reviews.


169-186: LGTM!

Comprehensive boundary testing for +/- controls with proper accessibility attribute verification at both min and max values.


188-199: LGTM!

Solid interaction test verifying that clicking +/- buttons correctly invokes the quantity change callbacks.


201-209: LGTM!

Good UX test verifying dynamic button label generation for ERC1155 items with quantity pluralization.


211-256: LGTM!

Excellent test coverage of modal and connection flows:

  • Immediate modal open when connected
  • Connect-first flow with proper state transitions
  • Reactivity to prop changes

Comment thread components/memelab/MemeLabPage.tsx Outdated
Comment thread components/nft-navigation/NftNavigation.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Nov 5, 2025

Please retry analysis of this Pull-Request directly on SonarQube Cloud

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 (2)
components/nft-transfer/TransferModal.tsx (1)

551-555: Remove inline TSX comments to meet project rules.

The TS/TSX guideline forbids comments, yet there are still comment lines here (and elsewhere, e.g., around Lines 872, 1216, 1270, 1403). Please delete these comment lines so the file complies. As per coding guidelines

__tests__/components/nft-transfer/TransferModal.test.tsx (1)

221-229: Strip inline comments from the test file.

The no-comments rule for TS/TSX applies here too, but there are multiple // comments (e.g., Lines 221, 298, 354, 389, 441, 555). Remove them to stay compliant. As per coding guidelines

🧹 Nitpick comments (1)
__tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx (1)

43-62: Test disabled state behavior and overlay messaging for MEMELAB.

The test verifies the "N/A" display but doesn't test the disabled state behavior when copiesMax is 0. According to the component logic, this should show an overlay message and prevent interaction.

Consider adding assertions for:

  • Overlay message "Not owned by your connected wallet" when copiesMax is 0
  • Verification that selection controls are not clickable in disabled state
  • Testing isTransferLoading prop effect on overlay messaging (shows "Loading" spinner)

Example assertion for disabled state:

expect(
  screen.getByText("Not owned by your connected wallet")
).toBeInTheDocument();
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28fed79 and ca067ef.

📒 Files selected for processing (3)
  • __tests__/components/nft-transfer/TransferModal.test.tsx (1 hunks)
  • __tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx (1 hunks)
  • components/nft-transfer/TransferModal.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Files:

  • __tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Files:

  • __tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx
  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
🧠 Learnings (13)
📚 Learning: 2025-09-28T12:33:30.950Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:30.950Z
Learning: Applies to __tests__/components/**/*.{ts,tsx,js,jsx} : Use `testing-library/react` and `testing-library/user-event` for React component tests

Applied to files:

  • __tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use FontAwesome for icons

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferModal.tsx
  • __tests__/components/nft-transfer/TransferModal.test.tsx
📚 Learning: 2025-09-28T12:30:53.505Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursor/rules/self_improve.mdc:0-0
Timestamp: 2025-09-28T12:30:53.505Z
Learning: Monitor code review comments for potential rule updates

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use TailwindCSS for styling

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Use react-query for data fetching

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:33:56.329Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: app/api/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:56.329Z
Learning: Applies to app/api/**/*.ts : Use TypeScript types for request parameters and responses; avoid any unless a third-party payload has no shape guarantees

Applied to files:

  • components/nft-transfer/TransferModal.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Keep mock implementations minimal—only what’s necessary for the test scenarios

Applied to files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Keep mocks up to date with the real implementations they represent

Applied to files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Mock only external dependencies or heavy functionality; avoid over-mocking internal logic

Applied to files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Review mocks periodically and remove unused mock modules

Applied to files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Document non-obvious expected behaviour directly in the mock file

Applied to files:

  • __tests__/components/nft-transfer/TransferModal.test.tsx
🧬 Code graph analysis (3)
__tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx (2)
components/user/collected/cards/UserPageCollectedCard.tsx (1)
  • UserPageCollectedCard (19-343)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
components/nft-transfer/TransferModal.tsx (7)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-39)
entities/IProfile.ts (1)
  • CommunityMemberMinimal (307-318)
components/nft-transfer/TransferModalPfp.tsx (1)
  • TransferModalPfp (12-52)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (166-170)
hooks/useIdentity.ts (1)
  • useIdentity (18-34)
hooks/useDebouncedValue.ts (1)
  • useDebouncedValue (3-10)
helpers/server.helpers.ts (1)
  • getUserProfile (10-21)
__tests__/components/nft-transfer/TransferModal.test.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (792-1488)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
__tests__/components/user/collected/cards/UserPageCollectedCard.test.tsx (1)

6-15: Good type safety improvement.

The test data is now properly typed as CollectedCard without type casts. This addresses the previous review concern about type safety.

Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

♻️ Duplicate comments (2)
components/user/collected/cards/UserPageCollectedCard.tsx (1)

187-187: Add explicit color prop for icon consistency.

The faCheck icon lacks an explicit color prop, while all other FontAwesome icons in the overlay controls (faPlus, faMinusCircle, faPlusCircle) explicitly set color="#fff". This inconsistency may cause unexpected rendering behavior in different contexts.

Apply this diff:

-              <FontAwesomeIcon icon={faCheck} className="tw-size-5" />
+              <FontAwesomeIcon icon={faCheck} className="tw-size-5" color="#fff" />
components/nft-transfer/TransferSingle.tsx (1)

132-146: Stop flashing 0 quantity before state hydrates

We’re still rendering {selectedQty} directly, so every mount (and any time the selection map is cleared) shows a brief 0/<max> before the effect repopulates the item. Let’s default the display value to 1 so the UI doesn’t flicker.

-  const selectedQty = t.selected.get(key)?.qty ?? 0;
+  const selectedQty = t.selected.get(key)?.qty ?? 0;
+  const displayQty = selectedQty === 0 ? 1 : selectedQty;-            <div className="tw-min-w-[2ch] tw-text-center tw-text-sm tw-tabular-nums tw-select-none">
-              {selectedQty}/{max}
+            <div className="tw-min-w-[2ch] tw-text-center tw-text-sm tw-tabular-nums tw-select-none">
+              {displayQty}/{max}
             </div>
🧹 Nitpick comments (2)
components/user/collected/cards/UserPageCollectedCard.tsx (1)

138-143: Clarify condition for deselection on decrement.

The condition qtySelected <= 1 is defensive but potentially confusing. Since this code is within the isSelectedAndCanSelect branch, qtySelected should always be at least 1 (otherwise the item wouldn't be selected). Using === 1 makes the intent clearer: when decrementing from exactly 1 copy, deselect the item.

Apply this diff for clarity:

-                  if (qtySelected <= 1) {
+                  if (qtySelected === 1) {
                     onDecQty();
                     onToggle();
                   } else {
__tests__/components/common/TabToggleWithOverflow.test.tsx (1)

13-24: Reuse existing delay helper.

There's already a shared delay helper at components/waves/drops/wave-drops-all/utils/delay.ts. Importing that here keeps the behavior consistent and avoids another ad‑hoc timer wrapper.

-import { act, render, screen, waitFor } from "@testing-library/react";
+import { act, render, screen, waitFor } from "@testing-library/react";
+import { delay } from "@/components/waves/drops/wave-drops-all/utils/delay";
 import userEvent from "@testing-library/user-event";
@@
-const delay = (ms: number) =>
-  new Promise((resolve) => setTimeout(resolve, ms));
-
 const ensureButtonFocused = async (button: HTMLElement) => {
   await act(async () => {
     button.focus();
     await delay(50);
     if (document.activeElement !== button) {
       button.focus();
     }
   });
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb356f0 and 3003141.

📒 Files selected for processing (4)
  • __tests__/components/common/TabToggleWithOverflow.test.tsx (6 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
  • components/user/collected/cards/UserPageCollectedCard.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/nft-transfer/TransferPanel.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Files:

  • __tests__/components/common/TabToggleWithOverflow.test.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/nft-transfer/TransferSingle.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Files:

  • __tests__/components/common/TabToggleWithOverflow.test.tsx
  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/nft-transfer/TransferSingle.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/common/TabToggleWithOverflow.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/common/TabToggleWithOverflow.test.tsx
🧠 Learnings (4)
📚 Learning: 2025-09-28T12:33:30.950Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:30.950Z
Learning: Applies to __tests__/components/**/*.{ts,tsx,js,jsx} : Use `testing-library/react` and `testing-library/user-event` for React component tests

Applied to files:

  • __tests__/components/common/TabToggleWithOverflow.test.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use TailwindCSS for styling

Applied to files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
  • components/nft-transfer/TransferSingle.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use FontAwesome for icons

Applied to files:

  • components/user/collected/cards/UserPageCollectedCard.tsx
🧬 Code graph analysis (3)
__tests__/components/common/TabToggleWithOverflow.test.tsx (1)
components/waves/drops/wave-drops-all/utils/delay.ts (1)
  • delay (1-4)
components/user/collected/cards/UserPageCollectedCard.tsx (3)
entities/IProfile.ts (1)
  • CollectedCard (408-417)
helpers/Helpers.ts (1)
  • formatNumberWithCommasOrDash (121-124)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-39)
components/nft-transfer/TransferSingle.tsx (4)
components/nft-transfer/TransferState.tsx (3)
  • TransferProvider (44-164)
  • useTransfer (166-170)
  • buildTransferKey (172-183)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (23-93)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (792-1488)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
__tests__/components/common/TabToggleWithOverflow.test.tsx (1)

91-139: Great keyboard coverage.

Nice job exercising the overflow trigger via keyboard, including both Enter and Space paths and asserting the aria-expanded transitions—it gives strong confidence in the accessible interaction.

Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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

🧹 Nitpick comments (2)
components/nft-transfer/TransferPanel.tsx (1)

245-246: Consider defensive handling for key format.

The code assumes it.key always follows the "collection:tokenId" format. If buildTransferKey guarantees this format, document it. Otherwise, add validation to handle malformed keys gracefully.

Apply this diff to add defensive handling:

-                      const [collection, tokenId] = it.key.split(":");
-                      const label = `${collection} #${tokenId}`;
+                      const parts = it.key.split(":");
+                      const label = parts.length === 2 
+                        ? `${parts[0]} #${parts[1]}`
+                        : it.title ?? it.key;
components/memelab/MemeLabPage.tsx (1)

171-172: Refactor duplicated wallet extraction logic.

The wallet extraction pattern appears twice (lines 171-172 and lines 561-562). Extract this to a useMemo at the component level to avoid duplication and ensure consistency.

Apply this refactor:

+  const wallets = useMemo(() => {
+    const walletObjects = connectedProfile?.wallets ?? [];
+    return walletObjects.map((w) => w.wallet);
+  }, [connectedProfile?.wallets]);
+
   useEffect(() => {
-    const walletObjects = connectedProfile?.wallets ?? [];
-    const wallets = walletObjects.map((w) => w.wallet);
     if (wallets.length > 0 && nftId) {

And remove the duplicate at lines 561-562:

   function printYourCards() {
     const firstAcquired = [...transactions].sort((a, b) =>
       a.transaction_date > b.transaction_date ? 1 : -1
     )[0];
 
     const airdropped = transactions.filter(
       (t) => t.value === 0 && areEqualAddresses(t.from_address, NULL_ADDRESS)
     );
 
-    const walletObjects = connectedProfile?.wallets ?? [];
-    const wallets = walletObjects.map((w) => w.wallet);
     const transferredIn =

Also applies to: 561-562

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3003141 and e228844.

📒 Files selected for processing (3)
  • components/memelab/MemeLabPage.tsx (9 hunks)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferSingle.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/nft-transfer/TransferSingle.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Files:

  • components/nft-transfer/TransferPanel.tsx
  • components/memelab/MemeLabPage.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Files:

  • components/nft-transfer/TransferPanel.tsx
  • components/memelab/MemeLabPage.tsx
🧠 Learnings (2)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferPanel.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use TailwindCSS for styling

Applied to files:

  • components/nft-transfer/TransferPanel.tsx
🧬 Code graph analysis (2)
components/nft-transfer/TransferPanel.tsx (1)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (792-1488)
components/memelab/MemeLabPage.tsx (2)
services/6529api.ts (1)
  • fetchAllPages (22-37)
components/nft-transfer/TransferSingle.tsx (1)
  • TransferSingle (32-38)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
components/memelab/MemeLabPage.tsx (2)

653-665: LGTM!

The TransferSingle integration is correct:

  • Uses MEMELAB_CONTRACT ✅
  • Uses CollectedCollectionType.MEMELAB ✅
  • No unnecessary TransferProvider wrapper ✅
  • Conditional rendering is appropriate ✅

227-227: LGTM!

The generic typing for fetchAllPages<NFTHistory> correctly matches the refactored API helper signature.

Comment thread components/nft-transfer/TransferPanel.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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/nft-transfer/TransferState.tsx (1)

34-34: Remove comment per coding guidelines.

This inline comment was flagged in a previous review and marked as addressed in commit 520c4b2, but it still remains in the code.

Apply this diff:

-  /** quantity controls */
   setQty: (key: string, qty: number) => void;

As per coding guidelines

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e228844 and 078d2e0.

📒 Files selected for processing (2)
  • components/nft-transfer/TransferPanel.tsx (1 hunks)
  • components/nft-transfer/TransferState.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Files:

  • components/nft-transfer/TransferPanel.tsx
  • components/nft-transfer/TransferState.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Files:

  • components/nft-transfer/TransferPanel.tsx
  • components/nft-transfer/TransferState.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferPanel.tsx
  • components/nft-transfer/TransferState.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use TailwindCSS for styling

Applied to files:

  • components/nft-transfer/TransferPanel.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferState.tsx
🧬 Code graph analysis (1)
components/nft-transfer/TransferPanel.tsx (4)
components/nft-transfer/TransferState.tsx (1)
  • useTransfer (201-205)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
components/distribution-plan-tool/common/CircleLoader.tsx (1)
  • CircleLoader (9-39)
components/nft-transfer/TransferModal.tsx (1)
  • TransferModal (792-1488)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)

Comment thread components/nft-transfer/TransferPanel.tsx
Comment thread components/nft-transfer/TransferState.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

♻️ Duplicate comments (2)
components/nft-transfer/TransferState.tsx (2)

34-34: Remove the inline comment.

The inline comment violates the coding guidelines for TS/TSX files.

Apply this diff:

-  /** quantity controls */
   setQty: (key: string, qty: number) => void;

As per coding guidelines


60-60: Fix the type signature to support functional updates.

The callback type only accepts boolean, but line 151 passes a function (v) => !v. This breaks the functional state update pattern and will cause a type error.

Apply this diff to fix the type:

-  const setEnabledStable = useCallback((v: boolean) => setEnabledRaw(v), []);
+  const setEnabledStable = useCallback(
+    (v: boolean | ((prev: boolean) => boolean)) => setEnabledRaw(v),
+    []
+  );
🧹 Nitpick comments (1)
components/nft-transfer/TransferState.tsx (1)

100-105: Consider simplifying the Map construction.

The code creates an intermediate array with Array.from(next.entries()) which is unnecessary—you can iterate next directly.

Apply this diff to iterate directly:

         const newMap = new Map();
         newMap.set(item.key, newItem);
-        for (const [key, value] of Array.from(next.entries())) {
+        for (const [key, value] of next) {
           newMap.set(key, value);
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 078d2e0 and 128b1dd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • components/nft-transfer/TransferState.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Files:

  • components/nft-transfer/TransferState.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Files:

  • components/nft-transfer/TransferState.tsx
🧠 Learnings (2)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Do not include any comments in the code

Applied to files:

  • components/nft-transfer/TransferState.tsx
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.{ts,tsx} : Always add readonly before props

Applied to files:

  • components/nft-transfer/TransferState.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
components/nft-transfer/TransferState.tsx (4)

1-10: LGTM!

The imports and client directive are appropriate for a stateful React context provider.


46-58: LGTM!

The clamp utility is correct, and the provider initialization properly uses readonly props.


154-196: LGTM!

The derived values and memoized API are correctly structured with appropriate dependencies.


198-220: LGTM!

The provider return, useTransfer hook, and buildTransferKey utility follow React best practices correctly.

Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Nov 5, 2025

@prxt6529 prxt6529 merged commit 1aeb90d into main Nov 5, 2025
8 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Nov 18, 2025
This was referenced Dec 12, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Jan 23, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Mar 9, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Mar 17, 2026
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