Conversation
WalkthroughTightens 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
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
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)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (2)**/*.{ts,tsx}📄 CodeRabbit inference engine (.cursorrules)
Files:
**/*.tsx📄 CodeRabbit inference engine (.cursorrules)
Files:
🧠 Learnings (2)📓 Common learnings📚 Learning: 2025-09-28T12:29:11.651ZApplied to files:
⏰ 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)
🔇 Additional comments (2)
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. Comment |
There was a problem hiding this comment.
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 dependencyisInProgress.Line 155 includes
isInProgressin the dependency array, but it's not used anywhere in the effect body. ThevotingStatecalculation only usesisUpcomingandisCompleted. 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
useMutationor a query hook to benefit from built-in loading states, error handling, caching, and retry logic.As per coding guidelines.
26-32: Addreadonlymodifiers to props per coding guidelines.The coding guidelines specify: "Always add readonly before props". The props interface should include
readonlymodifiers for consistency with the rest of the codebase (e.g.,CollectionMetainterface 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
onCollectionClickcallsgetTokenIdsString, 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 uselist.lengthinstead ofhasListItems.Using the boolean
hasListItemsas 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 duplicaterequestAuth()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: Addreadonlymodifier to props per coding guidelines.The props object is missing the
readonlymodifier ontokenPoolId, 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: Replaceas anywith proper typing.The type assertion
as anyon 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
filterDecisionsDuringPausescan accept theDecisionPointtype directly to avoid the conversion altogether.components/drops/create/full/mobile/CreateDropFullMobile.tsx (1)
71-71: Remove the unusedprofileprop from the component interface and update the parent component accordingly.The
profileprop is passed from the parent component (CreateDropFull.tsx, line 141) but is never used within CreateDropFullMobile.tsx. It can be safely removed from both theCreateDropFullMobilePropsinterface 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 usagecomponents/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, andonMetadataRemoveare 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
distributionPlanApiFetchinside 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis 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.tsxcomponents/groups/header/GroupHeaderSelect.tsxcomponents/brain/my-stream/MyStreamWaveDesktopTabs.tsxcomponents/drops/view/DropsList.tsxcomponents/drops/create/lexical/plugins/mentions/MentionsPlugin.tsxcomponents/drops/create/full/mobile/CreateDropFullMobile.tsxcomponents/gas-royalties/Gas.tsxcomponents/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsxcomponents/drops/create/lexical/nodes/ImageNode.tsxcomponents/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscription.tsxcomponents/delegation/CollectionDelegation.tsxcomponents/distribution-plan-tool/create-snapshots/CreateSnapshots.tsxcomponents/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsxcomponents/drops/view/Drops.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/groups/page/create/GroupCreate.tsxcomponents/groups/page/GroupsPageListWrapper.tsxcomponents/gas-royalties/Royalties.tsxcomponents/drops/view/item/rate/give/DropListItemRateGive.tsxcomponents/groups/page/create/config/wallets/GroupCreateWallets.tsxcomponents/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsxcomponents/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableHeader.tsxcomponents/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsxcomponents/drops/view/item/rate/give/DropListItemRateGiveSubmit.tsxcomponents/drops/create/full/desktop/CreateDropFullDesktop.tsxcomponents/groups/page/Groups.tsxcomponents/groups/page/list/card/GroupCardActionWrapper.tsxcomponents/distribution-plan-tool/map-delegations/MapDelegationsForm.tsxcomponents/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscriptionFooter.tsxcomponents/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsxcomponents/distribution/Distribution.tsxcomponents/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsxtypes/mojs.d.tscomponents/drops/create/lexical/plugins/hashtags/HashtagsPlugin.tsxcomponents/drops/create/utils/storm/CreateDropStormViewPartQuote.tsxcomponents/groups/page/list/card/GroupCard.tsxcomponents/drops/create/compact/CreateDropCompact.tsxcomponents/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.tsxcomponents/groups/header/GroupHeaderSelect.tsxcomponents/brain/my-stream/MyStreamWaveDesktopTabs.tsxcomponents/drops/view/DropsList.tsxcomponents/drops/create/lexical/plugins/mentions/MentionsPlugin.tsxcomponents/drops/create/full/mobile/CreateDropFullMobile.tsxcomponents/gas-royalties/Gas.tsxcomponents/drops/view/item/content/nft-tag/DropListItemContentNftDetails.tsxcomponents/drops/create/lexical/nodes/ImageNode.tsxcomponents/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscription.tsxcomponents/delegation/CollectionDelegation.tsxcomponents/distribution-plan-tool/create-snapshots/CreateSnapshots.tsxcomponents/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsxcomponents/drops/view/Drops.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/groups/page/create/GroupCreate.tsxcomponents/groups/page/GroupsPageListWrapper.tsxcomponents/gas-royalties/Royalties.tsxcomponents/drops/view/item/rate/give/DropListItemRateGive.tsxcomponents/groups/page/create/config/wallets/GroupCreateWallets.tsxcomponents/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsxcomponents/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableHeader.tsxcomponents/drops/view/item/rate/give/clap/DropListItemRateGiveClap.tsxcomponents/drops/view/item/rate/give/DropListItemRateGiveSubmit.tsxcomponents/drops/create/full/desktop/CreateDropFullDesktop.tsxcomponents/groups/page/Groups.tsxcomponents/groups/page/list/card/GroupCardActionWrapper.tsxcomponents/distribution-plan-tool/map-delegations/MapDelegationsForm.tsxcomponents/distribution-plan-tool/review-distribution-plan/table/ReviewDistributionPlanTableSubscriptionFooter.tsxcomponents/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsxcomponents/distribution/Distribution.tsxcomponents/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsxcomponents/drops/create/lexical/plugins/hashtags/HashtagsPlugin.tsxcomponents/drops/create/utils/storm/CreateDropStormViewPartQuote.tsxcomponents/groups/page/list/card/GroupCard.tsxcomponents/drops/create/compact/CreateDropCompact.tsxcomponents/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
useMemois a solid improvement that aligns with React best practices. The dependency array correctly includes bothdropandquotedDrop.drop_part_id, ensuring the memoized value recomputes only when necessary. The parameter rename fromparttocandidatealso 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_LABELSconstant, and the dependency array is accurate withavailableTabsandisMemesWave.components/delegation/CollectionDelegation.tsx (1)
3-3: LGTM! Excellent refactoring using React 19.2's useEffectEvent.The use of
useEffectEventhere is the correct pattern for this scenario:
- Wrapping
resetinuseEffectEventprovides a stable function identity while always accessing current values- This allows removing
resetfrom the dependency array on line 730, preventing potential infinite loops or unnecessary re-renders- The effect now only re-runs when
accountResolution.addresschanges, which is the intended behaviorAll values accessed within
reset(refetch methods, setState calls, hook reset methods) are either stable references or will be current viauseEffectEvent.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
ReactNodeand 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
isActiveGroupVoteAllensures the local state only flips back toIDLEwhen 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?.handleexists 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
haveProfiledirectly fromconnectedProfile?.handleeliminates 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
selectedWalletsfrom 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 entiredropobject 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 fromdropstodrops.lengthoptimizes 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
contractandtokenfrom 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
setViewModeinside the callback ensures state updates are consolidated within the memoized function.
45-57: Good refactor extractingconnectedHandlefor stable memoization.Deriving
connectedHandlefromconnectedProfile?.handleand using it in both useEffect hooks ensures consistent dependency tracking and prevents unnecessary effect re-runs when otherconnectedProfileproperties change.components/drops/view/DropsList.tsx (1)
171-171: Correct dependency fix formemoizedDropsmemoization.Adding
locationto the dependency array fixes a missing dependency issue, aslocationis passed toMemoizedDropon 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
onSuccesshandler no longer receives theApiDropresponse parameter since it wasn't being used. The callback still properly invokesonSuccessfulRateChange()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.tsfile contains an ambient module declaration that augments@mojs/core(line 1), withMojsTimelineInstanceexported 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 ofuseEffectEventpattern.Using
useEffectEventto 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
nodeparameter with an underscore prefix. The parameter is required by theDOMConversionMaptype 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
loadingTypeinstead 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 returnthisfor 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
thenmethod specially, mojs intentionally usesthen()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
easingobject and available easing functionsConsider importing and using official type definitions from
@types/mojs-coreor the library itself if available, rather than maintaining custom declarations.Check if official types are available:
Additionally, verify against the official documentation:
There was a problem hiding this comment.
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
setWalletsto 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 inuseCallback, this effect will re-run on every parent render, even whenemmaListhasn't changed.The previous review already identified that the parent handlers (
onEmmaWalletsChangeandonUploadedWalletsChange) are not memoized. That recommendation to wrap them withuseCallbackstill 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/.tsxfiles.
🧹 Nitpick comments (4)
components/groups/page/create/config/wallets/CreateGroupWalletsEmma.tsx (1)
46-49: Consider memoizingonWalletsRemovewithuseCallback.The
onWalletsRemovehandler is recreated on every render and passed as a prop toGroupCreateWalletsCount. Wrapping it inuseCallbackwould 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
findByTestIdproperly handles asynchronous rendering after the back button click. However, the test doesn't verify thatmockReplacewas 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 addreadonlyto parameter.Since
getRequirementFromFileTypeis 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 markedreadonlyper 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 usinguserEventinstead offireEventfor more realistic interactions.The coding guidelines specify using
@testing-library/user-eventfor component tests.userEventsimulates real user interactions more accurately thanfireEvent, 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
📒 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.tsxcomponents/brain/my-stream/MyStreamWaveDesktopTabs.tsxcomponents/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.tsxcomponents/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.tsxcomponents/brain/my-stream/MyStreamWaveDesktopTabs.tsxcomponents/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.tsxcomponents/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/reactand@testing-library/user-eventfor 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.tsxcomponents/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
useRoutermock correctly returns themockReplacefunction, 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
typeimport forApiWaveDecisionis 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
isInProgressfrom the destructuring is appropriate if it's not used in the component logic.
68-71: LGTM: Enhanced type safety.Replacing the
any-based conversion withPick<ApiWaveDecision, "decision_time">provides proper type checking while maintaining the same runtime behavior.
87-179: LGTM: Hook dependencies are correct.All
useEffectdependency 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
editorStateand avoids recomputing the exported markdown unnecessarily.
234-242: LGTM! Correct memoization of combined media.The memoization properly depends on
dropandfiles, 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
canSubmitandonCanSubmitChange.
359-427: LGTM! Consistent usage of memoized markdown content.The
onDropPartfunction correctly uses the memoizedmarkdownContentthroughout, 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
QueryClientProviderand using thecreateTestQueryClient()helper, which configures the client with test-friendly defaults (no retries, no refetch). TherenderItemhelper 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-disabledand spinner presence during fetch- Confirming proper cleanup and
onCollectioninvocation after resolutionThe pattern of creating a controllable Promise with
resolveFetchis an excellent way to test intermediate loading states.
113-124: Good error handling verification.This test correctly verifies that when
distributionPlanApiFetchfails (returnssuccess: 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
beforeEachblock correctly clears all mock functions between tests, ensuring proper test isolation and preventing state pollution.
There was a problem hiding this comment.
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/.tsxfiles. 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: Addreadonlymodifiers 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: RemovefetchRoyaltiesfrom the dependency array.
useEffectEventreturns 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, andsetSumGasareuseStatesetters 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
setMentionedUsersprop (aliased to_setMentionedUsers) is never invoked in this component. If it's not needed, consider removing it from theCreateDropWrapperPropsinterface to simplify the API surface.components/distribution/Distribution.tsx (1)
363-371: Consider memoizing thesetPagecallback.The inline callback is recreated on every render, which may break
React.memooptimization ifPaginationuses it. Extract to auseCallbackfor 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
📒 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.tsxcomponents/gas-royalties/Royalties.tsxcomponents/gas-royalties/Gas.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsxcomponents/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.tsxcomponents/gas-royalties/Royalties.tsxcomponents/gas-royalties/Gas.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/drops/create/lexical/plugins/enter/EnterKeyPlugin.tsxcomponents/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.tsxcomponents/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
useCallbackimport is appropriate for the memoization added below.
44-47: LGTM!Wrapping
onWalletsRemoveinuseCallbackprevents unnecessary recreation of the callback on every render. The dependency array[setWallets]is correct—setSelecteddoesn't need to be included since state setters fromuseStateare stable by default.
40-42: Approved. Parent component properly memoizes callbacks.The script confirms that
onEmmaWalletsChange(andonUploadedWalletsChange) are now wrapped withuseCallbackwith stable dependency arrays. This resolves the prior concern—the effect inCreateGroupWalletsEmma.tsxwill 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
markdownContentmemoization correctly depends only oneditorStateand properly handles the null case.
234-242: LGTM!The
combinedMediasmemoization correctly merges media from existing parts and new files with proper dependencies.
244-272: LGTM!The
missingMetadatamemoization has the correct dependencies and no longer includes the unnecessarydropdependency from the previous review.
274-292: LGTM!The
missingMediamemoization correctly tracks all dependencies includingdrop,files, andcombinedMedias.
294-316: LGTM!The
canSubmitmemoization correctly evaluates submission readiness with all necessary dependencies tracked.
318-341: LGTM!The
canAddPartmemoization correctly evaluates whether a part can be added with proper dependency tracking.
343-348: LGTM!The effect correctly notifies of
canSubmitchanges with proper dependencies.
359-427: LGTM!The
onDropPartfunction correctly uses the memoizedmarkdownContentthroughout, 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
useCallbackmemoization ensures stable function identity, and the numeric-awarelocaleComparecorrectly 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 prevprevents unnecessary state updates, and the functional updater ensures correct behavior whennftIdorsearchWalletschange.
73-106: Excellent cancellation safety for async fetches.Both distribution data and photos fetches now use the
isCurrentflag 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;useEffectEventwrappers look correct.The
useEffectEventwrappers 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, andisCapacitor, and properly excludes theuseEffectEventcallbacks (shouldHandleEnterandsubmit). React 19.2.0 is confirmed, which supportsuseEffectEvent.
There was a problem hiding this comment.
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: RemovefetchRoyaltiesfrom 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 ofuseEffectEvent—to separate "event" logic from reactive dependencies.}, [ collectionFocus, dateSelection, fromDate, toDate, fromBlock, toBlock, selectedArtist, isPrimary, isCustomBlocks, - ]); + ]);Note:
fetchRoyaltiesshould not be in this dependency array since it's created withuseEffectEvent.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 whenevernftIdis present and rely on the existingfetchingflag 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 usingtriggerViewModeChangefor consistent error handling.The JSX event handlers call
onViewModeChangedirectly without handling the returned promise, while effects use thetriggerViewModeChangewrapper for error logging. For consistency and to prevent unhandled promise rejections in the console (e.g., if auth fails), consider usingtriggerViewModeChangehere 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,useEffectEventwraps this fetch function, but as noted earlier,useEffectEventis experimental.Based on coding guidelines.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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.tscomponents/groups/page/Groups.tsxcomponents/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsxcomponents/gas-royalties/Royalties.tsxcomponents/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsxcomponents/gas-royalties/Gas.tsxcomponents/react-query-wrapper/ReactQueryWrapper.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/distribution/Distribution.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling
Files:
components/groups/page/Groups.tsxcomponents/distribution-plan-tool/create-snapshots/form/CreateSnapshotFormSearchCollectionDropdownItem.tsxcomponents/gas-royalties/Royalties.tsxcomponents/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsxcomponents/gas-royalties/Gas.tsxcomponents/react-query-wrapper/ReactQueryWrapper.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/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.tscomponents/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowDownload.tsxcomponents/react-query-wrapper/ReactQueryWrapper.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/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.tsxcomponents/gas-royalties/Gas.tsxcomponents/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
connectedProfilereference changes but its handle remains the same.
56-66: Properly updated effects with complete dependencies.The effects correctly use
triggerViewModeChangefor error handling and have accurate dependency arrays includingconnectedHandle,activeProfileProxy, and the memoized callbacks.components/gas-royalties/Gas.tsx (4)
3-3: LGTM!The addition of
useCallbackanduseRefis 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
resolvedFocusequalscollectionFocus, and the dependency array is comprehensive.
64-64: LGTM!Memoizing
getUrlWithParamsprevents 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
useEffectEventhook is a stable API available in React 19.2.0, which is the React version your project uses. Youreslint-plugin-react-hooksversion (^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.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
components/drops/create/utils/CreateDropWrapper.tsx (1)
338-343: Consider requesting parent to memoizeonCanSubmitChange.The
onCanSubmitChangecallback in the dependency array may cause unnecessary re-renders if the parent component doesn't wrap it inuseCallback. 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:
getUrlWithParamswrapsgetUrl("gas")inuseCallback, thengasUrlmemoizes the result. This can be simplified to:const gasUrl = useMemo(() => getUrl("gas"), [getUrl]);Or skip the
gasUrlvariable and usegetUrlWithParams()directly in thequeryKey:const getUrlWithParams = useCallback(() => getUrl("gas"), [getUrl]); // In useQuery: queryKey: ["gas-royalties", getUrlWithParams()],components/gas-royalties/Royalties.tsx (1)
75-77: MemoizeroyaltiesUrlfor consistency and optimization.Unlike Gas.tsx (line 63),
royaltiesUrlis computed directly withoutuseMemo, causing it to be recalculated on every render even when dependencies haven't changed. For consistency and to avoid unnecessary function calls, wrap it inuseMemo: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 thefetchingvariable.The
fetchingvariable 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
fetchingwithisDistributionsFetching:- {fetching ? ( + {isDistributionsFetching ? (
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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.tsxcomponents/gas-royalties/Royalties.tsxcomponents/distribution/Distribution.tsxcomponents/gas-royalties/Gas.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling
Files:
components/drops/create/utils/CreateDropWrapper.tsxcomponents/gas-royalties/Royalties.tsxcomponents/distribution/Distribution.tsxcomponents/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.tsxcomponents/gas-royalties/Royalties.tsxcomponents/distribution/Distribution.tsxcomponents/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.tsxcomponents/distribution/Distribution.tsxcomponents/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
markdownContentandaddressfrom 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
setCollectionFocusis 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
sumGascalculation is properly memoized with the correct dependency ongas.
95-100: LGTM: Fetching state synchronization is appropriate.The effect properly syncs React Query's
isFetchingto the sharedfetchingstate, with an appropriate guard forcollectionFocus.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
setCollectionFocusis 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
fetchingtotruewhencollectionFocusis 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/fetchAllPagescalls touseDistributionDataanduseDistributionPhotoshooks 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
readonlymodifiers on all fields, conforming to the coding guidelines.As per coding guidelines.
72-82: LGTM: Numeric-aware phase sorting implemented correctly.The memoized
distributionPhasescomputation now uses numeric-awarelocaleComparewith{ 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
nftIdorsearchWalletschange, 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:
getCountForPhaseuses case-insensitive comparison forAIRDROP(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 providesphases: ["Phase1"]butallowlist[].phase: ["phase1"], the lookup silently fails, returning"-"instead of matching entries.A duplicate instance of this same pattern exists in
UserPageStatsActivityDistributionsTable.tsx(line 84).
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/distribution/Distribution.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling
Files:
components/gas-royalties/Royalties.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/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.tsxcomponents/drops/create/utils/CreateDropWrapper.tsxcomponents/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.tsxcomponents/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
markdownContentmemoization correctly depends only oneditorStateand avoids unnecessary recomputation.
230-238: LGTM!The
combinedMediasmemoization correctly derives the merged media array and depends on the appropriate values.
240-268: LGTM!The
missingMetadatacomputation correctly validates required metadata with proper presence, length, and type checks. The dependency array accurately reflects the values used.
270-288: LGTM!The
missingMediacomputation correctly validates required media using the helper function and has an accurate dependency array.
290-312: LGTM!The
canSubmitlogic 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
canAddPartlogic correctly enforces both per-part (240) and total content (24000) length limits. The dependency array is accurate.
6-6: React version is compatible withuseEffectEvent.Your project uses React 19.2.0, which supports the
useEffectEventhook. 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 tosrc/errors/wallet.ts.WalletValidationErroris properly exported from that file, so the import resolves successfully.components/gas-royalties/Royalties.tsx (1)
76-109: Solid react-query refactor. TheuseQueryswap keeps the shared fetching flag aligned without manual promise bookkeeping and still normalizes the payload before it hits the table.
There was a problem hiding this comment.
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
📒 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.tsxcomponents/distribution/Distribution.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling
Files:
components/gas-royalties/Royalties.tsxcomponents/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.tsxcomponents/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.tsxcomponents/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
useCallbackanduseMemohooks 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
isFetchingto the sharedfetchingstate consumed byGasRoyaltiesHeader. The explicitsetFetching(true)whencollectionFocusis 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
useMemoto 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 theroyaltiesarray.
43-66: LGTM! Routing effect properly guards against unnecessary updates.The added guard on lines 49-51 prevents
setCollectionFocusfrom being called when the resolved focus matches the current state, avoiding unnecessary re-renders. The dependency array correctly includescollectionFocusto support this check.components/distribution/Distribution.tsx (6)
19-22: Excellent migration to React Query hooks and proper readonly props.The imports of
useDistributionDataanduseDistributionPhotosreplace manual fetch logic with react-query, and thereadonlymodifiers 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
getCountForPhasehelper 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
useDistributionDataanduseDistributionPhotoshooks 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
useMemofordistributionPhaseswith numeric-aware sorting correctly addresses the previous sorting concern (commit 06820bd). ThehandlePageChangecallback 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
nftIdis 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.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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)
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
__tests__/components/drops/view/item/rate/give/clap/DropListItemRateGiveClap.test.tsx (3)
1-1: ReplacefireEventwithuserEventper coding guidelines.The coding guidelines require using
@testing-library/user-eventfor React component tests.userEventmore 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
asyncif not already, andawaittheuserEvent.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
.thenreturns a mock function, which means async code can still treat it as Promise-like. The past review comment requested complete removal of thethenproperty, 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 formockStopto verify cleanup behavior.
mockStopis declared, integrated into the Timeline mock, and cleared inbeforeEach, but no test asserts it's ever called. The past review comment noted that the component callstimeline.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
getUrlWithParamscallback is not stable becausegetUrlfromuseSharedStateis recreated on every render. This causes theroyaltiesUrlmemo 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
getUrlinsideuseSharedStateusinguseCallback: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
📒 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/reactand@testing-library/user-eventfor 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
fetchingstate with React Query'sisFetching, maintaining compatibility with existing components that consume this shared state.
127-143: LGTM!The totals are efficiently computed using
useMemowith the correct dependency array, avoiding unnecessary recalculations and replacing the previous imperative state updates.
|

Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests