Skip to content

Lint issues v3#1597

Closed
simo6529 wants to merge 23 commits intomainfrom
lint-issues-v3
Closed

Lint issues v3#1597
simo6529 wants to merge 23 commits intomainfrom
lint-issues-v3

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Nov 6, 2025

Summary by CodeRabbit

  • New Features

    • Distribution listing now includes photos and improved paginated fetching.
  • Bug Fixes

    • More reliable infinite-scroll behavior and fewer stale reloads across lists.
    • More stable data for gas and royalties views.
  • Refactor

    • Download flow simplified (no confirmation modal); clearer loading indicators and accessibility states.
    • Streamlined drop creation UI with reduced props, memoized behaviors, and refined animations.
  • Tests

    • Expanded coverage for snapshots, downloads, animations, groups, and token-fetch flows.

Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 6, 2025

Walkthrough

Tightens React hook dependency arrays, memoizes callbacks/values, migrates several local fetches to React Query (hooks/mutations), removes unused props/state, refactors mojs animation setup and typings, and updates tests to use a real QueryClientProvider. (50 words)

Changes

Cohort / File(s) Summary
Intersection / Pagination
components/brain/direct-messages/DirectMessagesList.tsx, components/drops/view/Drops.tsx
Updated IntersectionObserver/effect dependency arrays to include helper refs/length and fetchNextPageIfNeeded; switched to local observer refs with tightened null checks and observe/unobserve lifecycle.
Distribution queries & keys
components/distribution/useDistributionQueries.ts, components/react-query-wrapper/ReactQueryWrapper.tsx, components/distribution/Distribution.tsx
Added useDistributionData and useDistributionPhotos React Query hooks; added new QueryKey entries and refactored Distribution to consume hooks and derive phases/photos via memoization.
Snapshots: mutations & downloads
components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx, components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx, components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx, __tests__/*CreateSnapshot*
Replaced direct token fetches with React Query mutation and useCallback; added loading/aria states and spinner; split JSON/CSV download flows into dedicated mutations; tests wrapped with QueryClientProvider.
Memoization & dependency fixes
components/drops/create/lexical/plugins/hashtags/HashtagsPlugin.tsx, components/drops/create/lexical/plugins/mentions/MentionsPlugin.tsx, components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx, components/drops/view/DropsList.tsx, components/groups/page/create/config/wallets/CreateGroupWallets.tsx
Fixed missing deps and added useCallback/useMemo wrappers to avoid stale closures and unnecessary recreations (e.g., include onSelect, fetchTokenPoolStatuses, location, setWallets).
Derived state → memo/computed
components/drops/create/utils/CreateDropWrapper.tsx, components/drops/create/utils/storm/CreateDropStormViewPartQuote.tsx, components/groups/page/GroupsPageListWrapper.tsx, components/groups/page/list/card/GroupCardActionWrapper.tsx, components/drops/view/item/rate/give/DropListItemRateGive.tsx
Replaced several useState/useEffect patterns with useMemo or direct computed values; removed coordinating effects and redundant local state.
Gas & Royalties → useQuery
components/gas-royalties/Gas.tsx, components/gas-royalties/Royalties.tsx, components/gas-royalties/GasRoyalties.tsx
Replaced manual fetch/state with React Query useQuery; memoized URL builders and totals; stabilized fetching and focus gating via useCallback/useMemo.
Context cleanup (removed setToasts)
components/distribution-plan-tool/map-delegations/MapDelegationsForm.tsx, components/distribution-plan-tool/review-distribution-plan/table/*.tsx
Removed setToasts destructuring and an unused reset helper; narrowed catch typing to unknown where applicable.
Component API / prop removals
components/drops/create/{compact,full,desktop,mobile}/CreateDrop*.tsx, components/drops/create/DropEditor.tsx, components/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsx, tests
Removed unused props/interfaces (profile, metadata, setMentionedUsers, CreateDropFullWaveProps), updated signatures/usages and corresponding tests.
Enter-key & lexical submit flow
components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
Introduced useEffectEvent wrappers (shouldHandleEnter, submit) and rewired ENTER handling to centralize submit logic and avoid stale closures.
Animation refactor & typings
components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx, types/mojs.d.ts, __tests__/*clap*
Replaced stateful animation with mojs instances in refs, added stop() cleanup calls, expanded @mojs/core typings, and updated tests/mocks to include stop/replay lifecycle.
Small UI/DOM cleanups
components/downloadUrlWidget/DownloadUrlWidget.tsx, components/drops/create/lexical/nodes/ImageNode.tsx
Removed confirmation modal and related imports; renamed unused function parameter to _node.
Groups page & GroupCard adjustments
components/groups/page/Groups.tsx, components/groups/page/list/card/GroupCard.tsx, components/groups/header/GroupHeaderSelect.tsx, components/groups/page/create/GroupCreate.tsx, components/groups/page/list/card/GroupCardActionWrapper.tsx
Centralized connected handle, used useCallback for view-mode changes, simplified haveProfile derivation, inlined address derivation, and tightened effect guards for vote idle/reset behavior.
Tests & mocks updates
__tests__/* (several files)
Tests updated to use QueryClientProvider, removed now-unused props, extended @mojs/core mocks (stop), added async loading-state assertions, and adjusted router mock behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DirectList as DirectMessagesList
    participant Observer
    participant Fetch as fetchNextPageIfNeeded

    Note over DirectList,Observer: IntersectionObserver effect now depends on helper refs/length and fetchNextPageIfNeeded
    User->>DirectList: scroll to bottom
    DirectList->>Observer: intersection callback fires
    Observer->>Fetch: call fetchNextPageIfNeeded()
    Fetch-->>DirectList: returns (fetch started / no-op)
    DirectList->>Observer: observe / unobserve using local observer ref
Loading
sequenceDiagram
    participant User
    participant Clap as DropListItemRateGiveClap
    participant Mojs as "@mojs/core"
    participant TLRef as animationTimelineRef

    User->>Clap: click
    Clap->>TLRef: timeline exists?
    alt timeline exists
        TLRef->>Mojs: replay()
    else
        Clap->>Mojs: create Burst/Html/Timeline instances
        Mojs-->>TLRef: timeline stored in ref
        TLRef->>Mojs: replay()
    end
    Note over Clap,Mojs: on unmount -> call stop() on instances (cleanup)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas needing extra attention:
    • components/distribution/Distribution.tsx and new hooks in components/distribution/useDistributionQueries.ts (pagination, placeholderData, query keys).
    • components/gas-royalties/{Gas,Royalties,GasRoyalties}.tsx (query behavior, URL builders, gating/enabled flags).
    • components/drops/create/utils/CreateDropWrapper.tsx (memoized validation/submit flows and removed prop).
    • components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx and types/mojs.d.ts (animation lifecycle, typings, and test mocks).
    • Tests adjusted to rely on QueryClientProvider and updated mojs mocks / async expectations.

Possibly related PRs

Suggested reviewers

  • prxt6529

Poem

🐇
I hopped through hooks and tended each thread,
memoized carrots and cleared up the spread.
Queries now hum, timelines leap high,
tests wait patient for Query's reply.
A tidy nibble — ready to ship — hop! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.13% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Lint issues v3' is vague and generic, using non-descriptive terminology that doesn't convey meaningful information about the changeset despite extensive modifications across 40+ files. Consider a more descriptive title that summarizes the primary changes, such as 'Refactor components to improve type safety, remove unused props, and optimize dependencies' or 'v3: Fix linting issues and improve code quality across distribution and drops components'.
✅ 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 lint-issues-v3

📜 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 9394905 and 05e5a07.

📒 Files selected for processing (1)
  • components/gas-royalties/GasRoyalties.tsx (3 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/gas-royalties/GasRoyalties.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/gas-royalties/GasRoyalties.tsx
🧠 Learnings (2)
📓 Common learnings
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
📚 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/gas-royalties/GasRoyalties.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 (2)
components/gas-royalties/GasRoyalties.tsx (2)

14-14: LGTM: useCallback import added.

The import is necessary for the memoization pattern applied to the getUrl function.


381-406: LGTM: Proper memoization with complete dependency array.

The getUrl function is correctly memoized with useCallback, and all dependencies are properly included in the dependency array. This prevents unnecessary re-creation of the function and improves performance when passed as a prop.


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

Caution

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

⚠️ Outside diff range comments (10)
components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (2)

45-45: Remove comments per coding guidelines.

The coding guidelines specify: "Do not include any comments in the code" for TypeScript files. Please remove all inline comments from this file.

As per coding guidelines

Also applies to: 59-59, 68-68, 131-132, 160-160, 167-167, 194-194


133-158: Remove unused dependency isInProgress.

Line 155 includes isInProgress in the dependency array, but it's not used anywhere in the effect body. The votingState calculation only uses isUpcoming and isCompleted. Including unused dependencies causes unnecessary re-renders.

Apply this diff:

   }, [
     wave,
     isMemesWave,
     isChatWave,
     isUpcoming,
     isCompleted,
-    isInProgress,
     firstDecisionDone,
     updateAvailableTabs,
   ]);
components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (3)

52-62: Use react-query for data fetching per coding guidelines.

The manual fetch implementation violates the coding guidelines which specify: "Use react-query for data fetching". Consider using useMutation or a query hook to benefit from built-in loading states, error handling, caching, and retry logic.

As per coding guidelines.


26-32: Add readonly modifiers to props per coding guidelines.

The coding guidelines specify: "Always add readonly before props". The props interface should include readonly modifiers for consistency with the rest of the codebase (e.g., CollectionMeta interface above).

Apply this diff:

 }) {
-  collection: DistributionPlanSearchContractMetadataResult;
-  onCollection: (param: {
-    address: string;
-    name: string;
-    tokenIds: string | null;
-  }) => void;
+  readonly collection: DistributionPlanSearchContractMetadataResult;
+  readonly onCollection: (param: {
+    address: string;
+    name: string;
+    tokenIds: string | null;
+  }) => void;
 }) {

As per coding guidelines.


64-81: Add error handling for async operations.

The async function onCollectionClick calls getTokenIdsString, which can fail, but there's no error handling. Unhandled promise rejections could occur, and users would receive no feedback if the operation fails. Consider adding try-catch blocks and providing user notification on errors.

Example:

const onCollectionClick = async () => {
  try {
    const regex = /^0x[0-9a-fA-F]{40}:.+$/;
    const isSubCollection = regex.test(collection.id);
    if (isSubCollection) {
      const tokenIdsString = await getTokenIdsString(collection.id);
      onCollection({
        name: collection.name,
        address: collection.address,
        tokenIds: tokenIdsString?.length ? tokenIdsString : null,
      });
      return;
    }
    onCollection({
      name: collection.name,
      address: collection.address,
      tokenIds: null,
    });
  } catch (error) {
    console.error('Failed to fetch collection:', error);
  }
};
components/brain/direct-messages/DirectMessagesList.tsx (1)

59-81: Fix the effect dependency to use list.length instead of hasListItems.

Using the boolean hasListItems as a dependency causes the IntersectionObserver effect to only re-run when the list transitions between empty and non-empty states. This misses intermediate length changes (e.g., 1→2 items, 5→10 items), which could prevent proper observer re-setup when the list grows.

Apply this diff:

-  const hasListItems = list.length > 0;
-
   useEffect(() => {
     const listHandle = listRef.current;
     const sentinel = listHandle?.sentinelRef.current;
 
     if (!sentinel || !hasNextPage || isFetchingNextPage) {
       return;
     }
 
     const observer = new IntersectionObserver(([entry]) => {
       if (entry.isIntersecting) {
         fetchNextPageIfNeeded();
       }
     }, {
       root: listHandle?.containerRef.current,
       rootMargin: "100px",
     });
 
     observer.observe(sentinel);
 
     return () => observer.disconnect();
-  }, [hasNextPage, isFetchingNextPage, hasListItems]);
+  }, [hasNextPage, isFetchingNextPage, list.length, fetchNextPageIfNeeded]);
components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (1)

27-28: Fix duplicate requestAuth() call.

The function calls requestAuth() twice consecutively, with the first call's result being ignored. This is unnecessary and potentially creates duplicate authentication attempts.

Apply this diff to remove the redundant call:

     queryFn: async () => {
-      await requestAuth();
       const { success } = await requestAuth();
       if (!success) {
         return [];
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (3)

14-18: Add readonly modifier to props per coding guidelines.

The props object is missing the readonly modifier on tokenPoolId, which violates the coding guidelines for TypeScript files.

As per coding guidelines

Apply this diff to add the readonly modifier:

 export default function CreateSnapshotTableRowDownload({
   tokenPoolId,
 }: {
-  tokenPoolId: string;
+  readonly tokenPoolId: string;
 }) {

35-47: Add empty array check to prevent runtime error.

Line 37 accesses results[0] without verifying the array has elements. If the API returns an empty array, this will throw a runtime error.

Apply this diff to add a safety check:

 const downloadCsv = (results: DistributionPlanSnapshotToken[]) => {
+  if (results.length === 0) return;
+
   const csv = [
     Object.keys(results[0]).join(","),
     ...results.map((item) => Object.values(item).join(",")),
   ].join("\n");

25-33: Revoke object URL to prevent memory leak.

The object URL created on line 28 should be revoked after the download completes to prevent memory leaks when the function is called multiple times.

Apply this diff to add cleanup:

 const downloadJson = (results: DistributionPlanSnapshotToken[]) => {
   const data = JSON.stringify(results);
   const blob = new Blob([data], { type: "application/json" });
   const url = window.URL.createObjectURL(blob);
   const link = document.createElement("a");
   link.href = url;
   link.download = "results.json";
   link.click();
+  window.URL.revokeObjectURL(url);
 };
🧹 Nitpick comments (4)
components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (1)

69-85: Replace as any with proper typing.

The type assertion as any on line 75 bypasses TypeScript's type safety. Consider defining a proper type or interface for the converted decision format to maintain type safety.

For example:

-        ({
-          decision_time: decision.timestamp,
-        } as any)
+        ({
+          decision_time: decision.timestamp,
+        } satisfies Partial<ApiWaveDecision>)

Or better yet, investigate if filterDecisionsDuringPauses can accept the DecisionPoint type directly to avoid the conversion altogether.

components/drops/create/full/mobile/CreateDropFullMobile.tsx (1)

71-71: Remove the unused profile prop from the component interface and update the parent component accordingly.

The profile prop is passed from the parent component (CreateDropFull.tsx, line 141) but is never used within CreateDropFullMobile.tsx. It can be safely removed from both the CreateDropFullMobileProps interface and the parent's usage.

Update required:

  • components/drops/create/full/mobile/CreateDropFullMobile.tsx (line 35): Remove readonly profile: ProfileMinWithoutSubs; from the interface
  • components/drops/create/full/mobile/CreateDropFullMobile.tsx (line 71): Remove profile: _profile, from destructuring
  • components/drops/create/full/CreateDropFull.tsx (line 141): Remove profile={profile} from the <CreateDropFullMobile> component usage
components/drops/create/compact/CreateDropCompact.tsx (1)

66-67: Review comment verified and accurate — these props are genuinely unused in CreateDropCompact.

The analysis confirms that profile, showProfile, title, metadata, and onMetadataRemove are destructured with underscore prefixes and never referenced in the component body. CreateDropFull actively uses all five of these props (title and metadata are passed to child components; profile and onMetadataRemove are actively used), but CreateDropCompact's compact view variant has no need for them.

CreateDropWrapper is the only caller and passes these props uniformly to both view variants. Removing them from CreateDropCompact would require only updating the interface and the prop-passing logic in CreateDropWrapper—no other files depend on them being passed to the compact variant.

components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (1)

49-76: Consider using react-query for data fetching per coding guidelines.

The coding guidelines specify "Use react-query for data fetching" for TypeScript/TSX files. Currently, this component uses direct fetch calls via distributionPlanApiFetch inside an event handler, which doesn't leverage react-query's caching, deduplication, and state management benefits.

However, the try/finally pattern for resetting loading state is well implemented.

As per coding guidelines

Consider refactoring to use a react-query mutation:

import { useMutation } from '@tanstack/react-query';

export default function CreateSnapshotTableRowDownload({
  tokenPoolId,
}: {
  readonly tokenPoolId: string;
}) {
  const { distributionPlan } = useContext(DistributionPlanToolContext);

  const { mutate: fetchJson, isPending: isLoadingJson } = useMutation({
    mutationFn: async () => {
      if (!distributionPlan) throw new Error('No distribution plan');
      const endpoint = `/allowlists/${distributionPlan.id}/token-pool-downloads/token-pool/${tokenPoolId}/tokens`;
      const { success, data } = await distributionPlanApiFetch<DistributionPlanSnapshotToken[]>(endpoint);
      if (!success || !data) throw new Error('Fetch failed');
      return data;
    },
    onSuccess: (data) => downloadJson(data),
  });

  const { mutate: fetchCsv, isPending: isLoadingCsv } = useMutation({
    mutationFn: async () => {
      if (!distributionPlan) throw new Error('No distribution plan');
      const endpoint = `/allowlists/${distributionPlan.id}/token-pool-downloads/token-pool/${tokenPoolId}/tokens`;
      const { success, data } = await distributionPlanApiFetch<DistributionPlanSnapshotToken[]>(endpoint);
      if (!success || !data) throw new Error('Fetch failed');
      return data;
    },
    onSuccess: (data) => downloadCsv(data),
  });

  return (
    <div className="tw-flex tw-justify-end tw-gap-x-3">
      <RoundedJsonIconButton onClick={() => fetchJson()} loading={isLoadingJson} />
      <RoundedCsvIconButton onClick={() => fetchCsv()} loading={isLoadingCsv} />
    </div>
  );
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e965f1b and 1f8f599.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (41)
  • components/brain/direct-messages/DirectMessagesList.tsx (2 hunks)
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (2 hunks)
  • components/delegation/CollectionDelegation.tsx (1 hunks)
  • components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx (3 hunks)
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (2 hunks)
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx (1 hunks)
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (3 hunks)
  • components/distribution-plan-tool/map-delegations/MapDelegationsForm.tsx (1 hunks)
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableHeader.tsx (1 hunks)
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscription.tsx (1 hunks)
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscriptionFooter.tsx (1 hunks)
  • components/distribution/Distribution.tsx (4 hunks)
  • components/downloadUrlWidget/DownloadUrlWidget.tsx (0 hunks)
  • components/drops/create/compact/CreateDropCompact.tsx (2 hunks)
  • components/drops/create/full/CreateDropFull.tsx (0 hunks)
  • components/drops/create/full/desktop/CreateDropFullDesktop.tsx (1 hunks)
  • components/drops/create/full/mobile/CreateDropFullMobile.tsx (1 hunks)
  • components/drops/create/lexical/nodes/ImageNode.tsx (1 hunks)
  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx (4 hunks)
  • components/drops/create/lexical/plugins/hashtags/HashtagsPlugin.tsx (1 hunks)
  • components/drops/create/lexical/plugins/mentions/MentionsPlugin.tsx (1 hunks)
  • components/drops/create/utils/CreateDropWrapper.tsx (8 hunks)
  • components/drops/create/utils/storm/CreateDropStormViewPartQuote.tsx (3 hunks)
  • components/drops/view/Drops.tsx (1 hunks)
  • components/drops/view/DropsList.tsx (1 hunks)
  • components/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsx (1 hunks)
  • components/drops/view/item/rate/give/DropListItemRateGive.tsx (1 hunks)
  • components/drops/view/item/rate/give/DropListItemRateGiveSubmit.tsx (1 hunks)
  • components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx (6 hunks)
  • components/drops/view/part/dropPartMarkdown/handlers/artBlocks.tsx (0 hunks)
  • components/gas-royalties/Gas.tsx (2 hunks)
  • components/gas-royalties/Royalties.tsx (3 hunks)
  • components/groups/header/GroupHeaderSelect.tsx (1 hunks)
  • components/groups/page/Groups.tsx (2 hunks)
  • components/groups/page/GroupsPageListWrapper.tsx (1 hunks)
  • components/groups/page/create/GroupCreate.tsx (1 hunks)
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (1 hunks)
  • components/groups/page/create/config/wallets/GroupCreateWallets.tsx (2 hunks)
  • components/groups/page/list/card/GroupCard.tsx (1 hunks)
  • components/groups/page/list/card/GroupCardActionWrapper.tsx (2 hunks)
  • types/mojs.d.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • components/drops/create/full/CreateDropFull.tsx
  • components/drops/view/part/dropPartMarkdown/handlers/artBlocks.tsx
  • components/downloadUrlWidget/DownloadUrlWidget.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/brain/direct-messages/DirectMessagesList.tsx
  • components/groups/header/GroupHeaderSelect.tsx
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx
  • components/drops/view/DropsList.tsx
  • components/drops/create/lexical/plugins/mentions/MentionsPlugin.tsx
  • components/drops/create/full/mobile/CreateDropFullMobile.tsx
  • components/gas-royalties/Gas.tsx
  • components/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsx
  • components/drops/create/lexical/nodes/ImageNode.tsx
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscription.tsx
  • components/delegation/CollectionDelegation.tsx
  • components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx
  • components/drops/view/Drops.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/groups/page/create/GroupCreate.tsx
  • components/groups/page/GroupsPageListWrapper.tsx
  • components/gas-royalties/Royalties.tsx
  • components/drops/view/item/rate/give/DropListItemRateGive.tsx
  • components/groups/page/create/config/wallets/GroupCreateWallets.tsx
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableHeader.tsx
  • components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx
  • components/drops/view/item/rate/give/DropListItemRateGiveSubmit.tsx
  • components/drops/create/full/desktop/CreateDropFullDesktop.tsx
  • components/groups/page/Groups.tsx
  • components/groups/page/list/card/GroupCardActionWrapper.tsx
  • components/distribution-plan-tool/map-delegations/MapDelegationsForm.tsx
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscriptionFooter.tsx
  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
  • components/distribution/Distribution.tsx
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx
  • types/mojs.d.ts
  • components/drops/create/lexical/plugins/hashtags/HashtagsPlugin.tsx
  • components/drops/create/utils/storm/CreateDropStormViewPartQuote.tsx
  • components/groups/page/list/card/GroupCard.tsx
  • components/drops/create/compact/CreateDropCompact.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/brain/direct-messages/DirectMessagesList.tsx
  • components/groups/header/GroupHeaderSelect.tsx
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx
  • components/drops/view/DropsList.tsx
  • components/drops/create/lexical/plugins/mentions/MentionsPlugin.tsx
  • components/drops/create/full/mobile/CreateDropFullMobile.tsx
  • components/gas-royalties/Gas.tsx
  • components/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsx
  • components/drops/create/lexical/nodes/ImageNode.tsx
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscription.tsx
  • components/delegation/CollectionDelegation.tsx
  • components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx
  • components/drops/view/Drops.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/groups/page/create/GroupCreate.tsx
  • components/groups/page/GroupsPageListWrapper.tsx
  • components/gas-royalties/Royalties.tsx
  • components/drops/view/item/rate/give/DropListItemRateGive.tsx
  • components/groups/page/create/config/wallets/GroupCreateWallets.tsx
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableHeader.tsx
  • components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx
  • components/drops/view/item/rate/give/DropListItemRateGiveSubmit.tsx
  • components/drops/create/full/desktop/CreateDropFullDesktop.tsx
  • components/groups/page/Groups.tsx
  • components/groups/page/list/card/GroupCardActionWrapper.tsx
  • components/distribution-plan-tool/map-delegations/MapDelegationsForm.tsx
  • components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscriptionFooter.tsx
  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
  • components/distribution/Distribution.tsx
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx
  • components/drops/create/lexical/plugins/hashtags/HashtagsPlugin.tsx
  • components/drops/create/utils/storm/CreateDropStormViewPartQuote.tsx
  • components/groups/page/list/card/GroupCard.tsx
  • components/drops/create/compact/CreateDropCompact.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx
🧠 Learnings (1)
📚 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/drops/create/utils/CreateDropWrapper.tsx
🧬 Code graph analysis (9)
components/groups/header/GroupHeaderSelect.tsx (1)
components/auth/Auth.tsx (1)
  • AuthContext (83-93)
components/gas-royalties/Gas.tsx (3)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IGas.ts (1)
  • Gas (1-8)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/drops/create/utils/CreateDropWrapper.tsx (5)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
components/drops/create/lexical/transformers/markdownTransformers.ts (1)
  • SAFE_MARKDOWN_TRANSFORMERS (42-42)
components/drops/create/lexical/transformers/MentionTransformer.ts (1)
  • MENTION_TRANSFORMER (4-32)
components/drops/create/lexical/transformers/HastagTransformer.ts (1)
  • HASHTAG_TRANSFORMER (4-32)
components/drops/create/lexical/transformers/ImageTransformer.ts (1)
  • IMAGE_TRANSFORMER (4-22)
components/gas-royalties/Royalties.tsx (3)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableHeader.tsx (1)
components/distribution-plan-tool/DistributionPlanToolContext.tsx (1)
  • DistributionPlanToolContext (86-105)
components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx (2)
types/mojs.d.ts (1)
  • MojsTimelineInstance (71-71)
helpers/AllowlistToolHelpers.ts (1)
  • getRandomObjectId (46-48)
components/distribution/Distribution.tsx (2)
entities/IDistribution.ts (2)
  • Distribution (6-19)
  • DistributionPhoto (21-28)
services/6529api.ts (2)
  • fetchUrl (7-20)
  • fetchAllPages (22-37)
components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (1)
components/distribution-plan-tool/DistributionPlanToolContext.tsx (1)
  • DistributionPlanToolContext (86-105)
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (4)
components/distribution-plan-tool/DistributionPlanToolContext.tsx (1)
  • DistributionPlanToolContext (86-105)
services/distribution-plan-api.ts (1)
  • distributionPlanApiFetch (38-62)
components/allowlist-tool/allowlist-tool.types.ts (1)
  • DistributionPlanSnapshotToken (199-204)
helpers/AllowlistToolHelpers.ts (1)
  • assertUnreachable (53-58)
🪛 Biome (2.1.2)
types/mojs.d.ts

[error] 42-42: Do not add then to a class.

(lint/suspicious/noThenProperty)

🔇 Additional comments (26)
components/drops/create/utils/storm/CreateDropStormViewPartQuote.tsx (1)

47-69: LGTM! Clean refactoring to derived state.

The refactoring from state+useEffect to useMemo is a solid improvement that aligns with React best practices. The dependency array correctly includes both drop and quotedDrop.drop_part_id, ensuring the memoized value recomputes only when necessary. The parameter rename from part to candidate also improves readability by avoiding variable shadowing.

components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (2)

31-38: LGTM! Good refactoring for maintainability.

The centralized TAB_LABELS mapping provides a single source of truth for tab labels and eliminates redundancy. This improves maintainability and ensures consistency across the component.


168-182: LGTM! Proper integration with TAB_LABELS.

The options memo correctly references the centralized TAB_LABELS constant, and the dependency array is accurate with availableTabs and isMemesWave.

components/delegation/CollectionDelegation.tsx (1)

3-3: LGTM! Excellent refactoring using React 19.2's useEffectEvent.

The use of useEffectEvent here is the correct pattern for this scenario:

  • Wrapping reset in useEffectEvent provides a stable function identity while always accessing current values
  • This allows removing reset from the dependency array on line 730, preventing potential infinite loops or unnecessary re-renders
  • The effect now only re-runs when accountResolution.address changes, which is the intended behavior

All values accessed within reset (refetch methods, setState calls, hook reset methods) are either stable references or will be current via useEffectEvent.

Also applies to: 709-730

components/groups/page/list/card/GroupCardActionWrapper.tsx (1)

3-3: LGTM! Type-only import optimization.

The type-only import of ReactNode and consistent usage in the props interface is a good optimization that improves tree-shaking and reduces bundle size.

Also applies to: 26-26

components/groups/page/list/card/GroupCard.tsx (2)

63-68: Targeted idle reset looks solid.

Tightening the dependency to isActiveGroupVoteAll ensures the local state only flips back to IDLE when the card truly deactivates, avoiding redundant renders while keeping the guard simple. Nice cleanup.


71-80: Guarding on handle avoids unintended clears.

Early-returning when connectedProfile?.handle exists prevents erasing the active selection for connected users, while still cleaning up when the handle drops. The updated dependency list covers all inputs, so this now behaves deterministically.

components/groups/header/GroupHeaderSelect.tsx (1)

3-9: LGTM! Good simplification of derived state.

Deriving haveProfile directly from connectedProfile?.handle eliminates unnecessary state management and effect coordination. This follows React best practices and reduces component complexity.

components/groups/page/create/GroupCreate.tsx (1)

160-163: LGTM! Inline derivation simplifies code.

Inlining the wallet address mapping eliminates unnecessary indirection while maintaining the same logic and nullish fallback behavior.

components/groups/page/create/config/wallets/GroupCreateWallets.tsx (1)

16-16: LGTM! Excellent refactor to derived memoized value.

Converting selectedWallets from state to a memoized derived value eliminates the need for synchronization effects and follows React best practices for dependent data.

Also applies to: 53-56

components/drops/view/item/rate/give/DropListItemRateGive.tsx (1)

35-45: LGTM! Improved dependency precision with functional updater.

Using a functional state updater with granular dependencies (canVote, maxRating, minRating) instead of the entire drop object reduces unnecessary re-runs while maintaining correct behavior.

components/groups/page/GroupsPageListWrapper.tsx (1)

29-33: LGTM! Simplified boolean expressions.

Converting from function-based derivation to direct constant assignment eliminates unnecessary abstraction for these straightforward boolean expressions.

components/drops/view/Drops.tsx (1)

104-137: LGTM! Improved IntersectionObserver pattern with local references.

The refactor to capture local references (observer, bottomElement) improves React 19 Strict Mode compatibility and prevents stale closure issues. Changing the dependency from drops to drops.length optimizes re-execution to only occur when the count changes.

components/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsx (1)

9-9: LGTM! Removed unused destructured variables.

Removing contract and token from the destructuring pattern cleans up unused variables.

components/groups/page/Groups.tsx (2)

31-43: LGTM! Well-structured useCallback with correct dependencies.

The callback properly handles both authentication and navigation, with all dependencies correctly tracked. Moving setViewMode inside the callback ensures state updates are consolidated within the memoized function.


45-57: Good refactor extracting connectedHandle for stable memoization.

Deriving connectedHandle from connectedProfile?.handle and using it in both useEffect hooks ensures consistent dependency tracking and prevents unnecessary effect re-runs when other connectedProfile properties change.

components/drops/view/DropsList.tsx (1)

171-171: Correct dependency fix for memoizedDrops memoization.

Adding location to the dependency array fixes a missing dependency issue, as location is passed to MemoizedDrop on line 158. This ensures the memoized array recalculates when the drop location changes.

components/drops/view/item/rate/give/DropListItemRateGiveSubmit.tsx (1)

65-68: Good simplification removing unused response parameter.

The onSuccess handler no longer receives the ApiDrop response parameter since it wasn't being used. The callback still properly invokes onSuccessfulRateChange() and clears the optimistic rollback reference.

components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsx (3)

19-21: Excellent animation lifecycle refactor with proper cleanup.

The consolidation of animation setup into a single effect with:

  • Constants for colors and duration (lines 19-21) improving maintainability
  • Ref-based timeline management (line 36) for stable reference across renders
  • Lazy-initialized randomID (line 39) ensuring stable DOM element targeting
  • Comprehensive cleanup (lines 108-115) preventing memory leaks by stopping all Mojs instances

This refactor replaces previous useState-based animation management with a cleaner, more efficient approach.

Also applies to: 36-116


197-213: Good optimization: constants and render-time computed values.

Replacing inline RGBA strings with constants (lines 197, 19-20) and computing display values at render time (lines 210-213) instead of using useState is more efficient and reduces unnecessary re-renders. The effect dependencies are correctly updated to include the new constants.


6-6: Import path is correct and requires no changes.

The types/mojs.d.ts file contains an ambient module declaration that augments @mojs/core (line 1), with MojsTimelineInstance exported within it (line 71). This makes the type accessible as an export from @mojs/core, so the import statement is valid as written.

components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx (1)

33-43: Good use of useEffectEvent pattern.

Using useEffectEvent to wrap prop callbacks allows the effect to access the latest values without re-registering the editor command unnecessarily. This is the correct pattern for this use case.

components/drops/create/lexical/nodes/ImageNode.tsx (1)

90-93: LGTM!

Correctly marks the unused node parameter with an underscore prefix. The parameter is required by the DOMConversionMap type signature but not needed in this implementation since it only returns static conversion metadata.

components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (1)

21-23: LGTM! Excellent refactor to derived state.

Deriving the loading booleans from loadingType instead of maintaining separate state variables is cleaner and eliminates potential synchronization issues.

types/mojs.d.ts (2)

40-46: The type definition is correct and matches the mojs library API.

The then() method is part of the mojs library—it chains a new animation state onto the instance. Similarly, tune() updates the instance's properties at runtime. Both methods take configuration objects and return this for chaining, exactly as specified in the type definition.

The Biome linting warning about "Do not add then to a class" is a false positive. While JavaScript does treat objects with a then method specially, mojs intentionally uses then() as an animation chaining API—not for Promise compatibility. The common pattern is: create → tune → generate() (if needed) → replay()/play(). This is reflected correctly in the type definitions, and the codebase uses these methods appropriately.

Likely an incorrect or invalid review comment.


1-74: Verify type definitions match the actual mojs library behavior.

The type definitions provide comprehensive coverage of the mojs API, but ensure they accurately reflect the actual library's behavior. Pay special attention to:

  • Optional vs. required properties in option interfaces
  • Method signatures and return types
  • The shape of the easing object and available easing functions

Consider importing and using official type definitions from @types/mojs-core or the library itself if available, rather than maintaining custom declarations.

Check if official types are available:

Additionally, verify against the official documentation:

Comment thread components/distribution/Distribution.tsx Outdated
Comment thread components/drops/create/full/desktop/CreateDropFullDesktop.tsx Outdated
Comment thread components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
Comment thread components/drops/create/utils/CreateDropWrapper.tsx Outdated
Comment thread components/gas-royalties/Gas.tsx Outdated
Comment thread components/gas-royalties/Royalties.tsx Outdated
Comment thread components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx Outdated
Comment thread components/groups/page/list/card/GroupCardActionWrapper.tsx
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@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: 4

♻️ Duplicate comments (2)
components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (1)

40-44: Lint rule satisfied, but the performance concern from the previous review remains.

Adding setWallets to the dependency array correctly satisfies the exhaustive-deps rule. However, as noted in the previous review, if the parent component (GroupCreateWallets.tsx) doesn't wrap the callback in useCallback, this effect will re-run on every parent render, even when emmaList hasn't changed.

The previous review already identified that the parent handlers (onEmmaWalletsChange and onUploadedWalletsChange) are not memoized. That recommendation to wrap them with useCallback still applies.

components/drops/create/utils/CreateDropWrapper.tsx (1)

56-56: Remove inline comment to satisfy TSX lint rule.

The coding guidelines forbid comments inside .ts/.tsx files.

🧹 Nitpick comments (4)
components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (1)

46-49: Consider memoizing onWalletsRemove with useCallback.

The onWalletsRemove handler is recreated on every render and passed as a prop to GroupCreateWalletsCount. Wrapping it in useCallback would prevent unnecessary re-renders of the child component.

Apply this diff:

+import { useContext, useEffect, useState, useCallback } from "react";
-import { useContext, useEffect, useState } from "react";

-  const onWalletsRemove = () => {
-    setWallets(null);
-    setSelected(null);
-  };
+  const onWalletsRemove = useCallback(() => {
+    setWallets(null);
+    setSelected(null);
+  }, [setWallets]);
__tests__/components/groups/page/Groups.test.tsx (1)

71-71: Good async handling, but consider verifying router interaction.

The switch to findByTestId properly handles asynchronous rendering after the back button click. However, the test doesn't verify that mockReplace was called with the expected URL.

Consider adding an assertion to verify router navigation:

await user.click(screen.getByRole("button", { name: /back/i }));
expect(mockReplace).toHaveBeenCalledWith(expect.stringMatching(/^\/groups(\?.*)?$/));
expect(await screen.findByTestId("list-wrapper")).toBeInTheDocument();
components/drops/create/utils/CreateDropWrapper.tsx (1)

44-57: Extract pure helper outside component and add readonly to parameter.

Since getRequirementFromFileType is a pure function with no dependencies on component state or props, it should be moved outside the component to avoid recreating it on every render. Additionally, the parameter should be marked readonly per coding guidelines.

As per coding guidelines

Apply this diff to extract and improve the function:

+"use client";
+
+import {
+  forwardRef,
+  ...
+} from "react";
+
+const getRequirementFromFileType = (
+  readonly file: File
+): ApiWaveParticipationRequirement | null => {
+  if (file.type.startsWith("image/")) {
+    return ApiWaveParticipationRequirement.Image;
+  }
+  if (file.type.startsWith("audio/")) {
+    return ApiWaveParticipationRequirement.Audio;
+  }
+  if (file.type.startsWith("video/")) {
+    return ApiWaveParticipationRequirement.Video;
+  }
+  return null;
+};
+
 const CreateDropWrapper = forwardRef<
   CreateDropWrapperHandles,
   CreateDropWrapperProps
 >(
   (
     {
       ...
__tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx (1)

76-76: Consider using userEvent instead of fireEvent for more realistic interactions.

The coding guidelines specify using @testing-library/user-event for component tests. userEvent simulates real user interactions more accurately than fireEvent, providing better test quality.

Apply this diff to use userEvent:

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

Then update the click interactions:

-    fireEvent.click(button);
+    await userEvent.click(button);

As per coding guidelines

Also applies to: 89-89

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f8f599 and 1959ae6.

📒 Files selected for processing (14)
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx (3 hunks)
  • __tests__/components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx (2 hunks)
  • __tests__/components/drops/create/compact/CreateDropCompact.test.tsx (0 hunks)
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx (2 hunks)
  • __tests__/components/groups/page/Groups.test.tsx (3 hunks)
  • components/brain/direct-messages/DirectMessagesList.tsx (1 hunks)
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (5 hunks)
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (5 hunks)
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (3 hunks)
  • components/drops/create/compact/CreateDropCompact.tsx (0 hunks)
  • components/drops/create/full/CreateDropFull.tsx (0 hunks)
  • components/drops/create/full/mobile/CreateDropFullMobile.tsx (0 hunks)
  • components/drops/create/utils/CreateDropWrapper.tsx (9 hunks)
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (1 hunks)
💤 Files with no reviewable changes (4)
  • components/drops/create/full/mobile/CreateDropFullMobile.tsx
  • tests/components/drops/create/compact/CreateDropCompact.test.tsx
  • components/drops/create/full/CreateDropFull.tsx
  • components/drops/create/compact/CreateDropCompact.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • components/brain/direct-messages/DirectMessagesList.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.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/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx
  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • __tests__/components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx
  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
  • components/drops/create/utils/CreateDropWrapper.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/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx
  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx
  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
🧠 Learnings (14)
📓 Common learnings
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
📚 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/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx
  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.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} : Use react-query for data fetching

Applied to files:

  • __tests__/components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx
  • __tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx
  • components/drops/create/utils/CreateDropWrapper.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} : Organise mocks to mirror the real module structure so import paths remain consistent

Applied to files:

  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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 mock implementations minimal—only what’s necessary for the test scenarios

Applied to files:

  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
📚 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__/app/api/**/?(*.)test.{ts,tsx,js,jsx} : Store integration tests for API routes under `app/api`

