Conversation
WalkthroughAdds paginated/infinite fetching for wave outcomes and per-outcome distributions, migrates outcome types from ApiWaveOutcomeOld to ApiWaveOutcome, wires distribution-driven rendering into outcome components, integrates IPFS avatar resolution, updates related helpers/types, query keys, and tests. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MyStream as MyStreamWaveOutcome
participant OutcomesHook as useWaveOutcomesQuery
participant InfiniteScroll as useInfiniteScroll
participant API
participant WaveOutcome
participant DistributionHook as useWaveOutcomeDistributionQuery
User->>MyStream: open wave page
MyStream->>OutcomesHook: query outcomes (waveId, page=1)
OutcomesHook->>API: GET /waves/{waveId}/outcomes?page=1
API-->>OutcomesHook: outcomes page 1
OutcomesHook-->>MyStream: return items
MyStream->>MyStream: render items + sentinel
MyStream->>InfiniteScroll: observe sentinel
User->>MyStream: scrolls to sentinel
InfiniteScroll->>OutcomesHook: trigger fetchNextPage()
OutcomesHook->>API: GET /waves/{waveId}/outcomes?page=2
API-->>OutcomesHook: outcomes page 2
OutcomesHook-->>MyStream: append items
MyStream->>WaveOutcome: render outcome (pass waveId, outcome.index)
WaveOutcome->>DistributionHook: query distribution (waveId, outcomeIndex)
DistributionHook->>API: GET /waves/{waveId}/outcomes/{index}/distribution?page=1
API-->>DistributionHook: distribution page 1
DistributionHook-->>WaveOutcome: distribution state (items, totalCount, fetchNextPage)
WaveOutcome->>WaveOutcome: render subcomponent (e.g., WaveRepOutcome) with distribution
WaveOutcome->>DistributionHook: (on "View more") fetchNextPage()
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 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)
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: 2
🧹 Nitpick comments (6)
helpers/waves/create-wave.helpers.ts (1)
208-209: LGTM: Approve outcomes correctly typed.The return type and variable declaration properly use
ApiCreateWaveOutcome. The constructed outcomes omit distribution arrays (appropriate for approve-type waves) and include all required fields.Note: Lines 228 and 237 use empty description strings for automatic credit distribution outcomes, which is valid but may warrant descriptive text for consistency.
components/brain/my-stream/MyStreamWaveOutcome.tsx (1)
3-3: Prefer direct named import forFC.Per coding guidelines, prefer direct named imports for React types instead of using
React.FC.🔎 Proposed fix
-import React, { useMemo, useRef } from "react"; +import { useMemo, useRef, type FC } from "react";Then update line 15:
-const MyStreamWaveOutcome: React.FC<MyStreamWaveOutcomeProps> = ({ wave }) => { +const MyStreamWaveOutcome: FC<MyStreamWaveOutcomeProps> = ({ wave }) => {components/waves/outcome/WaveRepOutcome.tsx (1)
37-39:remainingCountmay display misleading value.When
showAllisfalse, the "View more" button displaysremainingCountwhich istotalCount - items.length. However, ifitems.lengthis 5 andDEFAULT_AMOUNTS_TO_SHOWis 3, clicking "View more" initially reveals 2 more local items, but the button shows the server-side remaining count. This could confuse users about how many items they'll see next.Consider computing
remainingCountbased on current visibility state:🔎 Proposed fix
- const remainingCount = Math.max(totalCount - items.length, 0); + const hiddenLocalCount = Math.max(items.length - DEFAULT_AMOUNTS_TO_SHOW, 0); + const remainingFromServer = Math.max(totalCount - items.length, 0); + const remainingCount = showAll ? remainingFromServer : hiddenLocalCount + remainingFromServer;components/waves/outcome/WaveOutcome.tsx (1)
23-29: Consider extractingWaveOutcomeDistributionStateto a shared types file.This interface is defined here and the same shape is used in
WaveRepOutcome.tsx(and likelyWaveNICOutcome.tsxandWaveManualOutcome.tsx). Extracting it to a shared types file would reduce duplication and ensure type consistency.🔎 Proposed approach
Create a shared type in a types file (e.g.,
types/waves.types.ts):import type { ApiWaveOutcomeDistributionItem } from "@/generated/models/ApiWaveOutcomeDistributionItem"; export interface WaveOutcomeDistributionState { readonly items: ApiWaveOutcomeDistributionItem[]; readonly totalCount: number; readonly hasNextPage: boolean; readonly isFetchingNextPage: boolean; readonly fetchNextPage: () => void; }Then import and use it in both
WaveOutcome.tsxand the outcome components.components/waves/outcome/WaveNICOutcome.tsx (1)
110-123: Consider using item.index for more stable keys.The current key
wave-nic-outcome-${amount}-${i}uses the array indexi, which changes if items are reordered or inserted. SinceApiWaveOutcomeDistributionItemhas anindexfield, usingvisibleItemswithitem.indexwould provide a more stable key identity.🔎 Suggested change
- {amounts.map((amount, i) => ( + {visibleItems.map((item, i) => ( <div - key={`wave-nic-outcome-${amount}-${i}`} + key={`wave-nic-outcome-${item.index}`} className="tw-px-4 tw-py-3 tw-bg-gradient-to-r hover:tw-from-[#A4C2DB]/5 hover:tw-to-transparent tw-transition-colors tw-duration-300"> <div className="tw-flex tw-items-center tw-gap-4"> <span className="tw-flex tw-items-center tw-justify-center tw-size-8 tw-rounded-lg tw-bg-gradient-to-br tw-from-[#A4C2DB]/10 tw-to-[#A4C2DB]/5 tw-text-[#A4C2DB] tw-text-sm tw-font-semibold"> {i + 1} </span> <span className="tw-whitespace-nowrap tw-text-[#A4C2DB] tw-text-base tw-font-medium"> - {formatNumberWithCommas(amount)} NIC + {formatNumberWithCommas(item.amount ?? 0)} NIC </span> </div> </div> ))}components/waves/outcome/WaveManualOutcome.tsx (1)
51-53: Addtype="button"to prevent unintended form submission.The toggle button is missing
type="button", unlike WaveNICOutcome. This could cause unintended form submission if the component is used within a form context.🔎 Suggested fix
<button + type="button" onClick={() => setIsOpen(!isOpen)} className="tw-w-full tw-border-0 tw-px-4 tw-py-3 tw-bg-iron-950">
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
generated/models/ApiWave.tsis excluded by!**/generated/**
📒 Files selected for processing (13)
components/brain/my-stream/MyStreamWaveOutcome.tsx(1 hunks)components/react-query-wrapper/ReactQueryWrapper.tsx(1 hunks)components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx(2 hunks)components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx(2 hunks)components/waves/outcome/WaveManualOutcome.tsx(2 hunks)components/waves/outcome/WaveNICOutcome.tsx(2 hunks)components/waves/outcome/WaveOutcome.tsx(3 hunks)components/waves/outcome/WaveRepOutcome.tsx(2 hunks)helpers/waves/create-wave.helpers.ts(4 hunks)helpers/waves/waves.helpers.ts(2 hunks)hooks/waves/useWaveOutcomeDistributionQuery.ts(1 hunks)hooks/waves/useWaveOutcomesQuery.ts(1 hunks)openapi.yaml(0 hunks)
💤 Files with no reviewable changes (1)
- openapi.yaml
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
components/react-query-wrapper/ReactQueryWrapper.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxhooks/waves/useWaveOutcomesQuery.tscomponents/waves/outcome/WaveRepOutcome.tsxhelpers/waves/create-wave.helpers.tshelpers/waves/waves.helpers.tshooks/waves/useWaveOutcomeDistributionQuery.tscomponents/waves/outcome/WaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
components/react-query-wrapper/ReactQueryWrapper.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxcomponents/waves/outcome/WaveRepOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
components/react-query-wrapper/ReactQueryWrapper.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxhooks/waves/useWaveOutcomesQuery.tscomponents/waves/outcome/WaveRepOutcome.tsxhelpers/waves/create-wave.helpers.tshelpers/waves/waves.helpers.tshooks/waves/useWaveOutcomeDistributionQuery.tscomponents/waves/outcome/WaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
components/react-query-wrapper/ReactQueryWrapper.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxhooks/waves/useWaveOutcomesQuery.tscomponents/waves/outcome/WaveRepOutcome.tsxhelpers/waves/create-wave.helpers.tshelpers/waves/waves.helpers.tshooks/waves/useWaveOutcomeDistributionQuery.tscomponents/waves/outcome/WaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsx
🧠 Learnings (6)
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{tsx,jsx} : Use react-query for data fetching
Applied to files:
components/react-query-wrapper/ReactQueryWrapper.tsxhooks/waves/useWaveOutcomesQuery.tshooks/waves/useWaveOutcomeDistributionQuery.tscomponents/brain/my-stream/MyStreamWaveOutcome.tsx
📚 Learning: 2025-11-25T08:37:44.688Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: app/api/AGENTS.md:0-0
Timestamp: 2025-11-25T08:37:44.688Z
Learning: Applies to app/api/**/*.{ts,tsx} : Use TypeScript types for request parameters and responses; avoid `any` unless a 3rd-party payload truly has no shape guarantees.
Applied to files:
helpers/waves/waves.helpers.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Prefer Server Components over Client Components; use Server Functions/Server Actions (`'use server'`) for mutations
Applied to files:
components/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsx
🧬 Code graph analysis (10)
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)
components/ipfs/IPFSContext.tsx (1)
resolveIpfsUrlSync(77-89)
components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx (2)
components/ipfs/IPFSContext.tsx (1)
resolveIpfsUrlSync(77-89)helpers/image.helpers.ts (1)
getScaledImageUri(17-45)
hooks/waves/useWaveOutcomesQuery.ts (2)
generated/models/ApiWaveOutcomesPage.ts (1)
ApiWaveOutcomesPage(16-58)components/react-query-wrapper/utils/query-utils.ts (1)
getDefaultQueryRetry(21-34)
components/waves/outcome/WaveRepOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
helpers/waves/create-wave.helpers.ts (1)
generated/models/ApiCreateWaveOutcome.ts (1)
ApiCreateWaveOutcome(19-82)
helpers/waves/waves.helpers.ts (1)
generated/models/ApiUpdateWaveRequest.ts (1)
ApiUpdateWaveRequest(20-89)
hooks/waves/useWaveOutcomeDistributionQuery.ts (2)
generated/models/ApiWaveOutcomeDistributionItemsPage.ts (1)
ApiWaveOutcomeDistributionItemsPage(16-58)components/react-query-wrapper/utils/query-utils.ts (1)
getDefaultQueryRetry(21-34)
components/waves/outcome/WaveNICOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
components/waves/outcome/WaveManualOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
components/brain/my-stream/MyStreamWaveOutcome.tsx (6)
generated/models/ApiWave.ts (1)
ApiWave(26-171)__mocks__/react-use.js (1)
React(2-2)components/brain/my-stream/layout/LayoutContext.tsx (1)
useLayout(522-522)hooks/waves/useWaveOutcomesQuery.ts (1)
useWaveOutcomesQuery(41-105)components/common/SpinnerLoader.tsx (1)
SpinnerLoader(8-57)components/waves/outcome/WaveOutcome.tsx (1)
WaveOutcome(31-75)
⏰ 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 (26)
helpers/waves/waves.helpers.ts (1)
3-3: LGTM! Excellent type safety improvement.Restoring the
ApiUpdateWaveRequestimport and updating the return type fromanytoApiUpdateWaveRequestsignificantly improves type safety. The function body correctly constructs all required fields (name, picture, voting, visibility, participation, chat, wave) that match theApiUpdateWaveRequestschema.Based on learnings, this change properly avoids using
anyfor API request types, ensuring compile-time type checking and preventing potential runtime errors.Also applies to: 26-26
helpers/waves/create-wave.helpers.ts (3)
18-18: LGTM: Type migration to new outcome model.The import correctly transitions from
ApiWaveOutcomeOldtoApiCreateWaveOutcome, aligning with the refactoring objectives.
151-152: LGTM: Rank outcomes correctly typed.The return type and variable declaration properly reflect the new
ApiCreateWaveOutcomestructure. All constructed outcome objects include required fields and appropriate optional fields for MANUAL, REP, and NIC outcome types.
250-250: LGTM: Outcome delegation correctly typed.The return type correctly reflects the new
ApiCreateWaveOutcome[]structure and delegates appropriately to wave-type-specific helpers.components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)
12-12: LGTM! Consistent IPFS URL resolution.The IPFS URL resolution is correctly implemented and aligns with the pattern used in other leaderboard components like WaveleaderboardDropRaters.tsx.
Also applies to: 34-34
components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx (1)
14-14: LGTM! Correct IPFS URL resolution with Next.js Image.The implementation correctly resolves IPFS URLs for voter profile pictures and properly uses the Next.js
<Image>component. The order of operations (scaling then IPFS resolution) works correctly for both IPFS protocol URLs and standard HTTP URLs.Also applies to: 80-83
components/brain/my-stream/MyStreamWaveOutcome.tsx (4)
21-29: LGTM!Good integration with the new
useWaveOutcomesQueryhook. The destructured properties cover all necessary states for proper UI handling.
36-43: LGTM!Proper implementation of infinite scroll with a reasonable 200px root margin for preloading content before the user reaches the end.
64-78: LGTM!The key pattern
${outcome.index ?? index}-${outcome.type}correctly uses the nullish coalescing operator, which only falls back to the array index whenoutcome.indexisnullorundefined(not when it's0). The sentinel element and loading spinner placement are appropriate for infinite scroll.
59-63: LGTM!Good defensive condition that prevents showing the empty state during background refetches by checking
!isFetching.components/waves/outcome/WaveRepOutcome.tsx (2)
41-48: LGTM!The
onViewMorehandler correctly handles both revealing locally cached items and fetching additional pages. The guard!isFetchingNextPageprevents duplicate fetch requests.
120-133: LGTM!The rendering correctly displays 1-based position numbers. The key
wave-rep-outcome-${amount}-${i}is unique since the indexidifferentiates items with identical amounts.hooks/waves/useWaveOutcomesQuery.ts (4)
1-14: LGTM!Clean imports and proper use of
"use client"directive. The type imports forInfiniteDataandUseInfiniteQueryResultare correctly used with thetypekeyword.
41-65: LGTM!Excellent input normalization with proper handling of edge cases (trimming whitespace, validating positive integers, defaulting sort direction). The query key correctly includes all parameters that affect the response.
67-89: LGTM!Well-structured infinite query configuration. The
getNextPageParamcorrectly uses thenextboolean andpagenumber fromApiWaveOutcomesPage. UsingkeepPreviousDataprovides smooth UX during pagination. Based on learnings, react-query is the correct choice for data fetching.
91-104: LGTM!Clean return value construction with proper memoization of the flattened
outcomesarray. The error message extraction safely handles non-Error types by returningundefined.components/waves/outcome/WaveOutcome.tsx (2)
31-48: LGTM!Good separation of concerns - the component fetches distribution data and passes it to specialized outcome components. The
Boolean(hasNextPage)on line 45 is defensive but harmless sincehasNextPagefrom react-query is already a boolean.
62-74: LGTM!The Record-based component selection pattern is readable and maintainable. While it eagerly creates all three JSX elements, React's reconciliation efficiently handles this without significant overhead.
hooks/waves/useWaveOutcomeDistributionQuery.ts (3)
1-42: Well-structured hook with proper type exports and defaults.The type definitions, constants, and exports are well-organized. Using
Readonly<>wrapper on the params parameter at line 50 aligns with the coding guidelines for readonly props.
64-102: Query configuration looks solid.The infinite query setup correctly handles pagination with
getNextPageParam, useskeepPreviousDatafor smooth UX during page transitions, and integrates the default retry logic.
104-119: LGTM!The result derivation correctly flattens paginated data and extracts the total count from the first page. The error message extraction is properly type-guarded.
components/waves/outcome/WaveNICOutcome.tsx (2)
11-20: Props interface follows coding guidelines with readonly modifiers.The distribution prop shape clearly defines the contract for paginated data with fetch controls, which aligns well with the refactored architecture.
30-48: Logic for pagination and visibility is correct.The
shouldShowMorecondition properly handles both scenarios: when there are more pages to fetch from the server, and when there are more already-loaded items to reveal locally. TheonViewMorehandler correctly orchestrates both state changes.components/waves/outcome/WaveManualOutcome.tsx (3)
11-47: Consistent implementation with WaveNICOutcome.The props interface and pagination logic are consistent with WaveNICOutcome, which aids maintainability. The use of readonly modifiers follows coding guidelines.
118-120: Verify the conditional logic for displaying description.The condition
item.amount ? item.description : ""will hide the description whenamountis0ornull/undefined. If the intent is to always show the description when present, this should beitem.description ?? "". If the intent is to show description only for non-zero amounts, consider usingitem.amount !== 0 && item.amount != null ? item.description : ""to be explicit.
110-123: Good use of item.index in the key.The key includes
item.indexwhich provides stability. The additionalitem.amountanditem.descriptionare redundant ifitem.indexis unique, but this doesn't cause any issues.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/waves/outcome/WaveManualOutcome.tsx (1)
52-52: Add missing type attribute for consistency.The button should have
type="button"to be consistent with the same button inWaveNICOutcome.tsx(line 52) andWaveRepOutcome.tsx(line 52).Proposed fix
<button + type="button" onClick={() => setIsOpen(!isOpen)} className="tw-w-full tw-border-0 tw-px-4 tw-py-3 tw-bg-iron-950">
🧹 Nitpick comments (2)
components/waves/outcome/WaveNICOutcome.tsx (1)
24-48: Consider extracting shared logic into a custom hook.This component shares nearly identical logic with
WaveRepOutcomeandWaveManualOutcome(distribution destructuring, visibleItems calculation, remainingCount, shouldShowMore, and onViewMore). Consider extracting this into a shared custom hook likeuseOutcomeDistributionto reduce duplication and improve maintainability.Example structure for shared hook
function useOutcomeDistribution( distribution: { items: ApiWaveOutcomeDistributionItem[]; totalCount: number; hasNextPage: boolean; isFetchingNextPage: boolean; fetchNextPage: () => void; }, defaultVisible: number = 3 ) { const [showAll, setShowAll] = useState(false); const { items, totalCount, hasNextPage, isFetchingNextPage, fetchNextPage } = distribution; const visibleItems = showAll ? items : items.slice(0, defaultVisible); const remainingCount = Math.max(totalCount - visibleItems.length, 0); const shouldShowMore = hasNextPage || (!showAll && items.length > defaultVisible); const onViewMore = () => { if (!showAll) setShowAll(true); if (hasNextPage && !isFetchingNextPage) fetchNextPage(); }; return { visibleItems, remainingCount, shouldShowMore, onViewMore, totalCount }; }components/waves/outcome/WaveManualOutcome.tsx (1)
112-112: Simplify key to use only unique identifier.The key includes
amountanddescriptionwhich are not unique identifiers and can cause rendering issues. Use onlyitem.indexwhich is the unique identifier.Proposed fix
<div - key={`wave-manual-outcome-${item.amount ?? "na"}-${item.description ?? "na"}-${item.index}`} + key={`wave-manual-outcome-${item.index}`} className="tw-px-4 tw-py-3 tw-bg-gradient-to-r hover:tw-from-amber-500/5 hover:tw-to-transparent tw-transition-colors tw-duration-300">
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (31)
generated/models/AirdropAddressResponse.tsis excluded by!**/generated/**generated/models/AirdropAddressResponseTdhWallet.tsis excluded by!**/generated/**generated/models/AllowlistNormalizedEntry.tsis excluded by!**/generated/**generated/models/DistributionNormalized.tsis excluded by!**/generated/**generated/models/DistributionNormalizedPage.tsis excluded by!**/generated/**generated/models/DistributionPhasesPage.tsis excluded by!**/generated/**generated/models/DistributionPhoto.tsis excluded by!**/generated/**generated/models/DistributionPhotosPage.tsis excluded by!**/generated/**generated/models/NFTFinalSubscription.tsis excluded by!**/generated/**generated/models/NFTFinalSubscriptionUpload.tsis excluded by!**/generated/**generated/models/NFTFinalSubscriptionUploadPage.tsis excluded by!**/generated/**generated/models/NFTSubscription.tsis excluded by!**/generated/**generated/models/ObjectSerializer.tsis excluded by!**/generated/**generated/models/RedeemedSubscription.tsis excluded by!**/generated/**generated/models/RedeemedSubscriptionCounts.tsis excluded by!**/generated/**generated/models/RedeemedSubscriptionCountsPage.tsis excluded by!**/generated/**generated/models/RedeemedSubscriptionPage.tsis excluded by!**/generated/**generated/models/SubscribeAllEditionsResponse.tsis excluded by!**/generated/**generated/models/SubscriptionCountResponse.tsis excluded by!**/generated/**generated/models/SubscriptionCounts.tsis excluded by!**/generated/**generated/models/SubscriptionDetails.tsis excluded by!**/generated/**generated/models/SubscriptionLog.tsis excluded by!**/generated/**generated/models/SubscriptionLogPage.tsis excluded by!**/generated/**generated/models/SubscriptionModeResponse.tsis excluded by!**/generated/**generated/models/SubscriptionResponse.tsis excluded by!**/generated/**generated/models/SubscriptionTopUp.tsis excluded by!**/generated/**generated/models/SubscriptionTopUpPage.tsis excluded by!**/generated/**generated/models/UpdateSubscribeAllEditionsRequest.tsis excluded by!**/generated/**generated/models/UpdateSubscriptionCountRequest.tsis excluded by!**/generated/**generated/models/UpdateSubscriptionModeRequest.tsis excluded by!**/generated/**generated/models/UpdateSubscriptionRequest.tsis excluded by!**/generated/**
📒 Files selected for processing (3)
components/waves/outcome/WaveManualOutcome.tsx(2 hunks)components/waves/outcome/WaveNICOutcome.tsx(2 hunks)components/waves/outcome/WaveRepOutcome.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
components/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/outcome/WaveRepOutcome.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
components/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/outcome/WaveRepOutcome.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
components/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/outcome/WaveRepOutcome.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
components/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/outcome/WaveRepOutcome.tsx
🧬 Code graph analysis (2)
components/waves/outcome/WaveManualOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
components/waves/outcome/WaveRepOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
⏰ 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 (3)
components/waves/outcome/WaveNICOutcome.tsx (1)
3-48: Approve refactoring to distribution-based pagination.The component correctly accepts and uses the distribution prop for pagination. The logic for
visibleItems,remainingCount, andshouldShowMoreis sound, andonViewMoreproperly handles both expanding the visible items and fetching the next page.components/waves/outcome/WaveRepOutcome.tsx (1)
3-48: LGTM - consistent implementation.The distribution-based pagination logic is correctly implemented and consistent with
WaveNICOutcome. The component properly handles showing visible items, calculating remaining count, and fetching more pages.components/waves/outcome/WaveManualOutcome.tsx (1)
24-47: LGTM - distribution integration is correct.The component correctly integrates the distribution prop and implements pagination logic consistent with the other outcome components.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
components/waves/outcome/WaveRepOutcome.tsx (1)
121-134: Useitem.indexfor stable keys instead ofamount.The key
wave-rep-outcome-${amount}-${i}can produce duplicates if two items have the same amount value, causing React reconciliation issues. Useitem.indexfrom the distribution item for guaranteed uniqueness, consistent withWaveNICOutcome(Line 105).🔎 Proposed fix
- {amounts.map((amount, i) => ( + {visibleItems.map((item, i) => ( <div - key={`wave-rep-outcome-${amount}-${i}`} + key={`wave-rep-outcome-${item.index}`} className="tw-px-4 tw-py-3 tw-bg-gradient-to-r hover:tw-from-[#C3B5D9]/5 hover:tw-to-transparent tw-transition-colors tw-duration-300"> <div className="tw-flex tw-items-center tw-gap-4"> <span className="tw-flex tw-items-center tw-justify-center tw-size-8 tw-rounded-lg tw-bg-gradient-to-br tw-from-[#C3B5D9]/10 tw-to-[#C3B5D9]/5 tw-text-[#C3B5D9] tw-text-sm tw-font-semibold"> {i + 1} </span> <span className="tw-whitespace-nowrap tw-text-[#C3B5D9] tw-text-base tw-font-medium"> - {formatNumberWithCommas(amount)} Rep + {formatNumberWithCommas(item.amount ?? 0)} Rep </span> </div> </div> ))}__tests__/components/waves/outcome/WaveOutcome.test.tsx (1)
17-49: UserenderWithQueryClient()to wrap component renders.The tests use standard
render()without therenderWithQueryClient()test utility that's already available in__tests__/utils/reactQuery.tsx. SinceWaveOutcomecallsuseWaveOutcomeDistributionQuery, which requires React Query'sQueryClientProvidercontext, replacerender()withrenderWithQueryClient()in all test cases.
🧹 Nitpick comments (5)
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)
33-40: Implementation correctly addresses the previous ESLint violation.The
<img>element has been successfully replaced with Next.js<Image>component, resolving the@next/next/no-img-elementESLint rule violation flagged in the previous review. The implementation withfillandsizes="44px"works correctly.Since the image size is fixed at 44×44px, using explicit
widthandheightprops would be simpler and eliminate the need fortw-relativeon the parent:🔎 Optional simplification using fixed dimensions
- <div className="tw-h-full tw-text-center tw-flex tw-items-center tw-justify-center tw-rounded-lg tw-overflow-hidden tw-relative"> + <div className="tw-h-full tw-text-center tw-flex tw-items-center tw-justify-center tw-rounded-lg tw-overflow-hidden"> <Image src={resolveIpfsUrlSync(drop.author.pfp)} alt="Profile picture" - fill - sizes="44px" - className="tw-bg-transparent tw-object-contain" + width={44} + height={44} + className="tw-rounded-lg tw-object-contain" /> </div>As per coding guidelines, Image components from
next/imageshould be used for all images.components/brain/my-stream/MyStreamWaveOutcome.tsx (1)
3-3: UnusedReactimport.The
Reactnamespace import is unused since the modern JSX transform handles JSX without requiring it. OnlyFC,useMemo, anduseRefare needed.🔎 Proposed fix
-import React, { FC, useMemo, useRef } from "react"; +import { FC, useMemo, useRef } from "react";components/waves/outcome/WaveOutcome.tsx (1)
34-40: Consider memoizingdistributionStateto stabilize object reference.The
distributionStateobject is recreated on every render, which could cause unnecessary re-renders in child components if they perform reference equality checks or useReact.memo. Wrapping it withuseMemowould stabilize the reference when values haven't changed.🔎 Proposed fix
+import { FC, type JSX, useMemo } from "react"; -import { FC, type JSX } from "react"; ... - const distributionState: WaveOutcomeDistributionState = { - items, - totalCount, - hasNextPage: Boolean(hasNextPage), - isFetchingNextPage, - fetchNextPage, - }; + const distributionState: WaveOutcomeDistributionState = useMemo( + () => ({ + items, + totalCount, + hasNextPage: Boolean(hasNextPage), + isFetchingNextPage, + fetchNextPage, + }), + [items, totalCount, hasNextPage, isFetchingNextPage, fetchNextPage] + );components/waves/outcome/WaveManualOutcome.tsx (2)
34-41: Consider adding loading feedback when fetching next page.The
isFetchingNextPagestate is destructured but not used to provide visual feedback to the user. Consider disabling the button or showing a loading indicator while fetching.Suggested improvement
{shouldShowMore && ( <button className="tw-border-0 tw-w-full tw-px-4 tw-py-3 tw-text-left tw-bg-iron-900 tw-text-amber-300/80 tw-text-sm hover:tw-text-amber-300 tw-transition-all tw-duration-300" - onClick={onViewMore}> - <span>View more</span> + onClick={onViewMore} + disabled={isFetchingNextPage}> + <span>{isFetchingNextPage ? "Loading..." : "View more"}</span> <span className="tw-ml-1 tw-text-iron-400">•</span> <span className="tw-ml-1 tw-text-iron-400"> {remainingCount} more </span> </button> )}Also applies to: 120-130
105-108: Consider simplifying the key.The key construction is complex. If
item.indexis unique within the outcome's distribution (as suggested by the API model), it would be cleaner to use it directly.Suggested simplification
{visibleItems.map((item, i) => ( <div - key={`wave-manual-outcome-${item.amount ?? "na"}-${item.description ?? "na"}-${item.index}`} + key={`wave-manual-outcome-${item.index}`} className="tw-px-4 tw-py-3 tw-bg-gradient-to-r hover:tw-from-amber-500/5 hover:tw-to-transparent tw-transition-colors tw-duration-300">
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
__tests__/components/waves/outcome/WaveOutcome.test.tsx(1 hunks)components/brain/my-stream/MyStreamWaveOutcome.tsx(1 hunks)components/react-query-wrapper/ReactQueryWrapper.tsx(2 hunks)components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx(2 hunks)components/waves/outcome/WaveManualOutcome.tsx(2 hunks)components/waves/outcome/WaveNICOutcome.tsx(2 hunks)components/waves/outcome/WaveOutcome.tsx(3 hunks)components/waves/outcome/WaveRepOutcome.tsx(2 hunks)types/waves.types.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/react-query-wrapper/ReactQueryWrapper.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxtypes/waves.types.tscomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxtypes/waves.types.tscomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxtypes/waves.types.tscomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveNICOutcome.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/@(__tests__|*.test).{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Tests should live in
__tests__/orComponentName.test.tsx; mock external dependencies and APIs in tests
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
**/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Place tests in
__tests__/directory or asComponentName.test.tsxalongside components
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
__tests__/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use Jest +
ts-jestfor TypeScript testing
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
__tests__/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (tests/AGENTS.md)
__tests__/**/*.{ts,tsx,js}: Preferfor...ofloops overforEachas it allowsbreak/continueand works with async/await
Usearray.at(-1)andarray.at(-2)instead of index-based array access for negative indexing
UseString.prototype.replaceAll()instead ofreplace()for global string replacements
UseglobalThis.fetch()instead of directfetch()calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Useelement.remove()instead ofparent.removeChild(element)for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use semantic HTML elements (
<label>,<output>) over ARIA attributes when possible; every form control must have a label
Files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
🧠 Learnings (17)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)
Applied to files:
__tests__/components/waves/outcome/WaveOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests
Applied to files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests
Applied to files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label
Applied to files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant
Applied to files:
__tests__/components/waves/outcome/WaveOutcome.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{tsx,jsx} : Use react-query for data fetching
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Replace `<img>` elements with `<Image />` from `next/image`
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Replace `<img>` elements with `<Image />` from `next/image` to satisfy `next/next/no-img-element` ESLint rule
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use framework APIs: `<Link>` for internal links, `next/image` for images, adopt Next's ESLint rules
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use framework APIs: internal links should use `<Link>`, images should use `next/image`, and adopt Next's ESLint rules (Core Web Vitals)
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `<Link href="/path">` from Next.js for internal navigation instead of plain HTML links to satisfy `next/next/no-html-link-for-pages` ESLint rule
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Prefer Server Components over Client Components; use Server Functions/Server Actions (`'use server'`) for mutations
Applied to files:
components/waves/outcome/WaveOutcome.tsx
🧬 Code graph analysis (5)
components/waves/outcome/WaveRepOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-126)
types/waves.types.ts (1)
generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
components/waves/outcome/WaveNICOutcome.tsx (3)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-126)helpers/Helpers.ts (1)
formatNumberWithCommas(131-148)
components/waves/outcome/WaveManualOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-126)
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)
components/ipfs/IPFSContext.tsx (1)
resolveIpfsUrlSync(77-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 (11)
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)
6-6: LGTM: Imports correctly added.The Image component and resolveIpfsUrlSync imports are properly added to support the Next.js Image optimization and IPFS URL resolution.
Also applies to: 13-13
components/brain/my-stream/MyStreamWaveOutcome.tsx (1)
36-78: Well-structured infinite scroll implementation.The pagination logic correctly separates initial loading from fetching next pages, and the sentinel placement within the outcomes container enables proper intersection-based loading. The empty state handling with
!isFetchingprevents flickering during data fetches.types/waves.types.ts (1)
120-126: Well-designed distribution state interface.The
WaveOutcomeDistributionStateinterface cleanly encapsulates pagination state with properreadonlymodifiers. Usingimport typeforApiWaveOutcomeDistributionItemfollows best practices for type-only imports.components/waves/outcome/WaveOutcome.tsx (1)
54-66: The component lookup pattern instantiates all variants.The
Record<OutcomeType, JSX.Element>approach creates all three outcome components on every render, even though only one is displayed. This is a minor inefficiency. Consider conditional rendering if performance becomes a concern, but this is acceptable for now.components/waves/outcome/WaveRepOutcome.tsx (1)
42-49: Pagination logic is well-implemented.The
onViewMorehandler correctly manages both local expansion (showAll) and server-side pagination, with proper guard against duplicate fetches viaisFetchingNextPage.components/waves/outcome/WaveNICOutcome.tsx (1)
18-41: Clean distribution-based implementation.The component properly uses
item.indexfor keys and correctly separates local (showAll) and server-side pagination state. TheremainingCountcalculation is simpler thanWaveRepOutcomebut achieves the same result whenshowAllis true.components/waves/outcome/WaveManualOutcome.tsx (5)
1-9: LGTM!Imports are clean with appropriate type imports and direct named imports from React as per coding guidelines.
11-14: LGTM!Props interface correctly uses
readonlymodifiers and properly typed with the newApiWaveOutcomeandWaveOutcomeDistributionStatetypes.
22-32: LGTM!State derivation logic is sound. The
shouldShowMorecondition correctly handles both local item hiding (!showAll && items.length > DEFAULT_AMOUNTS_TO_SHOW) and server-side pagination (hasNextPage).
113-115: LGTM!The description display logic has been corrected to use
{item.description ?? ""}, ensuring the description is shown regardless of whether an amount exists.
43-94: LGTM!The accordion header section is well-structured with proper
type="button"attribute, appropriate FontAwesome icons, and clean TailwindCSS styling. The motion elements provide smooth animations for the expand/collapse indicator.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
components/waves/outcome/WaveOutcome.tsx (1)
34-43: Consider removing redundant useMemo.The
distributionStateobject is memoized, but all its dependencies (items,totalCount,hasNextPage,isFetchingNextPage,fetchNextPage) are already stable references returned fromreact-query. TheuseMemoprovides minimal benefit here and adds complexity.🔎 Simplified alternative
- const distributionState: WaveOutcomeDistributionState = useMemo( - () => ({ - items, - totalCount, - hasNextPage: Boolean(hasNextPage), - isFetchingNextPage, - fetchNextPage, - }), - [items, totalCount, hasNextPage, isFetchingNextPage, fetchNextPage] - ); + const distributionState: WaveOutcomeDistributionState = { + items, + totalCount, + hasNextPage: Boolean(hasNextPage), + isFetchingNextPage, + fetchNextPage, + };components/waves/outcome/WaveRepOutcome.tsx (1)
136-146: Consider disabling the "View more" button during fetch for consistency.The button checks
isFetchingNextPagein the click handler but doesn't visually disable the button. This is inconsistent withWaveManualOutcome.tsx(line 133) which usesdisabled={isFetchingNextPage}and shows "Loading..." text. Users might click multiple times while fetching, even though the handler guards against it.🔎 Proposed enhancement
{shouldShowMore && ( <button className="tw-border-0 tw-w-full tw-px-4 tw-py-3 tw-text-left tw-bg-iron-900 tw-text-[#C3B5D9]/80 tw-text-sm hover:tw-text-[#C3B5D9] tw-transition-all tw-duration-300" - onClick={onViewMore}> + onClick={onViewMore} + disabled={isFetchingNextPage}> - <span>View more</span> + <span>{isFetchingNextPage ? "Loading..." : "View more"}</span> <span className="tw-ml-1 tw-text-iron-400">•</span> <span className="tw-ml-1 tw-text-iron-400"> {remainingCount} more </span> </button> )}
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
__tests__/components/waves/outcome/WaveManualOutcome.test.tsx(1 hunks)__tests__/components/waves/outcome/WaveOutcome.test.tsx(1 hunks)__tests__/components/waves/outcome/WaveRepOutcome.test.tsx(1 hunks)components/brain/my-stream/MyStreamWaveOutcome.tsx(1 hunks)components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx(2 hunks)components/waves/outcome/WaveManualOutcome.tsx(2 hunks)components/waves/outcome/WaveOutcome.tsx(3 hunks)components/waves/outcome/WaveRepOutcome.tsx(2 hunks)hooks/waves/useWaveOutcomeDistributionQuery.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/components/waves/outcome/WaveOutcome.test.tsx
- hooks/waves/useWaveOutcomeDistributionQuery.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
components/waves/outcome/WaveRepOutcome.tsx__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
components/waves/outcome/WaveRepOutcome.tsx__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
components/waves/outcome/WaveRepOutcome.tsx__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
components/waves/outcome/WaveRepOutcome.tsx__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsxcomponents/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/@(__tests__|*.test).{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Tests should live in
__tests__/orComponentName.test.tsx; mock external dependencies and APIs in tests
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
**/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Place tests in
__tests__/directory or asComponentName.test.tsxalongside components
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
__tests__/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use Jest +
ts-jestfor TypeScript testing
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
__tests__/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (tests/AGENTS.md)
__tests__/**/*.{ts,tsx,js}: Preferfor...ofloops overforEachas it allowsbreak/continueand works with async/await
Usearray.at(-1)andarray.at(-2)instead of index-based array access for negative indexing
UseString.prototype.replaceAll()instead ofreplace()for global string replacements
UseglobalThis.fetch()instead of directfetch()calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Useelement.remove()instead ofparent.removeChild(element)for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use semantic HTML elements (
<label>,<output>) over ARIA attributes when possible; every form control must have a label
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
🧠 Learnings (14)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)
Applied to files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/components/waves/outcome/WaveManualOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant
Applied to files:
__tests__/components/waves/outcome/WaveManualOutcome.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Replace `<img>` elements with `<Image />` from `next/image`
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Replace `<img>` elements with `<Image />` from `next/image` to satisfy `next/next/no-img-element` ESLint rule
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use framework APIs: `<Link>` for internal links, `next/image` for images, adopt Next's ESLint rules
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use framework APIs: internal links should use `<Link>`, images should use `next/image`, and adopt Next's ESLint rules (Core Web Vitals)
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsxcomponents/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `<Link href="/path">` from Next.js for internal navigation instead of plain HTML links to satisfy `next/next/no-html-link-for-pages` ESLint rule
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Applied to files:
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{tsx,jsx} : Use react-query for data fetching
Applied to files:
components/brain/my-stream/MyStreamWaveOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)
Applied to files:
components/waves/outcome/WaveOutcome.tsx
🧬 Code graph analysis (7)
components/waves/outcome/WaveRepOutcome.tsx (3)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-126)helpers/Helpers.ts (1)
formatNumberWithCommas(131-148)
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx (1)
components/waves/outcome/WaveRepOutcome.tsx (1)
WaveRepOutcome(18-153)
__tests__/components/waves/outcome/WaveManualOutcome.test.tsx (1)
components/waves/outcome/WaveManualOutcome.tsx (1)
WaveManualOutcome(18-147)
components/waves/outcome/WaveManualOutcome.tsx (2)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)helpers/Helpers.ts (1)
formatNumberWithCommas(131-148)
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)
components/ipfs/IPFSContext.tsx (1)
resolveIpfsUrlSync(77-89)
components/brain/my-stream/MyStreamWaveOutcome.tsx (5)
generated/models/ApiWave.ts (1)
ApiWave(27-179)components/brain/my-stream/layout/LayoutContext.tsx (1)
useLayout(522-522)hooks/waves/useWaveOutcomesQuery.ts (1)
useWaveOutcomesQuery(41-105)components/common/SpinnerLoader.tsx (1)
SpinnerLoader(8-57)components/waves/outcome/WaveOutcome.tsx (1)
WaveOutcome(23-70)
components/waves/outcome/WaveOutcome.tsx (3)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)hooks/waves/useWaveOutcomeDistributionQuery.ts (1)
useWaveOutcomeDistributionQuery(44-120)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-126)
⏰ 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 (7)
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (2)
6-6: LGTM! Correct imports for Next.js Image optimization and IPFS resolution.The imports correctly bring in the Next.js
Imagecomponent and the IPFS URL resolver, aligning with the coding guidelines and the broader PR pattern.Also applies to: 13-13
34-40:andcomponents/waves/outcome/WaveManualOutcome.tsx (1)
105-127: LGTM! Distribution-driven rendering implemented correctly.The itemLabel logic properly handles all cases:
- Zero amounts display as "-"
- Non-zero amounts show formatted numbers
- Missing amounts fall back to descriptions
This addresses the previous review concern about description display and aligns with the new distribution-based architecture.
components/brain/my-stream/MyStreamWaveOutcome.tsx (4)
1-9: LGTM: Proper Client Component setup with correct imports.The
"use client"directive is correctly placed, and the migration fromReact.FCto direct named imports aligns with the coding guidelines. The new imports for infinite scroll and data fetching are appropriate for the refactored functionality.
18-43: LGTM: Clean infinite scroll implementation.The integration of
useWaveOutcomesQueryanduseInfiniteScrollfollows best practices. The refs are properly typed, and all necessary parameters are correctly passed to the infinite scroll hook.
45-46: LGTM: Appropriate loading state logic.The helper variables correctly differentiate between initial loading and subsequent pagination fetches, ensuring proper UI states are displayed.
47-78: Render logic and key generation are correct.The conditional rendering properly handles all UI states (initial loading, error, empty, data, pagination). The empty state check correctly includes
!isFetchingto prevent displaying "No outcomes" while paginating.The key generation uses
outcome.index ?? indexwhereoutcome.indexis a required (non-optional) number property on theApiWaveOutcometype, ensuring stable, unique keys that won't be affected by reordering or filtering of outcomes.
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
components/waves/outcome/WaveManualOutcome.tsx (1)
38-40: Consider aligningremainingCountcalculation withWaveRepOutcome.This uses
totalCount - visibleItems.length, whileWaveRepOutcomedistinguishes between locally hidden items and server-side remaining items. Both work, but the simpler calculation here may show slightly inaccurate counts whenshowAllis false and there are more items locally than displayed.🔎 Align with WaveRepOutcome's pattern for consistency
- const remainingCount = Math.max(totalCount - visibleItems.length, 0); + const hiddenLocalCount = Math.max( + items.length - DEFAULT_AMOUNTS_TO_SHOW, + 0 + ); + const remainingFromServer = Math.max(totalCount - items.length, 0); + const remainingCount = showAll + ? remainingFromServer + : hiddenLocalCount + remainingFromServer;__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx (1)
4-11: Remove unusedfetchMockimport and variable.
commonApiFetchis mocked butfetchMockis never used in the tests. This creates dead code.🔎 Remove unused import and variable
import { useWaveOutcomeDistributionQuery } from '@/hooks/waves/useWaveOutcomeDistributionQuery'; import { useInfiniteQuery } from '@tanstack/react-query'; -import { commonApiFetch } from '@/services/api/common-api'; import { QueryKey } from '@/components/react-query-wrapper/ReactQueryWrapper'; jest.mock('@tanstack/react-query'); -jest.mock('@/services/api/common-api'); const useInfiniteQueryMock = useInfiniteQuery as jest.Mock; -const fetchMock = commonApiFetch as jest.Mock;components/waves/outcome/WaveNICOutcome.tsx (1)
150-160: Consider adding loading state to the "View more" button.The button doesn't show loading feedback when
isFetchingNextPageis true. Based on the test expectations for WaveRepOutcome (lines 56-58 in the test file), the "View more" button should display loading text and be disabled during pagination for consistent UX.🔎 Suggested implementation
{shouldShowMore && ( <button onClick={onViewMore} + disabled={isFetchingNextPage} className="tw-border-0 tw-w-full tw-px-4 tw-py-3 tw-text-left tw-bg-iron-900 tw-text-[#A4C2DB]/80 tw-text-sm hover:tw-text-[#A4C2DB] tw-transition-all tw-duration-300"> - <span>View more</span> + <span>{isFetchingNextPage ? "loading..." : "View more"}</span> <span className="tw-ml-1 tw-text-iron-400">•</span> <span className="tw-ml-1 tw-text-iron-400"> {remainingCount} more </span> </button> )}
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
__tests__/components/waves/outcome/WaveManualOutcome.test.tsx(1 hunks)__tests__/components/waves/outcome/WaveOutcome.test.tsx(1 hunks)__tests__/components/waves/outcome/WaveRepOutcome.test.tsx(2 hunks)__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx(1 hunks)components/waves/outcome/WaveManualOutcome.tsx(3 hunks)components/waves/outcome/WaveNICOutcome.tsx(3 hunks)components/waves/outcome/WaveOutcome.tsx(3 hunks)components/waves/outcome/WaveRepOutcome.tsx(3 hunks)hooks/waves/useWaveOutcomeDistributionQuery.ts(1 hunks)types/waves.types.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/components/waves/outcome/WaveOutcome.test.tsx
- tests/components/waves/outcome/WaveManualOutcome.test.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
components/waves/outcome/WaveNICOutcome.tsxhooks/waves/useWaveOutcomeDistributionQuery.tstypes/waves.types.ts__tests__/components/waves/outcome/WaveRepOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
components/waves/outcome/WaveNICOutcome.tsx__tests__/components/waves/outcome/WaveRepOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
components/waves/outcome/WaveNICOutcome.tsxhooks/waves/useWaveOutcomeDistributionQuery.tstypes/waves.types.ts__tests__/components/waves/outcome/WaveRepOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
components/waves/outcome/WaveNICOutcome.tsxhooks/waves/useWaveOutcomeDistributionQuery.tstypes/waves.types.ts__tests__/components/waves/outcome/WaveRepOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsxcomponents/waves/outcome/WaveRepOutcome.tsxcomponents/waves/outcome/WaveOutcome.tsx
**/@(__tests__|*.test).{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Tests should live in
__tests__/orComponentName.test.tsx; mock external dependencies and APIs in tests
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
**/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Place tests in
__tests__/directory or asComponentName.test.tsxalongside components
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
__tests__/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use Jest +
ts-jestfor TypeScript testing
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
__tests__/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (tests/AGENTS.md)
__tests__/**/*.{ts,tsx,js}: Preferfor...ofloops overforEachas it allowsbreak/continueand works with async/await
Usearray.at(-1)andarray.at(-2)instead of index-based array access for negative indexing
UseString.prototype.replaceAll()instead ofreplace()for global string replacements
UseglobalThis.fetch()instead of directfetch()calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Useelement.remove()instead ofparent.removeChild(element)for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use semantic HTML elements (
<label>,<output>) over ARIA attributes when possible; every form control must have a label
Files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsx__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
🧠 Learnings (7)
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{tsx,jsx} : Use react-query for data fetching
Applied to files:
hooks/waves/useWaveOutcomeDistributionQuery.ts__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsxcomponents/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)
Applied to files:
__tests__/components/waves/outcome/WaveRepOutcome.test.tsxcomponents/waves/outcome/WaveManualOutcome.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Keep tests independent, deterministic, and fast with production-like data
Applied to files:
__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
components/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)
Applied to files:
components/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Applied to files:
components/waves/outcome/WaveOutcome.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
components/waves/outcome/WaveOutcome.tsx
🧬 Code graph analysis (7)
components/waves/outcome/WaveNICOutcome.tsx (3)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-129)helpers/Helpers.ts (1)
formatNumberWithCommas(131-148)
hooks/waves/useWaveOutcomeDistributionQuery.ts (2)
generated/models/ApiWaveOutcomeDistributionItemsPage.ts (1)
ApiWaveOutcomeDistributionItemsPage(16-58)components/react-query-wrapper/utils/query-utils.ts (1)
getDefaultQueryRetry(21-34)
types/waves.types.ts (1)
generated/models/ApiWaveOutcomeDistributionItem.ts (1)
ApiWaveOutcomeDistributionItem(15-50)
components/waves/outcome/WaveManualOutcome.tsx (3)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-129)helpers/Helpers.ts (1)
formatNumberWithCommas(131-148)
__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx (1)
hooks/waves/useWaveOutcomeDistributionQuery.ts (1)
useWaveOutcomeDistributionQuery(44-120)
components/waves/outcome/WaveRepOutcome.tsx (3)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-129)helpers/Helpers.ts (1)
formatNumberWithCommas(131-148)
components/waves/outcome/WaveOutcome.tsx (6)
generated/models/ApiWaveOutcome.ts (1)
ApiWaveOutcome(18-81)hooks/waves/useWaveOutcomeDistributionQuery.ts (1)
useWaveOutcomeDistributionQuery(44-120)types/waves.types.ts (1)
WaveOutcomeDistributionState(120-129)components/waves/outcome/WaveRepOutcome.tsx (1)
WaveRepOutcome(18-186)components/waves/outcome/WaveNICOutcome.tsx (1)
WaveNICOutcome(18-167)components/waves/outcome/WaveManualOutcome.tsx (1)
WaveManualOutcome(18-175)
⏰ 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 (19)
components/waves/outcome/WaveOutcome.tsx (2)
23-58: Distribution state setup is well-structured.The distribution query integration is correct. The child components (
WaveRepOutcome,WaveNICOutcome,WaveManualOutcome) properly handleisLoading,isError, anderrorMessagestates internally, so handling them at this level would be redundant. TheuseMemodependency array correctly includes all referenced values.
72-82: Distribution props correctly passed to all outcome variants.The component map properly provides
distributionStateto each child component, enabling consistent distribution-driven rendering across all outcome types.hooks/waves/useWaveOutcomeDistributionQuery.ts (3)
51-56: Input normalization handles edge cases well.The normalization logic correctly handles
null,undefined, empty strings, and0asoutcomeIndex. ConvertingoutcomeIndexto string before trimming ensures numeric indices like0are treated as valid (non-empty"0").
80-102: Infinite query configuration is well-implemented.The query correctly uses
keepPreviousDatafor smooth pagination UX, applies retry logic viagetDefaultQueryRetry(), and properly determines next page availability viagetNextPageParam. The endpoint construction and parameter passing are correct.
104-119: Derived state and return value are correctly structured.The
itemsflattening usesuseMemoappropriately. ReadingtotalCountfrom the first page is the standard pattern for paginated APIs where the count is consistent across pages.components/waves/outcome/WaveRepOutcome.tsx (3)
24-57: Distribution state destructuring and pagination logic are correct.The logic for
visibleItems,remainingCount, andshouldShowMorecorrectly handles the interplay between local state (showAll) and server-side pagination (hasNextPage). TheonViewMorefunction appropriately toggles local visibility and fetches more data when available.
150-166: Loading, error, and empty states are handled appropriately.The conditional rendering correctly prioritizes loading and error states before showing the empty message. The error display includes a fallback message when
errorMessageis undefined.
168-179: Pagination button correctly handles fetching state.The button disables during
isFetchingNextPageand shows appropriate loading feedback. The remaining count display is informative.components/waves/outcome/WaveManualOutcome.tsx (2)
119-137: Verify theitemLabeldisplay logic for manual outcomes.The condition
item.amount === 0 ? "-" : item.description ?? ""shows a dash when amount is exactly0, otherwise shows the description. This differs from the previous review's suggestion to always show the description. If a manual outcome intentionally hasamount: 0to indicate "no reward" while still having a meaningful description, this would hide that description.Confirm this is the intended UX—should items with
amount === 0display "-" or should they show their description regardless?
139-155: Loading, error, and empty states are consistent with other outcome components.The implementation matches the pattern used in
WaveRepOutcome, maintaining consistency across outcome types.__tests__/hooks/waves/useWaveOutcomeDistributionQuery.test.tsx (1)
28-92: Test coverage for key edge cases is good.The tests correctly verify that:
outcomeIndex: nullresults inenabled: falsewith empty string in queryKeyoutcomeIndex: 0(falsy but valid) results inenabled: truewith"0"in queryKeyoutcomeIndex: "1"(string) works correctlyThis validates the critical normalization logic that distinguishes between null/undefined and valid falsy values like
0.__tests__/components/waves/outcome/WaveRepOutcome.test.tsx (2)
21-32: LGTM! Well-structured distribution mock.The distribution mock properly implements the WaveOutcomeDistributionState interface with all required fields and a mocked fetchNextPage function.
46-60: LGTM! Comprehensive loading state test.The test properly validates that the "View more" button shows loading state (disabled with "loading..." text) while fetching the next page, and that the remaining count is still displayed.
types/waves.types.ts (1)
120-129: LGTM! Well-designed distribution state interface.The WaveOutcomeDistributionState interface comprehensively covers pagination state, loading/error states, and data items with proper readonly fields following the coding guidelines.
components/waves/outcome/WaveNICOutcome.tsx (5)
3-14: LGTM! Proper imports and props structure.The component correctly uses direct named imports for React hooks and properly defines readonly props following the coding guidelines.
18-40: LGTM! Sound pagination logic.The derived state logic correctly handles visible items, remaining count, and determines when to show the "View more" button based on both local items and server-side pagination state.
42-49: LGTM! Correct pagination trigger.The onViewMore handler properly coordinates local state expansion with server-side pagination, preventing duplicate fetch requests.
70-77: LGTM! Clean loading state.The skeleton loader provides good visual feedback during initial load with appropriate pluralization logic.
117-148: LGTM! Comprehensive state handling.The component properly renders distribution items using stable keys (item.index) and handles all states including loading, error, and empty scenarios with clear user feedback.


Summary by CodeRabbit
New Features
Refactor
UI
Tests
✏️ Tip: You can customize this high-level summary in your review settings.