Applied to files:

  • __tests__/components/groups/page/Groups.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: Use Jest’s built-in mocking for module replacement; keep manual mocks simple and lightweight

Applied to files:

  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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__/**/*.{test,spec}.{js,jsx,ts,tsx} : In tests, use jest.mock('module') with a bare module specifier to load the corresponding manual mock

Applied to files:

  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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} : Name mock files to mirror the real module names so jest.mock('module') can pick them up automatically

Applied to files:

  • __tests__/components/groups/page/Groups.test.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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} : Place manual mock modules under a __mocks__ directory so Jest can auto-resolve them

Applied to files:

  • __tests__/components/groups/page/Groups.test.tsx
🧬 Code graph analysis (4)
__tests__/components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.test.tsx (1)
components/distribution-plan-tool/DistributionPlanToolContext.tsx (1)
  • DistributionPlanToolContext (86-105)
components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (1)
generated/models/ApiWaveDecision.ts (1)
  • ApiWaveDecision (16-42)
__tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx (3)
__tests__/utils/reactQuery.tsx (1)
  • createTestQueryClient (11-34)
components/distribution-plan-tool/DistributionPlanToolContext.tsx (1)
  • DistributionPlanToolContext (86-105)
components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (1)
  • CreateSnapshotFormSearchCollectionDropdownItem (34-206)
components/drops/create/utils/CreateDropWrapper.tsx (3)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
src/errors/wallet-validation.ts (1)
  • WalletValidationError (1-7)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
🪛 Biome (2.1.2)
__tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx

[error] 14-14: Do not add then to an object.

(lint/suspicious/noThenProperty)

⏰ 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 (22)
__tests__/components/groups/page/Groups.test.tsx (5)

8-19: Verify the mockReplace logic for consistency.

The logic deletes only the "edit" param when the URL lacks a query string (line 11), but performs a full clear when parsing a query string (line 15). This asymmetry may not accurately simulate real router behavior if other params existed before navigation.

Consider whether the no-query-string branch should also clear all params for consistency, or add a comment explaining why only "edit" is removed.

 const mockReplace = jest.fn((url: string) => {
   if (!url.includes("?")) {
-    searchParams.delete("edit");
+    searchParams.clear();
     return;
   }

25-25: LGTM!

The useRouter mock correctly returns the mockReplace function, aligning with the new test infrastructure.


28-30: LGTM!

The mock is minimal and provides the necessary test ID for assertions. This follows the guidance to keep mocks lightweight.

Based on learnings


32-35: LGTM!

Consistent with the GroupCreate mock—minimal and sufficient for unit testing.

Based on learnings


54-58: LGTM!

Proper cleanup between tests ensures isolation and prevents state leakage from affecting subsequent tests.

components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (5)

6-6: LGTM: Type-only import is appropriate.

Using type import for ApiWaveDecision is correct since it's only used in type annotations (line 68), improving tree-shaking and clarity.


32-39: LGTM: Excellent refactor.

Extracting tab labels to a module-level constant is a solid improvement that avoids recreating the mapping on every render and provides a single source of truth.


55-55: LGTM: Cleanup of unused variable.

Removing isInProgress from the destructuring is appropriate if it's not used in the component logic.


68-71: LGTM: Enhanced type safety.

Replacing the any-based conversion with Pick<ApiWaveDecision, "decision_time"> provides proper type checking while maintaining the same runtime behavior.


87-179: LGTM: Hook dependencies are correct.

All useEffect dependency arrays are properly specified and include all values referenced within each effect, preventing stale closure issues.

components/drops/create/utils/CreateDropWrapper.tsx (8)

147-172: LGTM! Proper authentication flow with connection state handling.

The early return during initialization/connecting states prevents premature validation errors, and the dependency array correctly includes all values checked in the effect.


222-233: LGTM! Proper memoization of markdown content.

The memoization correctly depends on editorState and avoids recomputing the exported markdown unnecessarily.


234-242: LGTM! Correct memoization of combined media.

The memoization properly depends on drop and files, combining media from all sources efficiently.


274-292: LGTM! Correct memoization of missing media.

All dependencies in the array are properly used in the computation.


294-316: LGTM! Proper memoization of submit eligibility.

The memoization correctly depends on all values used in the computation and consolidates the submit validation logic.


318-341: LGTM! Proper memoization of add-part eligibility.

The memoization correctly depends on all values used in the computation.


343-348: LGTM! Correct effect dependencies.

The effect properly depends on both canSubmit and onCanSubmitChange.


359-427: LGTM! Consistent usage of memoized markdown content.

The onDropPart function correctly uses the memoized markdownContent throughout, avoiding redundant markdown exports.

__tests__/components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.test.tsx (3)

4-4: Excellent React Query test infrastructure setup.

The test properly integrates React Query by importing QueryClientProvider and using the createTestQueryClient() helper, which configures the client with test-friendly defaults (no retries, no refetch). The renderItem helper correctly wraps the component and returns all necessary test utilities.

Also applies to: 8-8, 37-48


83-111: Comprehensive async loading state test.

This test thoroughly validates the loading behavior by:

  • Using a manually-controlled Promise to precisely test the loading state
  • Verifying aria-disabled and spinner presence during fetch
  • Confirming proper cleanup and onCollection invocation after resolution

The pattern of creating a controllable Promise with resolveFetch is an excellent way to test intermediate loading states.


113-124: Good error handling verification.

This test correctly verifies that when distributionPlanApiFetch fails (returns success: false), the component does not trigger an additional toast, appropriately delegating error display to the API layer.

__tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx (1)

63-67: LGTM! Proper test isolation.

The beforeEach block correctly clears all mock functions between tests, ensuring proper test isolation and preventing state pollution.

Comment thread components/drops/create/utils/CreateDropWrapper.tsx
Signed-off-by: Simo <simo@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/drops/create/utils/CreateDropWrapper.tsx (1)

369-369: Remove comment to comply with guidelines.

The coding guidelines forbid comments in .ts/.tsx files. Please remove this comment.

As per coding guidelines

Apply this diff:

-        signer_address: address, // Already validated via useEffect above
+        signer_address: address,
components/distribution/Distribution.tsx (1)

28-32: Add readonly modifiers to props interface.

Per coding guidelines, all props should be marked as readonly.

As per coding guidelines.

Apply this diff:

 interface Props {
-  header: string;
-  contract: string;
-  link: string;
+  readonly header: string;
+  readonly contract: string;
+  readonly link: string;
 }
♻️ Duplicate comments (2)
components/gas-royalties/Royalties.tsx (1)

79-113: Error handling implemented correctly.

The async error handling with try/catch/finally properly addresses the unhandled rejection issue. On failure, all derived state is reset and the error is logged.

components/gas-royalties/Gas.tsx (1)

74-91: Error handling implemented correctly.

The async error handling with try/catch/finally properly addresses the unhandled rejection issue. On failure, all derived state is reset and the error is logged.

🧹 Nitpick comments (4)
components/gas-royalties/Royalties.tsx (1)

140-140: Remove fetchRoyalties from the dependency array.

useEffectEvent returns a stable function reference that doesn't need to be in the dependency array. Including it is redundant.

Apply this diff:

   }, [
     collectionFocus,
     dateSelection,
     fromDate,
     toDate,
     fromBlock,
     toBlock,
     selectedArtist,
     isPrimary,
     isCustomBlocks,
-    fetchRoyalties,
   ]);
components/gas-royalties/Gas.tsx (1)

91-91: Consider removing stable setter functions from dependencies.

setFetching, setGas, and setSumGas are useState setters with stable identities and can be safely omitted from the dependency array.

Apply this diff:

-  }, [getUrlWithParams, setFetching, setGas, setSumGas]);
+  }, [getUrlWithParams]);
components/drops/create/utils/CreateDropWrapper.tsx (1)

137-137: Consider removing unused prop.

The setMentionedUsers prop (aliased to _setMentionedUsers) is never invoked in this component. If it's not needed, consider removing it from the CreateDropWrapperProps interface to simplify the API surface.

components/distribution/Distribution.tsx (1)

363-371: Consider memoizing the setPage callback.

The inline callback is recreated on every render, which may break React.memo optimization if Pagination uses it. Extract to a useCallback for consistent performance.

+  const handlePageChange = useCallback((newPage: number) => {
+    setPageProps((prev) => {
+      if (prev.page === newPage) {
+        return prev;
+      }
+
+      return { ...prev, page: newPage };
+    });
+  }, []);
+
   ...
   
   <Pagination
     page={pageProps.page}
     pageSize={pageProps.pageSize}
     totalResults={totalResults}
-    setPage={(newPage: number) => {
-      setPageProps((prev) => {
-        if (prev.page === newPage) {
-          return prev;
-        }
-
-        return { ...prev, page: newPage };
-      });
-    }}
+    setPage={handlePageChange}
   />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1959ae6 and 06820bd.

📒 Files selected for processing (7)
  • components/distribution/Distribution.tsx (4 hunks)
  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx (3 hunks)
  • components/drops/create/utils/CreateDropWrapper.tsx (9 hunks)
  • components/gas-royalties/Gas.tsx (2 hunks)
  • components/gas-royalties/Royalties.tsx (3 hunks)
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (2 hunks)
  • components/groups/page/create/config/wallets/GroupCreateWallets.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/groups/page/create/config/wallets/GroupCreateWallets.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/distribution/Distribution.tsx
  • components/gas-royalties/Royalties.tsx
  • components/gas-royalties/Gas.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/distribution/Distribution.tsx
  • components/gas-royalties/Royalties.tsx
  • components/gas-royalties/Gas.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
  • components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx
🧠 Learnings (5)
📓 Common learnings
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
📚 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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.tsx
  • components/gas-royalties/Gas.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/drops/create/utils/CreateDropWrapper.tsx
📚 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:

  • components/drops/create/lexical/plugins/enter/EnterKeyPlugin.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/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx
🧬 Code graph analysis (4)
components/distribution/Distribution.tsx (2)
entities/IDistribution.ts (2)
  • Distribution (6-19)
  • DistributionPhoto (21-28)
services/6529api.ts (2)
  • fetchUrl (7-20)
  • fetchAllPages (22-37)
components/gas-royalties/Royalties.tsx (3)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/gas-royalties/Gas.tsx (3)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IGas.ts (1)
  • Gas (1-8)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/drops/create/utils/CreateDropWrapper.tsx (3)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
src/errors/wallet-validation.ts (1)
  • WalletValidationError (1-7)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
⏰ 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 (18)
components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (3)

3-3: LGTM!

The useCallback import is appropriate for the memoization added below.


44-47: LGTM!

Wrapping onWalletsRemove in useCallback prevents unnecessary recreation of the callback on every render. The dependency array [setWallets] is correct—setSelected doesn't need to be included since state setters from useState are stable by default.


40-42: Approved. Parent component properly memoizes callbacks.

The script confirms that onEmmaWalletsChange (and onUploadedWalletsChange) are now wrapped with useCallback with stable dependency arrays. This resolves the prior concern—the effect in CreateGroupWalletsEmma.tsx will no longer re-run unnecessarily on every parent render.

components/drops/create/utils/CreateDropWrapper.tsx (10)

44-57: LGTM!

The helper function correctly maps file MIME types to the corresponding API participation requirements.


156-172: Authentication validation dependencies are correct.

The effect properly waits for connection initialization and validates authentication state with the correct dependency array.


222-233: LGTM!

The markdownContent memoization correctly depends only on editorState and properly handles the null case.


234-242: LGTM!

The combinedMedias memoization correctly merges media from existing parts and new files with proper dependencies.


244-272: LGTM!

The missingMetadata memoization has the correct dependencies and no longer includes the unnecessary drop dependency from the previous review.


274-292: LGTM!

The missingMedia memoization correctly tracks all dependencies including drop, files, and combinedMedias.


294-316: LGTM!

The canSubmit memoization correctly evaluates submission readiness with all necessary dependencies tracked.


318-341: LGTM!

The canAddPart memoization correctly evaluates whether a part can be added with proper dependency tracking.


343-348: LGTM!

The effect correctly notifies of canSubmit changes with proper dependencies.


359-427: LGTM!

The onDropPart function correctly uses the memoized markdownContent throughout, properly handling null cases and filtering mentions/NFTs based on content.

components/distribution/Distribution.tsx (3)

56-71: Excellent memoization and numeric sort fix.

The useCallback memoization ensures stable function identity, and the numeric-aware localeCompare correctly addresses the past review comment about phase ordering (e.g., "Phase 2" now comes before "Phase 10").


138-150: Good functional updater pattern for page reset.

The guard if (prev.page === 1) return prev prevents unnecessary state updates, and the functional updater ensures correct behavior when nftId or searchWallets change.


73-106: Excellent cancellation safety for async fetches.

Both distribution data and photos fetches now use the isCurrent flag pattern to prevent state updates after unmount. This is a solid improvement to async safety.

Also applies to: 115-136

components/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsx (2)

33-43: Previous issues resolved; useEffectEvent wrappers look correct.

The useEffectEvent wrappers properly centralize the Enter key guard logic and submit handling. The previous review concerns about including these in the dependency array have been addressed (line 116 correctly excludes them). The implementation correctly allows reading the latest prop values without triggering effect re-runs.


45-116: Dependency array is correct and React version requirement is met.

The effect dependency array correctly includes editor, isMobile, and isCapacitor, and properly excludes the useEffectEvent callbacks (shouldHandleEnter and submit). React 19.2.0 is confirmed, which supports useEffectEvent.

Comment thread components/distribution/Distribution.tsx Outdated
Comment thread components/distribution/Distribution.tsx Outdated
Comment thread components/drops/create/utils/CreateDropWrapper.tsx Outdated
Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@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/gas-royalties/Royalties.tsx (1)

115-140: Remove fetchRoyalties from the dependency array.

When using useEffectEvent, the event function is intentionally stable and doesn't need to be included in dependency arrays. That's the primary purpose of useEffectEvent—to separate "event" logic from reactive dependencies.

   }, [
     collectionFocus,
     dateSelection,
     fromDate,
     toDate,
     fromBlock,
     toBlock,
     selectedArtist,
     isPrimary,
     isCustomBlocks,
-  ]);
+  ]); 

Note: fetchRoyalties should not be in this dependency array since it's created with useEffectEvent.

components/distribution/Distribution.tsx (1)

304-309: Keep the distribution table rendered while the first page loads.
With the new guard, the table (and its <DotLoader />) disappears during the initial fetch, leaving users with a blank section until data arrives. Render the table whenever nftId is present and rely on the existing fetching flag and empty-state block to cover spinner vs. “no data” cases.

-                  {nftId &&
-                    (distributions.length > 0 || searchWallets.length > 0) &&
-                    printDistribution()}
+                  {nftId && printDistribution()}
🧹 Nitpick comments (4)
components/groups/page/Groups.tsx (2)

71-87: Consider using triggerViewModeChange for consistent error handling.

The JSX event handlers call onViewModeChange directly without handling the returned promise, while effects use the triggerViewModeChange wrapper for error logging. For consistency and to prevent unhandled promise rejections in the console (e.g., if auth fails), consider using triggerViewModeChange here as well.

Apply this diff for consistency:

       <GroupsPageListWrapper
-        onCreateNewGroup={() => onViewModeChange(GroupsViewMode.CREATE)}
+        onCreateNewGroup={() => triggerViewModeChange(GroupsViewMode.CREATE)}
       />
     ),
     [GroupsViewMode.CREATE]: (
       <GroupCreate
-        onCompleted={() => onViewModeChange(GroupsViewMode.VIEW)}
+        onCompleted={() => triggerViewModeChange(GroupsViewMode.VIEW)}
         edit={edit ?? "new"}
       />
     ),

And:

           <button
-            onClick={() => onViewModeChange(GroupsViewMode.VIEW)}
+            onClick={() => triggerViewModeChange(GroupsViewMode.VIEW)}
             type="button"

90-102: Consider using FontAwesome for the back arrow icon.

Per the coding guidelines, FontAwesome is preferred for icons. The inline SVG could be replaced with a FontAwesome icon for consistency.

As per coding guidelines.

components/gas-royalties/Gas.tsx (1)

66-83: Consider migrating to react-query for data fetching.

The error handling and state management look solid. However, the coding guidelines specify using react-query for data fetching. Consider refactoring this to use a react-query mutation or query hook instead of the manual fetchUrl + state management pattern.

Based on coding guidelines.

components/gas-royalties/Royalties.tsx (1)

79-113: Consider migrating to react-query for data fetching.

The error handling is correct and mirrors the pattern in Gas.tsx. However, both files should use react-query for data fetching per the coding guidelines. Additionally, useEffectEvent wraps this fetch function, but as noted earlier, useEffectEvent is experimental.

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 06820bd and 1bcc532.

📒 Files selected for processing (17)
  • __tests__/components/CreateDropWrapper.test.tsx (0 hunks)
  • __tests__/components/drops/create/full/CreateDropFull.test.tsx (0 hunks)
  • __tests__/components/drops/create/full/desktop/CreateDropFullDesktop.test.tsx (0 hunks)
  • __tests__/components/drops/create/utils/CreateDropWrapper.test.tsx (0 hunks)
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (5 hunks)
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (2 hunks)
  • components/distribution/Distribution.tsx (7 hunks)
  • components/distribution/useDistributionQueries.ts (1 hunks)
  • components/drops/create/DropEditor.tsx (0 hunks)
  • components/drops/create/full/CreateDropFull.tsx (0 hunks)
  • components/drops/create/full/desktop/CreateDropFullDesktop.tsx (0 hunks)
  • components/drops/create/utils/CreateDropWrapper.tsx (8 hunks)
  • components/gas-royalties/Gas.tsx (2 hunks)
  • components/gas-royalties/Royalties.tsx (2 hunks)
  • components/groups/page/Groups.tsx (2 hunks)
  • components/groups/page/list/card/GroupCardActionWrapper.tsx (2 hunks)
  • components/react-query-wrapper/ReactQueryWrapper.tsx (1 hunks)
💤 Files with no reviewable changes (7)
  • components/drops/create/DropEditor.tsx
  • tests/components/CreateDropWrapper.test.tsx
  • components/drops/create/full/desktop/CreateDropFullDesktop.tsx
  • tests/components/drops/create/full/desktop/CreateDropFullDesktop.test.tsx
  • tests/components/drops/create/full/CreateDropFull.test.tsx
  • tests/components/drops/create/utils/CreateDropWrapper.test.tsx
  • components/drops/create/full/CreateDropFull.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/groups/page/list/card/GroupCardActionWrapper.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/distribution/useDistributionQueries.ts
  • components/groups/page/Groups.tsx
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx
  • components/gas-royalties/Royalties.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx
  • components/gas-royalties/Gas.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/distribution/Distribution.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/groups/page/Groups.tsx
  • components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx
  • components/gas-royalties/Royalties.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx
  • components/gas-royalties/Gas.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/distribution/Distribution.tsx
🧠 Learnings (4)
📓 Common learnings
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
📚 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/distribution/useDistributionQueries.ts
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/distribution/Distribution.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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.tsx
  • components/gas-royalties/Gas.tsx
  • components/distribution/Distribution.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/drops/create/utils/CreateDropWrapper.tsx
🧬 Code graph analysis (7)
components/distribution/useDistributionQueries.ts (2)
entities/IDistribution.ts (2)
  • Distribution (6-19)
  • DistributionPhoto (21-28)
services/6529api.ts (2)
  • fetchUrl (7-20)
  • fetchAllPages (22-37)
components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (2)
components/allowlist-tool/allowlist-tool.types.ts (1)
  • DistributionPlanSearchContractMetadataResult (171-181)
services/distribution-plan-api.ts (1)
  • distributionPlanApiFetch (38-62)
components/gas-royalties/Royalties.tsx (3)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (5)
components/distribution-plan-tool/DistributionPlanToolContext.tsx (1)
  • DistributionPlanToolContext (86-105)
components/allowlist-tool/allowlist-tool.types.ts (1)
  • DistributionPlanSnapshotToken (199-204)
services/distribution-plan-api.ts (1)
  • distributionPlanApiFetch (38-62)
components/distribution-plan-tool/common/RoundedJsonIconButton.tsx (1)
  • RoundedJsonIconButton (4-22)
components/distribution-plan-tool/common/RoundedCsvIconButton.tsx (1)
  • RoundedCsvIconButton (4-22)
components/gas-royalties/Gas.tsx (4)
components/gas-royalties/GasRoyalties.tsx (1)
  • useSharedState (364-450)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IGas.ts (1)
  • Gas (1-8)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/drops/create/utils/CreateDropWrapper.tsx (4)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
src/errors/wallet-validation.ts (1)
  • WalletValidationError (1-7)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
components/drops/create/lexical/transformers/markdownTransformers.ts (1)
  • SAFE_MARKDOWN_TRANSFORMERS (42-42)
components/distribution/Distribution.tsx (1)
components/distribution/useDistributionQueries.ts (2)
  • useDistributionData (19-46)
  • useDistributionPhotos (53-70)
⏰ 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 (14)
components/groups/page/Groups.tsx (5)

3-3: LGTM! Good addition for memoization.


31-43: Excellent async callback pattern with proper auth gating.

The useCallback memoization and async auth check before state updates ensure the view mode only changes when authorization succeeds. Dependencies are complete.


45-52: Good error handling wrapper.

The wrapper correctly handles promise rejections with logging, making it safe for use in effects.


54-54: Smart optimization of derived value.

Extracting the handle prevents unnecessary effect re-runs when connectedProfile reference changes but its handle remains the same.


56-66: Properly updated effects with complete dependencies.

The effects correctly use triggerViewModeChange for error handling and have accurate dependency arrays including connectedHandle, activeProfileProxy, and the memoized callbacks.

components/gas-royalties/Gas.tsx (4)

3-3: LGTM!

The addition of useCallback and useRef is appropriate for the memoization and focus-tracking patterns introduced in this refactor.


36-59: LGTM!

The guard at line 42 prevents unnecessary state updates when resolvedFocus equals collectionFocus, and the dependency array is comprehensive.


64-64: LGTM!

Memoizing getUrlWithParams prevents unnecessary re-renders of child components that receive this function as a prop.


85-102: LGTM!

The ref-based change detection pattern is clean, and clearing the gas array on focus changes provides good UX by preventing stale data display.

components/gas-royalties/Royalties.tsx (3)

55-59: LGTM!

State declarations are well-organized and correctly typed.


77-77: LGTM!

Consistent memoization pattern with Gas.tsx.


3-9: No changes required.

The useEffectEvent hook is a stable API available in React 19.2.0, which is the React version your project uses. Your eslint-plugin-react-hooks version (^7.0.1) is up-to-date and properly recognizes Effect Events. The imports at lines 3-9 are correct and valid.

components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsx (1)

60-88: Solid split between JSON/CSV mutations.

Nice job isolating the shared fetch logic while giving each download its own mutation and handler—the separate loading flags keep the buttons honest without extra state churn.

components/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsx (1)

99-172: Nice accessibility upgrade during token fetch.

The combination of aria-busy, temporary pointer lock, and the inline spinner makes the wait state obvious without extra noise—great touch.

Comment thread components/distribution/useDistributionQueries.ts Outdated
Comment thread components/drops/create/utils/CreateDropWrapper.tsx
Comment thread components/gas-royalties/Royalties.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: 0

🧹 Nitpick comments (4)
components/drops/create/utils/CreateDropWrapper.tsx (1)

338-343: Consider requesting parent to memoize onCanSubmitChange.

The onCanSubmitChange callback in the dependency array may cause unnecessary re-renders if the parent component doesn't wrap it in useCallback. While not a bug, memoizing this callback in the parent would improve performance.

components/gas-royalties/Gas.tsx (1)

62-63: Consider simplifying the URL memoization.

The current approach uses two levels of memoization: getUrlWithParams wraps getUrl("gas") in useCallback, then gasUrl memoizes the result. This can be simplified to:

const gasUrl = useMemo(() => getUrl("gas"), [getUrl]);

Or skip the gasUrl variable and use getUrlWithParams() directly in the queryKey:

const getUrlWithParams = useCallback(() => getUrl("gas"), [getUrl]);

// In useQuery:
queryKey: ["gas-royalties", getUrlWithParams()],
components/gas-royalties/Royalties.tsx (1)

75-77: Memoize royaltiesUrl for consistency and optimization.

Unlike Gas.tsx (line 63), royaltiesUrl is computed directly without useMemo, causing it to be recalculated on every render even when dependencies haven't changed. For consistency and to avoid unnecessary function calls, wrap it in useMemo:

Apply this diff:

 const getUrlWithParams = useCallback(() => getUrl("royalties"), [getUrl]);
-
-const royaltiesUrl = collectionFocus ? getUrlWithParams() : "";
+const royaltiesUrl = useMemo(
+  () => (collectionFocus ? getUrlWithParams() : ""),
+  [collectionFocus, getUrlWithParams]
+);

Or simplify like the suggestion for Gas.tsx:

-const getUrlWithParams = useCallback(() => getUrl("royalties"), [getUrl]);
-
-const royaltiesUrl = collectionFocus ? getUrlWithParams() : "";
+const getUrlWithParams = useCallback(() => getUrl("royalties"), [getUrl]);
+const royaltiesUrl = useMemo(
+  () => (collectionFocus ? getUrl("royalties") : ""),
+  [collectionFocus, getUrl]
+);
components/distribution/Distribution.tsx (1)

91-91: Consider inlining the fetching variable.

The fetching variable is only used once at line 184. Inlining it as {isDistributionsFetching ? ... } would simplify the code and reduce unnecessary intermediate variables.

Apply this diff to inline the variable:

-  const fetching = isDistributionsFetching;
-
   const handlePageChange = useCallback((newPage: number) => {

Then at line 184, replace fetching with isDistributionsFetching:

-                      {fetching ? (
+                      {isDistributionsFetching ? (
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bcc532 and e06075b.

📒 Files selected for processing (6)
  • components/distribution/Distribution.tsx (8 hunks)
  • components/distribution/useDistributionQueries.ts (1 hunks)
  • components/drops/create/utils/CreateDropWrapper.tsx (8 hunks)
  • components/gas-royalties/Gas.tsx (2 hunks)
  • components/gas-royalties/Royalties.tsx (2 hunks)
  • components/groups/page/Groups.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/distribution/useDistributionQueries.ts
  • components/groups/page/Groups.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/drops/create/utils/CreateDropWrapper.tsx
  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
  • components/gas-royalties/Gas.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
  • components/gas-royalties/Gas.tsx
🧠 Learnings (4)
📓 Common learnings
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
📚 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/drops/create/utils/CreateDropWrapper.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/drops/create/utils/CreateDropWrapper.tsx
  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
  • components/gas-royalties/Gas.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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
  • components/gas-royalties/Gas.tsx
🧬 Code graph analysis (4)
components/drops/create/utils/CreateDropWrapper.tsx (4)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
src/errors/wallet.ts (1)
  • WalletValidationError (9-15)
src/errors/wallet-validation.ts (1)
  • WalletValidationError (1-7)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
components/gas-royalties/Royalties.tsx (3)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/distribution/Distribution.tsx (3)
entities/IDistribution.ts (1)
  • Distribution (6-19)
helpers/Helpers.ts (1)
  • numberWithCommas (83-100)
components/distribution/useDistributionQueries.ts (2)
  • useDistributionData (19-48)
  • useDistributionPhotos (55-72)
components/gas-royalties/Gas.tsx (5)
contexts/TitleContext.tsx (1)
  • useTitle (186-192)
components/gas-royalties/GasRoyalties.tsx (1)
  • useSharedState (364-450)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IGas.ts (1)
  • Gas (1-8)
services/6529api.ts (1)
  • fetchUrl (7-20)
⏰ 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 (22)
components/drops/create/utils/CreateDropWrapper.tsx (4)

44-57: LGTM! Clean utility function for file type mapping.

The function correctly maps MIME types to participation requirements and handles unsupported types gracefully.


143-167: LGTM! Proper authentication guard.

The connection state guard prevents validation errors during wallet initialization, and the error handling provides clear user feedback.


217-336: LGTM! Well-structured memoizations with correct dependencies.

All six memoized values (markdownContent, combinedMedias, missingMetadata, missingMedia, canSubmit, canAddPart) have accurate dependency arrays and follow React best practices. The validation logic for content length and required fields is clear and comprehensive.


354-426: LGTM! Proper refactoring to use memoized values.

The functions now consistently use markdownContent and address from context, eliminating redundant computations and ensuring validated values are used throughout the drop creation flow.

components/gas-royalties/Gas.tsx (6)

3-3: LGTM: Appropriate imports for React Query migration.

The imports support the new query-driven data flow and proper memoization.


25-35: LGTM: Shared state destructuring is complete.

All destructured fields are properly utilized throughout the component.


37-60: LGTM: Guard prevents unnecessary state updates.

The conditional check at line 43 ensures setCollectionFocus is only called when the value actually changes, avoiding unnecessary re-renders. The dependencies are complete.


65-88: LGTM: React Query implementation is well-structured.

The query properly:

  • Uses gasUrl in the queryKey for cache invalidation
  • Enables only when needed
  • Handles errors by logging and returning empty data
  • Normalizes gas values consistently

90-93: LGTM: Memoized sum computation is efficient.

The sumGas calculation is properly memoized with the correct dependency on gas.


95-100: LGTM: Fetching state synchronization is appropriate.

The effect properly syncs React Query's isFetching to the shared fetching state, with an appropriate guard for collectionFocus.

components/gas-royalties/Royalties.tsx (5)

3-4: LGTM: Appropriate imports for React Query migration.

The imports support the query-driven refactor and memoization patterns.


50-73: LGTM: Guard prevents unnecessary state updates.

The conditional check at lines 56-58 ensures setCollectionFocus is only called when the value changes, matching the pattern used in Gas.tsx. Dependencies are complete.


79-102: LGTM: React Query implementation is well-structured.

The query properly:

  • Uses royaltiesUrl in the queryKey for cache management
  • Enables only when the URL is available
  • Handles errors by logging and returning empty data
  • Normalizes all numeric fields consistently

104-111: LGTM: Fetching state properly communicates loading status.

The effect sets fetching to true when collectionFocus is missing (lines 105-107), indicating a loading state while focus is being resolved. This appropriately syncs React Query's fetch status with shared state.


113-129: LGTM: Memoized sum computations are efficient.

The sums are properly memoized with the correct dependency on royalties, and the empty-array case is handled explicitly for clarity.

components/distribution/Distribution.tsx (7)

19-22: Excellent migration to React Query hooks!

The refactoring from manual fetchUrl/fetchAllPages calls to useDistributionData and useDistributionPhotos hooks is well-executed. This provides automatic caching, deduplication, background refetching, and built-in cancellation support, fully aligning with the coding guidelines and addressing previous review feedback.

As per coding guidelines. Based on learnings.

Also applies to: 59-70, 84-89


29-33: LGTM: Props correctly marked as readonly.

The Props interface correctly uses readonly modifiers on all fields, conforming to the coding guidelines.

As per coding guidelines.


72-82: LGTM: Numeric-aware phase sorting implemented correctly.

The memoized distributionPhases computation now uses numeric-aware localeCompare with { numeric: true, sensitivity: "base" }, which correctly sorts "Phase 2" before "Phase 10". This addresses the previous review feedback perfectly.


93-101: LGTM: handlePageChange correctly memoized.

The callback uses the functional update pattern with an empty dependency array, avoiding stale closures. The early return optimization for unchanged pages is a nice touch.


110-122: LGTM: Effect correctly resets pagination on filter changes.

The effect appropriately resets to page 1 when nftId or searchWallets change, with proper early-return guards and functional updates to avoid unnecessary re-renders.


305-305: LGTM: Defensive rendering guard.

The conditional {nftId && printDistribution()} prevents rendering the distribution table before the NFT ID is available, avoiding potential errors.


35-45: Verify phase casing consistency between phases array and allowlist entries at backend level.

The review comment correctly identifies an inconsistency: getCountForPhase uses case-insensitive comparison for AIRDROP (line 36: phase.toUpperCase() === "AIRDROP") but employs exact string matching for allowlist phases (line 41: entry.phase === phase). While test data shows lowercase consistency, the code lacks defensive normalization. If the backend provides phases: ["Phase1"] but allowlist[].phase: ["phase1"], the lookup silently fails, returning "-" instead of matching entries.

A duplicate instance of this same pattern exists in UserPageStatsActivityDistributionsTable.tsx (line 84).

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e06075b and cfe9346.

📒 Files selected for processing (4)
  • components/distribution/Distribution.tsx (8 hunks)
  • components/drops/create/utils/CreateDropWrapper.tsx (8 hunks)
  • components/gas-royalties/Gas.tsx (2 hunks)
  • components/gas-royalties/Royalties.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/gas-royalties/Gas.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/gas-royalties/Royalties.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/distribution/Distribution.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/gas-royalties/Royalties.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/distribution/Distribution.tsx
🧠 Learnings (4)
📓 Common learnings
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
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
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
📚 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/gas-royalties/Royalties.tsx
  • components/drops/create/utils/CreateDropWrapper.tsx
  • components/distribution/Distribution.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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.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/drops/create/utils/CreateDropWrapper.tsx
🧬 Code graph analysis (3)
components/gas-royalties/Royalties.tsx (3)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/drops/create/utils/CreateDropWrapper.tsx (3)
components/auth/SeizeConnectContext.tsx (1)
  • useSeizeConnectContext (618-626)
src/errors/wallet-validation.ts (1)
  • WalletValidationError (1-7)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
components/distribution/Distribution.tsx (4)
entities/IDistribution.ts (1)
  • Distribution (6-19)
helpers/Helpers.ts (1)
  • numberWithCommas (83-100)
components/distribution/useDistributionQueries.ts (2)
  • useDistributionData (19-48)
  • useDistributionPhotos (55-72)
components/dotLoader/DotLoader.tsx (1)
  • DotLoader (5-13)
⏰ 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 (11)
components/drops/create/utils/CreateDropWrapper.tsx (10)

45-58: LGTM!

Clean utility function that correctly maps MIME type prefixes to participation requirements.


144-168: LGTM!

The wallet validation logic correctly guards against premature validation during initialization and connection states, and the dependency array properly includes all referenced values.


218-229: LGTM!

The markdownContent memoization correctly depends only on editorState and avoids unnecessary recomputation.


230-238: LGTM!

The combinedMedias memoization correctly derives the merged media array and depends on the appropriate values.


240-268: LGTM!

The missingMetadata computation correctly validates required metadata with proper presence, length, and type checks. The dependency array accurately reflects the values used.


270-288: LGTM!

The missingMedia computation correctly validates required media using the helper function and has an accurate dependency array.


290-312: LGTM!

The canSubmit logic correctly validates content presence, required media/metadata, and enforces the 240-character limit for parts added to existing drops. The dependency array is complete.


314-337: LGTM!

The canAddPart logic correctly enforces both per-part (240) and total content (24000) length limits. The dependency array is accurate.


6-6: React version is compatible with useEffectEvent.

Your project uses React 19.2.0, which supports the useEffectEvent hook. The import and usage at lines 6 and 339-345 are compatible.


40-40: Import path is correct—no action needed.

The import statement correctly references @/src/errors/wallet, which resolves to src/errors/wallet.ts. WalletValidationError is properly exported from that file, so the import resolves successfully.

components/gas-royalties/Royalties.tsx (1)

76-109: Solid react-query refactor. The useQuery swap keeps the shared fetching flag aligned without manual promise bookkeeping and still normalizes the payload before it hits the table.

Comment thread components/distribution/Distribution.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: 0

🧹 Nitpick comments (1)
components/gas-royalties/Royalties.tsx (1)

75-98: Migration to React Query successfully addresses previous error handling concern.

The query implementation correctly:

  • Guards execution with enabled: Boolean(royaltiesUrl)
  • Handles fetch failures with try-catch
  • Normalizes numeric fields
  • Returns empty array on error

However, consider these refinements:

QueryKey improvement (recommended): Use semantic parts instead of the full URL string for better cache introspection and debugging:

-    queryKey: ["gas-royalties", "royalties", royaltiesUrl],
+    queryKey: [
+      "gas-royalties",
+      "royalties",
+      collectionFocus,
+      isPrimary,
+      dateSelection,
+      fromDate,
+      toDate,
+      fromBlock,
+      toBlock,
+      selectedArtist,
+    ],

This requires extracting those values from useSharedState() (currently not destructured).

Optional: Remove redundant placeholderData: [] on line 77, since line 75 already defaults to [].

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfe9346 and 9a6465f.

📒 Files selected for processing (2)
  • components/distribution/Distribution.tsx (8 hunks)
  • components/gas-royalties/Royalties.tsx (2 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/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
🧠 Learnings (3)
📓 Common learnings
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
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
📚 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/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.tsx
  • components/distribution/Distribution.tsx
🧬 Code graph analysis (2)
components/gas-royalties/Royalties.tsx (4)
components/gas-royalties/GasRoyalties.tsx (1)
  • useSharedState (364-450)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
services/6529api.ts (1)
  • fetchUrl (7-20)
components/distribution/Distribution.tsx (4)
entities/IDistribution.ts (1)
  • Distribution (6-19)
helpers/Helpers.ts (1)
  • numberWithCommas (83-100)
components/distribution/useDistributionQueries.ts (2)
  • useDistributionData (19-48)
  • useDistributionPhotos (55-72)
components/dotLoader/DotLoader.tsx (1)
  • DotLoader (5-13)
⏰ 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)
components/gas-royalties/Royalties.tsx (4)

3-4: LGTM! Clean setup for React Query migration.

The new imports and memoized URL generation properly prepare the component for query-driven data fetching. The useCallback and useMemo hooks prevent unnecessary recalculations and align with React Query best practices.

Based on learnings

Also applies to: 68-73


100-107: LGTM! Correct synchronization of legacy fetching state.

This effect properly bridges the query's isFetching to the shared fetching state consumed by GasRoyaltiesHeader. The explicit setFetching(true) when collectionFocus is undefined ensures a loading state displays while the focus is being determined from the route, even though the query itself is disabled.


109-125: LGTM! Derived sums computed efficiently.

Using useMemo to compute aggregate totals from the query data is the correct pattern. This eliminates separate state management for derived values and ensures the sums stay synchronized with the royalties array.


43-66: LGTM! Routing effect properly guards against unnecessary updates.

The added guard on lines 49-51 prevents setCollectionFocus from being called when the resolved focus matches the current state, avoiding unnecessary re-renders. The dependency array correctly includes collectionFocus to support this check.

components/distribution/Distribution.tsx (6)

19-22: Excellent migration to React Query hooks and proper readonly props.

The imports of useDistributionData and useDistributionPhotos replace manual fetch logic with react-query, and the readonly modifiers on all props align perfectly with the coding guidelines.

As per coding guidelines. Based on learnings.

Also applies to: 29-33


35-45: LGTM: Clean extraction of phase count logic.

The getCountForPhase helper properly handles both the special "AIRDROP" phase and allowlist entries, with appropriate fallbacks and formatting. This extraction improves maintainability over the previous inline approach.


59-70: Perfect integration of React Query hooks.

The useDistributionData and useDistributionPhotos hooks replace all manual fetch logic with proper query-based data fetching. Dependencies are correct, and derived values use safe fallbacks. This addresses previous review comments and follows the react-query guideline.

As per coding guidelines. Based on learnings.

Also applies to: 84-89


72-82: Excellent use of memoization and stable callbacks.

The useMemo for distributionPhases with numeric-aware sorting correctly addresses the previous sorting concern (commit 06820bd). The handlePageChange callback is properly memoized with immutable state updates and an early-return optimization.

Also applies to: 91-99


108-120: LGTM: Clean page reset logic.

The effect properly resets to page 1 when filters change, with appropriate guards to prevent unnecessary updates. The immutable state updates and early returns are well done.


303-308: Proper rendering guards successfully address previous concerns.

Both guards are well placed: line 303 prevents rendering the distribution table before nftId is set, and line 306 correctly gates the empty state to avoid the premature "Distribution Plan will be made available soon!" message that was flagged in past reviews.

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a6465f and 4c98000.

📒 Files selected for processing (1)
  • components/gas-royalties/Royalties.tsx (2 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/gas-royalties/Royalties.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/gas-royalties/Royalties.tsx
🧠 Learnings (3)
📓 Common learnings
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
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
📚 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/gas-royalties/Royalties.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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.tsx
🧬 Code graph analysis (1)
components/gas-royalties/Royalties.tsx (4)
components/gas-royalties/GasRoyalties.tsx (1)
  • useSharedState (364-450)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
services/6529api.ts (1)
  • fetchUrl (7-20)
⏰ 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/gas-royalties/Royalties.tsx
Signed-off-by: Simo <simo@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 (3)
__tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx (3)

1-1: Replace fireEvent with userEvent per coding guidelines.

The coding guidelines require using @testing-library/user-event for React component tests. userEvent more accurately simulates real user interactions and is the recommended approach.

Apply this diff:

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

Then update lines 95 and 108:

-    fireEvent.click(button);
+    await userEvent.click(button);

Note: Mark the test functions as async if not already, and await the userEvent.click() calls.


9-29: Remove the Proxy workaround and simplify the Html mock.

This Proxy-based solution is overly complex and still makes the mock functionally thenable—accessing .then returns a mock function, which means async code can still treat it as Promise-like. The past review comment requested complete removal of the then property, not a workaround.

Replace the entire function with a simple object:

-const createMockMojsHtmlInstance = () => {
-  const base = {
-    tune: jest.fn(),
-    stop: jest.fn(),
-  };
-
-  let thenMock!: jest.Mock;
-  const proxy = new Proxy(base, {
-    // Provide a `.then` handler without turning the object into a "thenable" for linting purposes.
-    get(target, property, receiver) {
-      if (property === 'then') {
-        return thenMock;
-      }
-
-      return Reflect.get(target, property, receiver);
-    },
-  });
-
-  thenMock = jest.fn().mockReturnValue(proxy);
-  return proxy;
-};

And update line 35:

-    Html: jest.fn().mockImplementation(() => createMockMojsHtmlInstance()),
+    Html: jest.fn().mockImplementation(() => ({ tune: jest.fn(), stop: jest.fn() })),

7-7: Add test assertions for mockStop to verify cleanup behavior.

mockStop is declared, integrated into the Timeline mock, and cleared in beforeEach, but no test asserts it's ever called. The past review comment noted that the component calls timeline.stop() during useEffect cleanup (line 107 of the component implementation).

Add a test case to verify cleanup:

it('calls stop on timeline during cleanup', async () => {
  const onSubmit = jest.fn();
  const { unmount } = render(
    <DropListItemRateGiveClap rate={5} voteState={DropVoteState.CAN_VOTE} canVote onSubmit={onSubmit} />
  );
  await waitFor(() => expect(mockAdd).toHaveBeenCalled());
  
  unmount();
  
  expect(mockStop).toHaveBeenCalled();
});
🧹 Nitpick comments (1)
components/gas-royalties/Royalties.tsx (1)

75-80: Optional: Consider stabilizing the URL callback.

The getUrlWithParams callback is not stable because getUrl from useSharedState is recreated on every render. This causes the royaltiesUrl memo to recompute unnecessarily. While this doesn't affect correctness (the query key properly controls refetching), it's a minor inefficiency.

The proper fix would be to memoize getUrl inside useSharedState using useCallback:

In GasRoyalties.tsx (useSharedState hook):

const getUrl = useCallback(
  (type: string) => {
    return getUrlParams(
      type,
      isPrimary,
      isCustomBlocks,
      dateSelection,
      collectionFocus,
      fromDate,
      toDate,
      fromBlock,
      toBlock,
      selectedArtist
    );
  },
  [
    isPrimary,
    isCustomBlocks,
    dateSelection,
    collectionFocus,
    fromDate,
    toDate,
    fromBlock,
    toBlock,
    selectedArtist,
  ]
);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c98000 and 9394905.

📒 Files selected for processing (2)
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx (2 hunks)
  • components/gas-royalties/Royalties.tsx (2 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:

  • components/gas-royalties/Royalties.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

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

Files:

  • components/gas-royalties/Royalties.tsx
  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
🧠 Learnings (13)
📓 Common learnings
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
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
📚 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/gas-royalties/Royalties.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,tsx,js,jsx} : Never call fetch directly with user-controlled or scraped URLs in API code; use @/lib/security/urlGuard helpers (parsePublicUrl, assertPublicUrl, fetchPublicUrl, fetchPublicJson) so every hop is validated

Applied to files:

  • components/gas-royalties/Royalties.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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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 mock implementations minimal—only what’s necessary for the test scenarios

Applied to files:

  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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} : Organise mocks to mirror the real module structure so import paths remain consistent

Applied to files:

  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
📚 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/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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: Use Jest’s built-in mocking for module replacement; keep manual mocks simple and lightweight

Applied to files:

  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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__/**/*.{test,spec}.{js,jsx,ts,tsx} : In tests, use jest.mock('module') with a bare module specifier to load the corresponding manual mock

Applied to files:

  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.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} : Name mock files to mirror the real module names so jest.mock('module') can pick them up automatically

Applied to files:

  • __tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx
🧬 Code graph analysis (1)
components/gas-royalties/Royalties.tsx (4)
components/gas-royalties/GasRoyalties.tsx (1)
  • useSharedState (364-450)
helpers/Helpers.ts (1)
  • capitalizeEveryWord (334-338)
entities/IRoyalty.ts (1)
  • Royalty (1-11)
services/6529api.ts (1)
  • fetchUrl (7-20)
⏰ 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 (6)
components/gas-royalties/Royalties.tsx (6)

3-4: LGTM!

The import additions support the React Query refactor and align with the project's data-fetching patterns.

Based on learnings


30-48: LGTM!

All URL parameters are now destructured and available for the query key, ensuring the query refetches when any relevant parameter changes.


50-73: LGTM!

The guard condition prevents unnecessary state updates when the focus hasn't changed, and all dependencies are correctly listed.


82-116: Excellent React Query implementation!

The query properly:

  • Includes all URL-affecting parameters in the key (including isCustomBlocks, per past review)
  • Handles errors with try/catch to prevent unhandled rejections (per past review)
  • Returns an empty array on failure so the UI displays "No royalties found"
  • Preserves the numeric field normalization logic

118-125: LGTM!

The synchronization effect correctly bridges the legacy fetching state with React Query's isFetching, maintaining compatibility with existing components that consume this shared state.


127-143: LGTM!

The totals are efficiently computed using useMemo with the correct dependency array, avoiding unnecessary recalculations and replacing the previous imperative state updates.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Nov 7, 2025

Quality Gate Passed Quality Gate passed

Issues
0 New issues
1 Accepted issue

Measures
0 Security Hotspots
No data about Coverage
0.1% Duplication on New Code

See analysis details on SonarQube Cloud

@simo6529 simo6529 closed this Nov 17, 2025
@simo6529 simo6529 deleted the lint-issues-v3 branch November 17, 2025 11:15
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.

1 participant