Conversation
WalkthroughAdded two new credit-type enum values and consolidated human-readable voting labels; replaced raw credit-type strings with label lookups across many wave components. Refactored voting inputs/slider/stats to use a Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas needing extra attention:
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: 4
🧹 Nitpick comments (2)
helpers/waves/waves.constants.ts (1)
15-25: Voting labels and stats labels look correct and aligned with ApiWaveCreditType.All credit types (including XTDH and TDH_PLUS_XTDH) are covered, and labels are consistent. If you want slightly stronger typing for the stats keys, you can add
as const:export const WAVE_VOTE_STATS_LABELS = { YOUR_VOTES: "Your votes", TOTAL: "Total", } as const;components/waves/drop/SingleWaveDropVoteInput.tsx (1)
148-177: Minor UX and style notes: quick percentages and labels are solid, but remove JSX comments and rely on labels from constants.
getQuickPercentageButtonClassand the quick-percentage arrays look fine and correctly derive selection/negative state.- Both MINI and NORMAL inputs now consistently display
{WAVE_VOTING_LABELS[creditType]}, which keeps voting units in sync across the UI.Two small cleanups to align with repo guidelines:
Remove JSX comments in TSX
- Lines like
{/* Input and buttons on one row */}and the comments around quick-percentage sections violate the “no comments in code” rule.- You can safely delete these without impacting readability, since the JSX structure is self-explanatory.
Simplify type usage for
voteValue
- Since
voteValueis alreadynumber | string, you can keep usingNumber(voteValue)ingetQuickPercentageButtonClassand rely on clamping logic you already have; that part is fine as-is.Example for comment removal:
- <div className="tw-flex tw-flex-col"> - {/* Input and buttons on one row */} + <div className="tw-flex tw-flex-col"> @@ - {/* Quick percentage buttons below */} <div className="tw-mt-1.5 tw-flex tw-gap-1 tw-overflow-x-auto tw-scrollbar-thin tw-scrollbar-thumb-iron-500 tw-scrollbar-track-iron-800 hover:tw-scrollbar-thumb-iron-300"> - {/* Mobile percentages */} <div className="sm:tw-hidden tw-flex tw-gap-1"> @@ - {/* Full percentages for sm and above */} <div className="tw-hidden sm:tw-flex tw-gap-1">Also applies to: 199-305
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
generated/models/ApiWaveCreditType.tsis excluded by!**/generated/**
📒 Files selected for processing (19)
components/waves/create-wave/voting/CreateWaveVoting.tsx(2 hunks)components/waves/drop/SingleWaveDropLog.tsx(5 hunks)components/waves/drop/SingleWaveDropVoteContent.tsx(3 hunks)components/waves/drop/SingleWaveDropVoteInput.tsx(2 hunks)components/waves/drop/SingleWaveDropVoteSlider.tsx(4 hunks)components/waves/drop/SingleWaveDropVoteStats.tsx(2 hunks)components/waves/drop/SingleWaveDropVoter.tsx(3 hunks)components/waves/drop/SingleWaveDropVotes.tsx(5 hunks)components/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsx(2 hunks)components/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsx(4 hunks)components/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsx(2 hunks)components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx(4 hunks)components/waves/specs/WaveNotificationSettings.tsx(0 hunks)components/waves/specs/WaveRating.tsx(1 hunks)components/waves/specs/WaveRatingRep.tsx(0 hunks)components/waves/specs/WaveSpecs.tsx(1 hunks)helpers/waves/create-wave.validation.ts(2 hunks)helpers/waves/waves.constants.ts(1 hunks)openapi.yaml(1 hunks)
💤 Files with no reviewable changes (2)
- components/waves/specs/WaveNotificationSettings.tsx
- components/waves/specs/WaveRatingRep.tsx
🧰 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/drop/SingleWaveDropVotes.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsxhelpers/waves/create-wave.validation.tscomponents/waves/specs/WaveRating.tsxcomponents/waves/specs/WaveSpecs.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsxhelpers/waves/waves.constants.tscomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.tsxcomponents/waves/create-wave/voting/CreateWaveVoting.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/drop/SingleWaveDropVoteStats.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drop/SingleWaveDropLog.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/drop/SingleWaveDropVotes.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsxcomponents/waves/specs/WaveRating.tsxcomponents/waves/specs/WaveSpecs.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.tsxcomponents/waves/create-wave/voting/CreateWaveVoting.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/drop/SingleWaveDropVoteStats.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drop/SingleWaveDropLog.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/drop/SingleWaveDropVotes.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsxhelpers/waves/create-wave.validation.tscomponents/waves/specs/WaveRating.tsxcomponents/waves/specs/WaveSpecs.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsxhelpers/waves/waves.constants.tscomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.tsxcomponents/waves/create-wave/voting/CreateWaveVoting.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/drop/SingleWaveDropVoteStats.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drop/SingleWaveDropLog.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/drop/SingleWaveDropVotes.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsxhelpers/waves/create-wave.validation.tscomponents/waves/specs/WaveRating.tsxcomponents/waves/specs/WaveSpecs.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsxhelpers/waves/waves.constants.tscomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.tsxcomponents/waves/create-wave/voting/CreateWaveVoting.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/drop/SingleWaveDropVoteStats.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drop/SingleWaveDropLog.tsx
🧠 Learnings (10)
📚 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/drop/SingleWaveDropVotes.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: Move data fetching from client-side Effects to Server Components for reads; use Server Functions / Server Actions (`'use server'`) for mutations
Applied to files:
components/waves/drop/SingleWaveDropVotes.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: Prefer Server Components over Client Components where possible; data reads should use Server Components with inline fetches; mutations should use Server Functions / Server Actions (`'use server'`); avoid client Effects for data fetching unless truly needed
Applied to files:
components/waves/drop/SingleWaveDropVotes.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/specs/WaveRating.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/specs/WaveRating.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:
components/waves/specs/WaveSpecs.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/drop/SingleWaveDropVoteContent.tsxcomponents/waves/drop/SingleWaveDropVoteInput.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/drop/SingleWaveDropLog.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/drop/SingleWaveDropLog.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/drop/SingleWaveDropLog.tsx
🧬 Code graph analysis (9)
components/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsx (1)
helpers/waves/waves.constants.ts (2)
WAVE_VOTE_STATS_LABELS(15-18)WAVE_VOTING_LABELS(20-25)
components/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx (5)
components/auth/SeizeConnectContext.tsx (1)
useSeizeConnectContext(618-626)components/auth/Auth.tsx (1)
useAuth(95-97)hooks/useIdentity.ts (1)
useIdentity(18-34)helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsx (1)
helpers/waves/waves.constants.ts (2)
WAVE_VOTE_STATS_LABELS(15-18)WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropVoteSlider.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/create-wave/voting/CreateWaveVoting.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropVoter.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropVoteInput.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropLog.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (14)
components/waves/drop/SingleWaveDropLog.tsx (1)
9-9: LGTM! Label centralization improves consistency.The refactor to use
WAVE_VOTING_LABELS[creditType]ensures consistent display of voting credit types across the UI.Also applies to: 115-115, 142-142
components/waves/drop/SingleWaveDropVoter.tsx (1)
7-7: LGTM! Consistent label usage.Aligns with the centralized labeling approach used throughout the PR.
Also applies to: 93-93
components/waves/drop/SingleWaveDropVoteSlider.tsx (2)
26-30: LGTM! Interface correctly reflects implementation.The
positionfield is used incalculatePresetMarksfunction (lines 107, 120, 131, 141), so adding it to the interface properly types the existing usage.
10-10: LGTM! Consistent label usage.Aligns with the centralized labeling approach used throughout the PR.
Also applies to: 302-302
components/waves/specs/WaveRating.tsx (1)
7-8: LGTM! Credit type mappings extended correctly.The new mappings for
XtdhandTdhPlusXtdhalign with the extendedApiWaveCreditTypeenum and match the labels used inWAVE_VOTING_LABELSconstant.components/waves/drop/SingleWaveDropVoteStats.tsx (1)
3-6: LGTM! Comprehensive label centralization.Replacing hardcoded strings with
WAVE_VOTE_STATS_LABELSandWAVE_VOTING_LABELSimproves maintainability and prepares the codebase for potential internationalization.Also applies to: 23-25, 30-30, 37-37
helpers/waves/create-wave.validation.ts (1)
178-199: LGTM! Validation correctly extends to all non-Rep credit types.The updated logic
voting.type !== ApiWaveCreditType.Repproperly restricts category and profileId for all non-Rep credit types (TDH, XTDH, TDH+XTDH), which is correct since only Rep voting should have these attributes.Note: The error constants still reference "TDH_VOTING" (lines 181, 184) but now apply to all non-Rep types. While the logic is correct, consider updating the error constant names in a future refactor for clarity.
components/waves/create-wave/voting/CreateWaveVoting.tsx (2)
14-19: LGTM! Explicit ordering ensures deterministic rendering.The
VOTING_TYPES_ORDERconstant replaces the non-deterministicObject.values(ApiWaveCreditType)iteration, ensuring voting type options always render in the intended order: TDH, XTDH, TDH + XTDH, Rep.Also applies to: 65-67
73-73: Note: Label prefix added, not removed.The label now includes the "By " prefix (e.g., "By TDH", "By Rep"). Note that this contradicts the AI summary which mentions "removing 'By' prefixes" - the code actually adds them.
components/waves/drops/participation/ratings/ParticipationDropRatingsVoterSection.tsx (1)
10-15: Centralizing tooltip unit labels viaWAVE_VOTING_LABELSis correct.Using
WAVE_VOTING_LABELS[drop.wave.voting_credit_type]in the tooltip keeps the displayed unit consistent with the rest of the waves UI and automatically supports the new XTDH and TDH_PLUS_XTDH values.Also applies to: 56-59
openapi.yaml (1)
6994-7002: ExtendingApiWaveCreditTypewithXTDHandTDH_PLUS_XTDHis consistent and safe.The new enum values integrate cleanly with existing references (e.g.,
ApiWaveMin.voting_credit_typeandApiWaveVotingConfig.credit_type) and match the frontend label mappings, so generated clients will be able to use them without additional schema changes.components/waves/specs/WaveSpecs.tsx (1)
37-37: LGTM!The label update from "Rating" to "Voting" aligns with the PR's objective to refactor voting-related terminology across wave components.
components/waves/drops/participation/ratings/ParticipationDropRatingsUserSection.tsx (1)
3-6: LGTM!The refactoring consolidates hardcoded UI strings into shared constants (WAVE_VOTE_STATS_LABELS and WAVE_VOTING_LABELS), improving maintainability and consistency across the codebase.
Also applies to: 30-30, 40-40
components/waves/drops/participation/ratings/ParticipationDropRatingsTotalSection.tsx (1)
6-9: LGTM. The refactoring correctly usesWAVE_VOTE_STATS_LABELSandWAVE_VOTING_LABELSwith the properApiWaveCreditTypedefinitions.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (11)
components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx (2)
61-61: Consider extracting the repeated label expression to a variable.The expression
WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType]is used three times (lines 61, 102, 118). Extracting it to a constant improves readability and ensures consistency.export const WaveLeaderboardDropRaters: React.FC< WaveLeaderboardDropRatersProps > = ({ drop }) => { const votersCountLabel = drop.raters_count === 1 ? "voter" : "voters"; const userVote = drop.context_profile_context?.rating ?? 0; const isNegativeVote = userVote < 0; + const votingLabel = WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType];Then use
votingLabelat lines 61, 102, and 118.
76-83: Consider usingnext/imagefor the avatar.The
<img>element should be replaced with<Image />fromnext/imageper coding guidelines. While this isn't part of the current changes, it's worth addressing.+import Image from "next/image";- <img - src={getScaledImageUri( - voter.profile.pfp, - ImageScale.W_AUTO_H_50 - )} - alt={`${voter.profile.handle}'s Profile`} - className="tw-h-5 tw-w-5 tw-rounded-md tw-ring-1 tw-ring-black tw-bg-iron-800 tw-object-contain" - /> + <Image + src={getScaledImageUri( + voter.profile.pfp, + ImageScale.W_AUTO_H_50 + )} + alt={`${voter.profile.handle}'s Profile`} + width={20} + height={20} + className="tw-h-5 tw-w-5 tw-rounded-md tw-ring-1 tw-ring-black tw-bg-iron-800 tw-object-contain" + />components/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsx (1)
188-191: Consider adding a safe fallback for unmapped credit typesUsing
WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType]makes the UI friendlier, assuming the map is exhaustive for allApiWaveCreditTypevalues. If there is any chance of a new/unknownvoting_credit_typecoming from the API, this could renderundefinedin the UI.You might want to precompute the label with a fallback to the raw value (or a generic label), e.g. in the render body:
const votingCreditType = drop.wave.voting_credit_type as ApiWaveCreditType; const votingCreditLabel = WAVE_VOTING_LABELS[votingCreditType] ?? votingCreditType;and then use
votingCreditLabelin JSX.components/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsx (2)
4-5: Consistent use of WAVE_VOTING_LABELS for credit type displayUsing
WAVE_VOTING_LABELS[winner.drop.wave.voting_credit_type as ApiWaveCreditType]keeps this header aligned with the rest of the waves UI and avoids leaking raw enum values in the UI. Looks good.To make this a bit more defensive against unexpected/unknown values coming from the API, you could optionally add a fallback (e.g., to the raw
voting_credit_typeor a generic label):{WAVE_VOTING_LABELS[winner.drop.wave.voting_credit_type as ApiWaveCreditType] ?? winner.drop.wave.voting_credit_type}Also applies to: 68-69
7-9: Mark props fields asreadonlyto match guidelinesThe props interface currently has a mutable
winnerfield. To align with the guideline of making React props readonly, consider:interface WaveWinnersDropHeaderVotersProps { readonly winner: ApiWaveDecisionWinner; }components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx (1)
7-7: Credit-type label mapping change looks correct and type‑safeIndexing
WAVE_VOTING_LABELSwithcreditType: ApiWaveCreditTypeis aligned with the shared constants and keeps the UI text consistent across the app (including new XTDH / TDH+XTDH types). No issues with correctness or typing here; this is a clean UX improvement over showing the raw enum value.As a separate, non-blocking note: this TSX file still uses plain
<img>tags and an inline<svg>icon; per project guidelines and Next.js ESLint rules, consider gradually refactoring these tonext/imageand FontAwesome icons in a follow-up to keep the file consistent. Based on learnings, this is a recommended refactor rather than a blocker.Also applies to: 48-48, 80-81
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx (1)
7-7: Consistent, human‑readable vote label usage; implementation is soundUsing
WAVE_VOTING_LABELS[creditType]forlog.contents.newVoteis consistent with the shared wave voting constants and keeps activity log entries in sync with the rest of the UI. GivencreditType: ApiWaveCreditTypeandRecord<ApiWaveCreditType, string>, this is type‑safe and should handle the newly added credit types without further changes. The className conditional for green/red remains correct.Similar to the other sidebar component, this file still uses raw
<img>tags and an inline<svg>icon. When convenient, consider refactoring tonext/imageand FontAwesome icons to better align with the project’s Next.js and UI guidelines. Based on learnings, this is a non‑blocking, recommended cleanup.Also applies to: 85-89
components/waves/winners/DefaultWaveWinnerDropSmall.tsx (1)
14-15: Consistent voting label mapping; consider extracting a localvotingLabelconstantUsing
WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType]keeps this component aligned with the shared label map and avoids hard‑coded strings, which is good.To avoid repeating the same cast and lookup twice, you could compute it once near the top of the component body:
- const handleDropClick = useCallback(() => { + const votingLabel = + WAVE_VOTING_LABELS[ + drop.wave.voting_credit_type as ApiWaveCreditType + ]; + + const handleDropClick = useCallback(() => { onDropClick(drop); }, [drop, onDropClick]);and then use
{votingLabel}in both places. This keeps things a bit cleaner and centralizes the mapping.Also applies to: 88-89, 107-108
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
16-17: Good use of shared voting labels; you can DRY up the repeated lookupSwitching both spots to
WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType]correctly reuses the shared label map and keeps display text in sync with other wave views.As in the default winner component, you could compute this once:
- const handleDropClick = useCallback(() => { + const votingLabel = + WAVE_VOTING_LABELS[ + drop.wave.voting_credit_type as ApiWaveCreditType + ]; + + const handleDropClick = useCallback(() => { onDropClick(drop); }, [drop, onDropClick]);and then render
{votingLabel}in both label positions to avoid repeating the cast and lookup.Also applies to: 90-91, 109-110
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (2)
20-21: Centralized voting label imports are consistent with constantsImporting
WAVE_VOTING_LABELSandApiWaveCreditTypematches the shared constants pattern and keeps labels in sync across the app. You might optionally markApiWaveCreditTypeas a type-only import to avoid a runtime binding, but it’s not required.
67-67: Voting credit label lookup with safe fallbackUsing
WAVE_VOTING_LABELS[winner.drop.wave.voting_credit_type as ApiWaveCreditType] || "votes"correctly routes through the shared mapping while preserving the previous"votes"fallback when the mapping is missing. If you ever allow empty-string labels, consider?? "votes"instead of||, but the current code is fine given the existing labels.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
components/drops/view/DropsList.tsx(2 hunks)components/waves/drops/wave-drops-all/index.tsx(1 hunks)components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx(4 hunks)components/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsx(2 hunks)components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx(2 hunks)components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx(3 hunks)components/waves/winners/DefaultWaveWinnerDropSmall.tsx(3 hunks)components/waves/winners/MemesWaveWinnerDropSmall.tsx(3 hunks)components/waves/winners/drops/DefaultWaveWinnerDrop.tsx(4 hunks)components/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsx(2 hunks)components/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsx(2 hunks)components/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsx(2 hunks)components/waves/winners/podium/WavePodiumItem.tsx(5 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/waves/drops/wave-drops-all/index.tsx
🧰 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/drops/view/DropsList.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/winners/DefaultWaveWinnerDropSmall.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.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/drops/view/DropsList.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/winners/DefaultWaveWinnerDropSmall.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.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/drops/view/DropsList.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/winners/DefaultWaveWinnerDropSmall.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.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/drops/view/DropsList.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/winners/DefaultWaveWinnerDropSmall.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsxcomponents/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.tsx
🧠 Learnings (2)
📚 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} : Remove unnecessary Effects; if Effect only derives state, compute during render instead
Applied to files:
components/drops/view/DropsList.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/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx
🧬 Code graph analysis (9)
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/winners/DefaultWaveWinnerDropSmall.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx (2)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)
components/waves/winners/podium/WavePodiumItem.tsx (4)
helpers/waves/drop.helpers.ts (1)
ExtendedDrop(16-20)components/utils/tooltip/UserProfileTooltipWrapper.tsx (1)
UserProfileTooltipWrapper(12-34)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)components/waves/winners/podium/WavePodiumItemContentOutcomes.tsx (1)
WavePodiumItemContentOutcomes(15-253)
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
⏰ 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 (12)
components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx (2)
11-12: LGTM!The imports for
WAVE_VOTING_LABELSandApiWaveCreditTypeare correctly added to support the label mapping refactor.
18-124: LGTM!The refactor to use
WAVE_VOTING_LABELSinstead of rawvoting_credit_typevalues is consistent and aligns with the centralized label constants pattern introduced in this PR. The component logic remains correct.components/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsx (1)
17-18: Imports for voting labels and credit type look correctImporting
WAVE_VOTING_LABELSandApiWaveCreditTypehere aligns with the summarized PR changes and keeps the label mapping local to this component. No issues from a typing or structure standpoint.components/drops/view/DropsList.tsx (1)
42-43: Whitespace-only change is fineSpacing/blank line adjustments here are non-functional and consistent with surrounding style.
components/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsx (1)
3-4: Label mapping is consistent with shared wave voting labelsSwitching to
WAVE_VOTING_LABELS[winner.drop.wave.voting_credit_type as ApiWaveCreditType]keeps this header consistent with the rest of the wave UI and with the centralized enum→label mapping. The change is clear and type‑safe given the sharedApiWaveCreditTypeenum.Also applies to: 39-40
components/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsx (1)
10-11: Tooltip voting label matches shared mapping and other winner viewsUsing
WAVE_VOTING_LABELS[winner.drop.wave.voting_credit_type as ApiWaveCreditType]in the tooltip aligns this display with the rest of the wave components and the centralized constants. The change is small, self‑contained, and improves consistency of what users see for voting credits.Also applies to: 52-53
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (2)
6-9: Drop helper import usage looks correctBringing in both
ExtendedDropandconvertApiDropToExtendedDropkeeps the prop type and conversion helper aligned; no issues here.
113-116: ClassName conditional formatting remains validThe multi-line template for the positive/negative vote color is syntactically correct and preserves the intended Tailwind classes; no functional change beyond readability.
components/waves/winners/podium/WavePodiumItem.tsx (4)
11-12: LGTM!The new imports for
WAVE_VOTING_LABELSandApiWaveCreditTypeare correctly added and properly used to replace hardcoded credit type strings with centralized constants.
236-238: Verify type safety of the credit type lookup.The type assertion
as ApiWaveCreditTypebypasses TypeScript's type checking. Ifdrop.wave.voting_credit_typecontains an unexpected value, the lookup will returnundefined.Consider adding a fallback or validating the type:
- {WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType]} + {WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType] ?? drop.wave.voting_credit_type}
201-226: Good implementation of the user profile tooltip.The
UserProfileTooltipWrapperis correctly applied with proper fallback (drop.author.handle ?? drop.author.id). Click propagation is properly stopped to prevent triggering the parent'sonDropClick.
228-254: LGTM!Good refactoring to use centralized
WAVE_VOTING_LABELSinstead of hardcoded strings. The conditional color for negative ratings, proper pluralization of "voter"/"voters", and click propagation handling are all correctly implemented.
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 (1)
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
125-133: Replace raw<img>withnext/imageImage componentThe avatar currently uses a plain
<img>, which conflicts with the project guideline to usenext/imageand aligns with@next/next/no-img-elementrule recommendations. You can keep the same URI helper and Tailwind classes while migrating toImage:+import Image from "next/image"; @@ - {drop.author.pfp ? ( - <img - src={getScaledImageUri( - drop.author.pfp, - ImageScale.W_AUTO_H_50 - )} - alt={`${drop.author.handle}'s profile`} - className="tw-size-7 tw-rounded-lg tw-ring-1 tw-ring-white/10 tw-object-cover" - /> + {drop.author.pfp ? ( + <Image + src={getScaledImageUri( + drop.author.pfp, + ImageScale.W_AUTO_H_50 + )} + alt={`${drop.author.handle}'s profile`} + width={28} + height={28} + className="tw-size-7 tw-rounded-lg tw-ring-1 tw-ring-white/10 tw-object-cover" + /> + ) : (Width/height
28matchestw-size-7sizing. Note:DefaultWaveWinnerDropSmall.tsxhas the identical pattern and should be fixed similarly.
🧹 Nitpick comments (11)
components/waves/drop/SingleWaveDropVoter.tsx (1)
45-46: Replace<img>with<Image />fromnext/image.Per coding guidelines, use
next/imagefor images to satisfy the@next/next/no-img-elementESLint rule.+import Image from "next/image"; ... {voter.voter.pfp ? ( - <img src={voter.voter.pfp} alt="" className={pfpClasses} /> + <Image src={voter.voter.pfp} alt="" width={24} height={24} className={pfpClasses} /> ) : (components/waves/drop/SingleWaveDropVoteSlider.tsx (3)
19-21: Remove placeholder comment.Lines 19-21 appear to be leftover placeholder text that should be removed.
-// ... existing code ... - -
23-27: Remove unusedPresetMarkinterface.Per the AI summary, preset marks logic was removed, but this interface remains as dead code.
-interface PresetMark { - percentage: number; - label: string; - position: number; -}
134-136: Missing dependency in useEffect.The
xmotion value should be included in the dependency array to satisfyreact-hooks/exhaustive-deps. Sincexis a stable ref fromuseMotionValue, adding it won't cause re-runs but will satisfy the linter.useEffect(() => { x.set(currentPercentage); - }, [currentPercentage]); + }, [currentPercentage, x]);components/waves/drop/SingleWaveDropVoteInput.tsx (2)
27-32: Hoist static arrays outside the component.
memeticValues,quickPercentages, andmobileQuickPercentagesare constant arrays that don't depend on props or state. Defining them inside the component causes unnecessary recreation on every render.+const MEMETIC_VALUES: number[] = [ + -69420, -42069, -6529, -420, -69, 69, 420, 6529, 42069, 69420, +]; +const QUICK_PERCENTAGES = [-100, -75, -50, -25, 25, 50, 75, 100]; +const MOBILE_QUICK_PERCENTAGES = [-75, -50, -25, 25, 50, 75]; + export const SingleWaveDropVoteInput: React.FC< SingleWaveDropVoteInputProps > = ({ ... }) => { - const memeticValues: number[] = [ - -69420, -42069, -6529, -420, -69, 69, 420, 6529, 42069, 69420, - ]; - - const quickPercentages = [-100, -75, -50, -25, 25, 50, 75, 100]; - const mobileQuickPercentages = [-75, -50, -25, 25, 50, 75];Then update references from
memeticValuestoMEMETIC_VALUES,quickPercentagestoQUICK_PERCENTAGES, andmobileQuickPercentagestoMOBILE_QUICK_PERCENTAGES.
237-274: Consider using FontAwesome for consistency.Per coding guidelines, FontAwesome should be used for icons in React components. The inline SVGs work but differ from the pattern used elsewhere (e.g.,
faExchangeinSingleWaveDropVoteContent.tsx).import { faArrowUp, faArrowDown } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; // Then replace SVGs with: <FontAwesomeIcon icon={faArrowUp} className="tw-w-4 tw-h-4 tw-flex-shrink-0" /> <FontAwesomeIcon icon={faArrowDown} className="tw-w-4 tw-h-4 tw-flex-shrink-0" />components/waves/winners/podium/WavePodiumItem.tsx (1)
29-29: Improved but consider conditional pattern for maximum compatibility.The
hoverTextColorproperties now contain complete static variant strings (e.g.,"desktop-hover:hover:tw-text-[#fbbf24]"), which should be detected by Tailwind's scanner since they exist as literals in the source. This is a significant improvement over runtime variant construction.However, the past review recommended using conditional helper functions that return complete static strings (similar to
DefaultWaveLeaderboardDrop.tsx) for maximum compatibility. The current interpolation pattern${styles.hoverTextColor}should work, but the conditional approach eliminates any potential edge cases with Tailwind's scanner.If you prefer to align with the recommended pattern:
const getHoverColorClass = (position: "first" | "second" | "third") => { const colorMap = { first: "desktop-hover:hover:tw-text-[#fbbf24]", second: "desktop-hover:hover:tw-text-[#94a3b8]", third: "desktop-hover:hover:tw-text-[#CD7F32]", }; return colorMap[position]; };Then use:
className={... ${getHoverColorClass(position)} ...}Also applies to: 52-52, 75-75, 210-210, 212-212
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
16-17: Guard voting label lookup with a fallback to preserve robustnessDeriving
votingLabelfromWAVE_VOTING_LABELSis the right direction for consistency, but the hard cast toApiWaveCreditTypemeans any unexpected/legacyvoting_credit_typewill yieldundefinedand render as empty text where we previously showed the raw value.To keep behavior resilient while still using the label map, consider a nullish-coalescing fallback:
-import { WAVE_VOTING_LABELS } from "@/helpers/waves/waves.constants"; -import { ApiWaveCreditType } from "@/generated/models/ApiWaveCreditType"; +import { WAVE_VOTING_LABELS } from "@/helpers/waves/waves.constants"; +import { ApiWaveCreditType } from "@/generated/models/ApiWaveCreditType"; … - const votingLabel = WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType]; + const votingLabel = + WAVE_VOTING_LABELS[drop.wave.voting_credit_type as ApiWaveCreditType] ?? + drop.wave.voting_credit_type ?? + "";This keeps the new labeling while ensuring we still show something sensible in both the main rating line and the “You” line if an unknown credit type appears. Please double-check that
drop.wave.voting_credit_type’s runtime values always matchApiWaveCreditTypeor that this fallback matches your domain expectations.Also applies to: 58-59, 92-93, 110-112
components/waves/winners/drops/MemesWaveWinnerDrop.tsx (1)
28-28: Centralized vote stat labels look good; consider mappingcreditTypefor consistencyUsing
WAVE_VOTE_STATS_LABELS.TOTALandWAVE_VOTE_STATS_LABELS.YOUR_VOTESstandardizes the copy and aligns this drop view with other vote UIs. One optional improvement: consider deriving a human‑readable label viaWAVE_VOTING_LABELS(as in other components) instead of rendering the rawcreditTypevalue, so the unit text stays fully consistent across the app.Also applies to: 176-183, 232-239
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx (1)
5-5: Avatarnext/imageusage and voting label mapping are on pointSwitching the voter avatar to
next/imagewith explicit dimensions and handle‑basedaltis solid, and usingWAVE_VOTING_LABELS[creditType]keeps the unit text aligned with the global wave voting labels. If you want full consistency with other components later, you could also centralize the trailing"total"string via the same stats label constants you’re using elsewhere, but this isn’t blocking.Also applies to: 8-8, 32-38, 83-84
components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx (1)
2-2: Tooltip identity/avatars and voting labels are wired correctlyResolving
pfpviauseSeizeConnectContext/useAuth/useIdentityand rendering it withnext/imagein the “Your Voting Power” header personalizes the tooltip without changing behavior, and usingWAVE_VOTING_LABELS[drop.wave.voting_credit_type]for both the Voting Range and Voted lines keeps the units in sync with the rest of the waves voting UI. If you touch this again, you could optionally cache that label in a localconstto avoid repeating the lookup, but it’s not required.Also applies to: 8-8, 10-12, 26-37, 82-98, 107-107, 111-115
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
components/drops/view/DropsList.tsx(3 hunks)components/waves/drop/SingleWaveDropVoteContent.tsx(9 hunks)components/waves/drop/SingleWaveDropVoteInput.tsx(2 hunks)components/waves/drop/SingleWaveDropVoteSlider.tsx(7 hunks)components/waves/drop/SingleWaveDropVoteStats.tsx(1 hunks)components/waves/drop/SingleWaveDropVoter.tsx(3 hunks)components/waves/drop/SingleWaveDropVotes.tsx(5 hunks)components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx(4 hunks)components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx(6 hunks)components/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsx(3 hunks)components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx(5 hunks)components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx(4 hunks)components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.tsx(2 hunks)components/waves/winners/DefaultWaveWinnerDropSmall.tsx(4 hunks)components/waves/winners/MemesWaveWinnerDropSmall.tsx(4 hunks)components/waves/winners/drops/DefaultWaveWinnerDrop.tsx(4 hunks)components/waves/winners/drops/MemesWaveWinnerDrop.tsx(3 hunks)components/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsx(2 hunks)components/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsx(2 hunks)components/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsx(2 hunks)components/waves/winners/podium/WavePodiumItem.tsx(9 hunks)helpers/waves/create-wave.validation.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
- components/waves/winners/drops/header/WaveWinnersDropHeaderTotalVotes.tsx
- components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx
- components/waves/winners/drops/header/WaveWinnersDropHeaderVoter.tsx
- components/waves/drop/SingleWaveDropVotes.tsx
- components/waves/drop/SingleWaveDropVoteStats.tsx
- components/drops/view/DropsList.tsx
- components/waves/winners/DefaultWaveWinnerDropSmall.tsx
- helpers/waves/create-wave.validation.ts
- components/waves/winners/drops/header/WaveWinnersDropHeaderVoters.tsx
🧰 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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsxcomponents/waves/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/drop/SingleWaveDropVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.tsxcomponents/waves/drop/SingleWaveDropVoteContent.tsxcomponents/waves/winners/drops/DefaultWaveWinnerDrop.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.tsx
🧠 Learnings (12)
📚 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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsxcomponents/waves/drop/SingleWaveDropVoteContent.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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.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/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.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/winners/podium/WavePodiumItem.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.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/winners/podium/WavePodiumItem.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 TailwindCSS for styling in React components
Applied to files:
components/waves/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.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 FontAwesome for icons in React components
Applied to files:
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsxcomponents/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.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/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.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:
components/waves/drop/SingleWaveDropVoteInput.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:
components/waves/drop/SingleWaveDropVoteContent.tsx
🧬 Code graph analysis (8)
components/waves/winners/drops/MemesWaveWinnerDrop.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTE_STATS_LABELS(15-18)
components/waves/drop/SingleWaveDropVoter.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (2)
WAVE_VOTING_LABELS(20-25)WAVE_VOTE_STATS_LABELS(15-18)
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx (2)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropVoteContent.tsx (2)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)components/waves/drop/SingleWaveDropVoteStats.tsx (1)
SingleWaveDropVoteStats(12-41)
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (1)
helpers/waves/waves.constants.ts (2)
WAVE_VOTING_LABELS(20-25)WAVE_VOTE_STATS_LABELS(15-18)
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropVoteSlider.tsx (1)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (16)
components/waves/drop/SingleWaveDropVoter.tsx (2)
7-7: LGTM - Label constants integration.The import and usage of
WAVE_VOTING_LABELSandWAVE_VOTE_STATS_LABELSaligns with the PR's goal of centralizing voting labels across the codebase.
92-94: LGTM - Proper label usage.The display text now correctly uses mapped labels (
WAVE_VOTING_LABELS[creditType]) and constants (WAVE_VOTE_STATS_LABELS.TOTAL) instead of raw enum values.components/waves/drop/SingleWaveDropVoteSlider.tsx (1)
95-103: LGTM - Label prop usage.The component correctly receives and uses the
labelprop in the tooltip display, replacing the previouscreditTypeapproach.Also applies to: 253-253
components/waves/drop/SingleWaveDropVoteContent.tsx (3)
33-35: LGTM - Defensive label computation.The fallback to
"votes"handles cases wherevoting_credit_typemight be undefined or an unexpected value, providing resilient UI behavior.
37-39: LGTM - Dependency update.The useEffect now correctly depends on
currentVoteValueto sync the local state when the prop changes.
77-85: LGTM - Consistent label prop forwarding.Both MINI and NORMAL layouts correctly pass
label={voteLabel}toSingleWaveDropVoteSlider, maintaining consistency across size variants.Also applies to: 163-170
components/waves/drop/SingleWaveDropVoteInput.tsx (3)
59-73: LGTM - Timer handling refactored correctly.The timer refs are now properly typed with
ReturnType<typeof setInterval/setTimeout> | null, theclearTimershelper properly clears both refs, and thestartPress/stopPressfunctions correctly manage theisPressedflag. The cleanup effect ensures timers are cleared on unmount. This addresses the issues from the previous review.Also applies to: 133-156
75-131: Verify memetic crossing behavior.The memetic value crossing logic now uses
isPressed.currentto determine whether to restart the interval after the 1-second pause. Please verify this provides the expected user experience where:
- Crossing a memetic value pauses at that value for 1 second
- If the user is still pressing, the interval resumes
- If the user releases during the pause, no further updates occur
182-186: LGTM - Keyboard submission support.The
handleKeyDownhandler enables form submission via Enter key, improving accessibility and UX.components/waves/winners/podium/WavePodiumItem.tsx (3)
163-173: LGTM! Image component properly implemented.The migration from
<img>to<Image>fromnext/imageis correct, with properwidthandheightprops. This addresses the previous review concern and satisfies the@next/next/no-img-elementESLint rule.
176-231: Well-structured badge and author section.The decorative position badge with SVG icon and the tooltip-wrapped author link are well-implemented. Proper accessibility attributes (
aria-hidden="true") and click propagation handling (stopPropagation) are in place.
233-260: Clean implementation of rating and voters display.The use of
WAVE_VOTING_LABELSfor consistent labeling, proper singular/plural handling for voters, and appropriate click propagation management are all well-executed. The conditional color for negative ratings is a nice UX touch.components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoters.tsx (1)
7-8: Clock icon migration to FontAwesome is clean and consistentUsing
FontAwesomeIconwithfaClockin the empty-state block keeps icon usage consistent with the rest of the app and avoids inline SVG duplication; no behavioral changes introduced.Also applies to: 42-45
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (1)
20-21: Voting unit and “Your votes” labeling are correctly centralized
creditTypenow comes fromWAVE_VOTING_LABELSwith a"votes"fallback, and the “Your votes” label usesWAVE_VOTE_STATS_LABELS.YOUR_VOTES, which keeps winner drops in line with the new global voting label strategy without changing behavior.Also applies to: 67-67, 110-116
components/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsx (1)
17-18: Gallery vote labels now use shared mappings consistentlyDeriving
votingCreditLabelfromWAVE_VOTING_LABELS(with a safe fallback) and prefixing the user line withWAVE_VOTE_STATS_LABELS.YOUR_VOTESmakes the gallery item’s vote text consistent with the rest of the waves UI without altering vote logic.Also applies to: 94-96, 193-194
components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.tsx (1)
7-10: Activity log icons, avatars, and vote units are modernized correctlyReplacing the inline clock SVG with
FontAwesomeIcon, migrating both avatars tonext/imagewith fixed dimensions, and rendering vote units viaWAVE_VOTING_LABELS[creditType]cleanly align this sidebar log with the shared icon and voting label patterns, without changing the underlying vote/change semantics.Also applies to: 32-35, 54-59, 80-84, 94-99
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 (1)
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
128-136: Replace<img>avatar with Next.js<Image>to satisfy ESLint and optimize loadingThis component uses a raw
<img>for the author avatar, which violates the@next/next/no-img-elementESLint rule and misses image optimization. Replace with<Image>fromnext/image:+import Image from "next/image"; @@ - {drop.author.pfp ? ( - <img - src={getScaledImageUri( - drop.author.pfp, - ImageScale.W_AUTO_H_50 - )} - alt={`${drop.author.handle}'s profile`} - className="tw-size-7 tw-rounded-lg tw-ring-1 tw-ring-white/10 tw-object-cover" - /> + {drop.author.pfp ? ( + <Image + src={getScaledImageUri( + drop.author.pfp, + ImageScale.W_AUTO_H_50 + )} + alt={`${drop.author.handle}'s profile`} + width={28} + height={28} + className="tw-size-7 tw-rounded-lg tw-ring-1 tw-ring-white/10 tw-object-cover" + />
🧹 Nitpick comments (5)
components/waves/winners/podium/WavePodiumItem.tsx (1)
220-222: Consider removing duplicate hover class on nested element.The
hoverTextColorClassis applied to both the<Link>(line 220) and the inner<span>(line 222). Since the span inherits text color from its parent, applying it only to the Link should suffice.className={`tw-transition-all tw-no-underline tw-mb-2 tw-mt-2 sm:tw-mt-4 tw-relative tw-text-center ${hoverTextColorClass} tw-group/link`} > - <span className={`${styles.autorFontSize} tw-font-semibold tw-text-iron-200 ${hoverTextColorClass} tw-transition-colors tw-inline-flex tw-items-center`}> + <span className={`${styles.autorFontSize} tw-font-semibold tw-text-iron-200 tw-transition-colors tw-inline-flex tw-items-center`}>components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
16-17: Voting label mapping and fallbacks are sound; consider extracting a typed helperUsing
WAVE_VOTING_LABELSwith a??fallback todrop.wave.voting_credit_typeand then""is a good, robust way to keep the UI readable even for unknown or missing credit types.The only minor concern is the
as ApiWaveCreditTypeassertion ondrop.wave.voting_credit_type: if that field’s type ever drifts fromApiWaveCreditType, TypeScript will no longer protect you. To keep this pattern type‑safe and reusable across components, consider moving the logic into a helper likegetWaveVotingLabel(votingCreditType: ApiWaveCreditType | null | undefined): stringinhelpers/waves/waves.constants.tsand calling that here instead of asserting. Based on learnings, this would also help keep mapping and fallback behavior centralized.Also applies to: 58-61
components/waves/drop/SingleWaveDropVoteInput.tsx (2)
36-61: Timer refs and cleanup are structurally sound but may need a hooks-lint tweakUsing separate refs for the interval and pause timeout, plus
clearTimersandpressStartTime/isPressed, is a good, type-safe structure and should avoid the earlier mixed-timer issues.startPress/stopPresscorrectly delegate toclearTimers, and the unmountuseEffectensures timers are torn down.One thing to watch:
useEffect’s cleanup callsclearTimers, butclearTimersis not in the dependency array.react-hooks/exhaustive-depsmay flag this. A small refactor would keep ESLint happy without changing behavior:-import React, { useEffect, useRef } from "react"; +import React, { useCallback, useEffect, useRef } from "react"; - const clearTimers = () => { + const clearTimers = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } if (pauseTimeoutRef.current) { clearTimeout(pauseTimeoutRef.current); pauseTimeoutRef.current = null; } - } - }; + } + }, []); useEffect(() => { return () => { clearTimers(); }; - }, []); + }, [clearTimers]);This keeps
clearTimersstable and eliminates hook-dependency warnings.Please run ESLint with the React Hooks plugin to confirm whether it currently complains about
clearTimersin the effect dependencies.Also applies to: 149-165, 167-171
128-135: Quick-percentage helpers are coherent; consider edge-case semanticsThe quick-percentage logic is consistent between mobile and desktop (
MOBILE_QUICK_PERCENTAGESvsQUICK_PERCENTAGES), and the button styling correctly reflects the active percentage viagetQuickPercentageButtonClass.One nuance: for negative percentages, you compute:
percentage < 0 ? (Math.abs(percentage) / 100) * minValue : (percentage / 100) * maxValue;This assumes
minValueis negative when negative percentages are shown. If a future wave config ever usedminValue >= 0(e.g., only long-side voting), negative quick percentages would all map to0. If that’s possible, you may want to either hide negative quick buttons in that case or derive negative targets symmetrically from the positive side.Please confirm whether
minValueis guaranteed to be negative whenever negative quick percentages are rendered; if not, consider adjusting the mapping or conditionally hiding those buttons.Also applies to: 272-303
components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx (1)
34-37: Consider scaling the user pfp for consistency and performance.The user's profile picture (line 88) is rendered without scaling, while top voters' profile pictures use
getScaledImageUri(lines 54-57). Since both display at 16×16 pixels, applying the same scaling to the user pfp would improve consistency and performance, especially if the source image is large.Apply this diff to scale the user pfp:
const pfp = (() => { - if (activeProfileProxy) return activeProfileProxy.created_by.pfp; - return profile?.pfp ?? null; + const rawPfp = activeProfileProxy?.created_by.pfp ?? profile?.pfp ?? null; + return rawPfp ? getScaledImageUri(rawPfp, ImageScale.W_AUTO_H_50) : null; })();Also applies to: 85-95
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
components/waves/drop/SingleWaveDropVoteInput.tsx(6 hunks)components/waves/drop/SingleWaveDropVoteSlider.tsx(8 hunks)components/waves/drop/SingleWaveDropVoter.tsx(4 hunks)components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx(5 hunks)components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx(4 hunks)components/waves/winners/MemesWaveWinnerDropSmall.tsx(4 hunks)components/waves/winners/drops/MemesWaveWinnerDrop.tsx(4 hunks)components/waves/winners/podium/WavePodiumItem.tsx(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- components/waves/drop/SingleWaveDropVoter.tsx
- components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarVoter.tsx
🧰 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/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.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/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.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/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.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/winners/drops/MemesWaveWinnerDrop.tsxcomponents/waves/winners/podium/WavePodiumItem.tsxcomponents/waves/winners/MemesWaveWinnerDropSmall.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsxcomponents/waves/drop/SingleWaveDropVoteSlider.tsx
🧠 Learnings (9)
📚 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/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.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/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.tsxcomponents/waves/drop/SingleWaveDropVoteInput.tsxcomponents/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.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 TailwindCSS for styling in React components
Applied to files:
components/waves/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.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/winners/podium/WavePodiumItem.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 FontAwesome for icons in React components
Applied to files:
components/waves/drop/SingleWaveDropVoteInput.tsx
🧬 Code graph analysis (2)
components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(20-25)
components/waves/drop/SingleWaveDropVoteSlider.tsx (1)
helpers/Helpers.ts (1)
formatNumberWithCommas(103-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (18)
components/waves/winners/podium/WavePodiumItem.tsx (5)
1-12: LGTM!The imports are properly structured. The
Imagecomponent fromnext/imageaddresses the previous review feedback, andWAVE_VOTING_LABELScentralizes voting label management.
118-128: LGTM!This helper correctly addresses the dynamic Tailwind class detection issue by returning complete static class strings. The
as constassertion provides proper type safety.
173-183: LGTM!The
<Image />component usage is correct. Fetching a 56×56 source and scaling via CSS classes ensures quality across all positions while maintaining proper layout.
251-253: LGTM!Using
WAVE_VOTING_LABELS[drop.wave.voting_credit_type]centralizes the label management and aligns with the PR's objective of consistent voting labels across components.
266-268: LGTM!Event propagation is handled correctly. The
stopPropagation()calls on nested interactive elements prevent unintended triggering of the parent'sonDropClickhandler.components/waves/winners/drops/MemesWaveWinnerDrop.tsx (3)
28-32: LGTM! Imports align with centralized label refactoring.The new imports properly support the centralized voting label pattern being introduced across wave components.
66-69: No issues found. The code is correct:WAVE_VOTING_LABELSis properly typed asRecord<ApiWaveCreditType, string>and includes all four enum values (Tdh, Rep, Xtdh, TdhPlusXtdh). The fallback chain provides solid runtime safety.
189-189: WAVE_VOTE_STATS_LABELS constants are properly defined and exported. ✓The constants
TOTALandYOUR_VOTESare correctly defined inhelpers/waves/waves.constants.ts, properly imported in this file, and used correctly at lines 189 and 239.components/waves/winners/MemesWaveWinnerDropSmall.tsx (1)
95-95: Consistent use ofvotingLabelimproves UX and avoids leaking raw enum valuesSwapping the raw
drop.wave.voting_credit_typefor the computedvotingLabelin both the main rating line and the “You: …” line keeps the wording consistent and human‑readable, and it will automatically pick up future label changes fromWAVE_VOTING_LABELSwithout touching this component.Also applies to: 115-115
components/waves/drop/SingleWaveDropVoteSlider.tsx (3)
9-17: Label prop integration is consistent and type-safe
labelis added to the props interface, plumbed through the component signature, and rendered in the tooltip text in a single, consistent way. This matches the PR-wide move fromcreditTypeto label-based display with no apparent typing or runtime issues.Also applies to: 85-93, 236-244
124-127: Motion value sync effect is correctly scopedKeeping
xandcurrentPercentagein the dependency array ensures the framer-motion value tracks prop-driven changes without extra re-renders. This should satisfyreact-hooks/exhaustive-depswhile preserving the intended animation behavior.Please run your lint suite to confirm there are no hook dependency warnings around this effect.
136-143: Layout / hit-area styling adjustments look goodThe updated container and track classNames maintain the existing structure while improving touch area and spacing, and they remain Tailwind-only as per guidelines. No behavioral regressions are apparent.
components/waves/drop/SingleWaveDropVoteInput.tsx (3)
3-6: Imports, props, label usage, and icon/UI wiring align with guidelines
- Uses FontAwesome icons and Tailwind classes exclusively in the JSX.
- Props interface is
readonlyand includes the newlabelstring, which is rendered in both MINI and normal layouts.- Event handlers (
onChange,onKeyDown, press handlers) are wired consistently across input and buttons.This all matches the repo’s conventions and the PR-wide shift to label-based voting display.
Also applies to: 8-16, 203-220, 224-240, 242-268
136-147: Input parsing and quick-percentage highlighting behavior look robust
handleInputChangegracefully handles transient values like""and"-", only parsing/clamping once a numeric value is available.- Clamping via
clampValueensures typed values stay within[minValue, maxValue].getQuickPercentageButtonClasscomputestargetValueusing the same formula ashandleQuickPercentage, so the “selected” styling correctly reflects the last clicked quick button even asvoteValuechanges.No correctness issues stand out here.
Also applies to: 173-195
62-75: The diagnosis of async state updater semantics is incorrect.React's state updater functions execute synchronously when
setVoteValue(updater)is called. ThecrossedMemeticflag is assigned within the updater function and theifcheck evaluates it immediately afterward, beforesetVoteValuereturns. The code should work as intended.If the memetic pause is not triggering, investigate other causes: (1) whether
handleMemeticPausereceives the correct increment value in all code paths, (2) whetherisPressed.currentremains true when the 1s timeout fires, or (3) whether rapid successive updates create race conditions in the pause/resume logic.The proposed fix introduces an unnecessary Effect that violates React 19.2 guidelines (derive state during render, not in Effects) and does not address the actual issue.
components/waves/drops/participation/ratings/tooltips/VoteBreakdownTooltip.tsx (3)
53-62: LGTM! Top voter avatars properly implemented.The conversion to
next/imageis correctly done with descriptive alt text, explicit dimensions, and performance-optimized image scaling. The conditional rendering ensures graceful handling when pfp is missing.
69-74: LGTM! Rating display logic is clear and correct.The conditional color coding (green for positive, red for negative) paired with the "+" prefix for positive ratings provides clear visual feedback. The formatting correctly handles both positive and negative values.
8-8: This review comment is incorrect. The code is type-safe and will not result in undefined values.The
WAVE_VOTING_LABELSconstant is typed asRecord<ApiWaveCreditType, string>, which guarantees that all possibleApiWaveCreditTypeenum values have corresponding string mappings. The enum defines four values (Tdh,Xtdh,TdhPlusXtdh,Rep), and all four are present inWAVE_VOTING_LABELS. TypeScript's type system ensures that indexing into aRecord<K, V>with a key of typeKalways returnsV, never undefined. Therefore,votingLabelat line 25 will always be a valid string, and the code at lines 110 and 117 will display the correct label without any risk of showing "undefined".Likely an incorrect or invalid review comment.
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 (1)
components/waves/drop/SingleWaveDropVoteInput.tsx (1)
203-222: Add semantic labels for accessibility.Both input fields lack proper
<label>elements oraria-labelattributes. The label text (lines 217, 238) is purely visual overlay and not accessible to screen readers, preventing assistive technology users from understanding the purpose of these inputs.Based on learnings, every form control must have a label using semantic HTML elements.
Apply this diff to add proper labels for the MINI mode:
if (size === SingleWaveDropVoteSize.MINI) { return ( <div className="tw-flex tw-items-center"> - <div className="tw-relative tw-w-full tw-h-full"> + <label className="tw-relative tw-w-full tw-h-full"> <input type="text" pattern="-?[0-9]*" inputMode="numeric" className="tw-w-full tw-px-3 tw-pr-12 tw-h-8 tw-bg-iron-950 tw-rounded-md tw-text-iron-50 tw-placeholder-iron-400 tw-text-base tw-font-medium tw-outline-none tw-border tw-border-solid tw-border-iron-700 desktop-hover:hover:tw-border-primary-400 focus:tw-border-primary-400 tw-transition-all focus:tw-bg-iron-950 tw-duration-300 tw-ease-out" value={voteValue} onChange={handleInputChange} onKeyDown={handleKeyDown} + aria-label={`Vote amount in ${label}`} /> <div className="tw-absolute tw-right-3 tw-top-1/2 -tw-translate-y-1/2 tw-text-[11px] tw-text-iron-400 tw-pointer-events-none"> {label} </div> - </div> + </label> </div> ); }Apply this diff for NORMAL mode:
<div className="tw-flex tw-items-center tw-gap-2"> - <div className="tw-relative tw-w-full xl:tw-max-w-xs"> + <label className="tw-relative tw-w-full xl:tw-max-w-xs"> <input type="text" pattern="-?[0-9]*" inputMode="numeric" className="tw-w-full tw-px-3 tw-pr-24 tw-h-9 tw-bg-iron-900 tw-rounded-lg tw-text-iron-50 tw-placeholder-iron-400 tw-text-base tw-font-medium tw-border-0 tw-ring-1 tw-ring-iron-700 focus:tw-ring-primary-400/50 desktop-hover:hover:tw-ring-primary-400/30 tw-outline-none tw-transition-all desktop-hover:hover:tw-bg-iron-950/60 focus:tw-bg-iron-950/80" value={voteValue} onChange={handleInputChange} onKeyDown={handleKeyDown} + aria-label={`Vote amount in ${label}`} /> <div className="tw-absolute tw-right-3 tw-top-1/2 -tw-translate-y-1/2 tw-text-xs tw-text-iron-400 tw-pointer-events-none"> {label} </div> - </div> + </label> </div>Also applies to: 227-240
🧹 Nitpick comments (2)
components/waves/drop/SingleWaveDropVoteInput.tsx (2)
128-134: Extract duplicate percentage calculation into a shared helper.The percentage-to-value calculation logic in
handleQuickPercentage(lines 129-132) is duplicated ingetQuickPercentageButtonClass(lines 177-181). Consider extracting this into a reusable helper function to follow DRY principles.Apply this diff to extract the shared logic:
+ const calculatePercentageValue = (percentage: number) => { + return Math.round( + percentage < 0 + ? (Math.abs(percentage) / 100) * minValue + : (percentage / 100) * maxValue + ); + }; + const handleQuickPercentage = (percentage: number) => { - const value = - percentage < 0 - ? (Math.abs(percentage) / 100) * minValue - : (percentage / 100) * maxValue; - setVoteValue(Math.round(value)); + setVoteValue(calculatePercentageValue(percentage)); }; const getQuickPercentageButtonClass = ( percentage: number, currentVoteValue: number | string ) => { - const targetValue = Math.round( - percentage < 0 - ? (Math.abs(percentage) / 100) * minValue - : (percentage / 100) * maxValue - ); + const targetValue = calculatePercentageValue(percentage); const isSelected = Number(currentVoteValue) === targetValue; const isNegative = percentage < 0;Also applies to: 173-195
243-268: Add accessible labels to arrow buttons.The increment and decrement arrow buttons lack accessible text, making their purpose unclear to screen reader users. While users can still interact with the input field directly, adding
aria-labelattributes would improve the experience for assistive technology users.Apply this diff:
<button onMouseDown={() => startPress(true)} onMouseUp={stopPress} onMouseLeave={stopPress} onTouchStart={() => startPress(true)} onTouchEnd={stopPress} + aria-label={`Increase ${label}`} className="tw-border-0 tw-flex tw-items-center tw-justify-center tw-size-9 tw-rounded-lg tw-bg-iron-900 tw-ring-1 tw-ring-iron-800 desktop-hover:hover:tw-ring-emerald-400/50 tw-text-emerald-400 desktop-hover:hover:tw-text-emerald-300 tw-transition-all tw-duration-300 desktop-hover:hover:tw-scale-105 desktop-hover:hover:tw-bg-iron-800/90 active:tw-scale-95" > <FontAwesomeIcon icon={faArrowUp} className="tw-w-4 tw-h-4 tw-flex-shrink-0" /> </button> <button onMouseDown={() => startPress(false)} onMouseUp={stopPress} onMouseLeave={stopPress} onTouchStart={() => startPress(false)} onTouchEnd={stopPress} + aria-label={`Decrease ${label}`} className="tw-border-0 tw-flex tw-items-center tw-justify-center tw-size-9 tw-rounded-lg tw-bg-iron-900 tw-ring-1 tw-ring-iron-800 desktop-hover:hover:tw-ring-rose-400/50 tw-text-rose-400 desktop-hover:hover:tw-text-rose-300 tw-transition-all tw-duration-300 desktop-hover:hover:tw-scale-105 desktop-hover:hover:tw-bg-iron-800/90 active:tw-scale-95" > <FontAwesomeIcon icon={faArrowDown} className="tw-w-4 tw-h-4 tw-flex-shrink-0" /> </button>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
components/waves/drop/SingleWaveDropVoteInput.tsx(6 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/drop/SingleWaveDropVoteInput.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/drop/SingleWaveDropVoteInput.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/drop/SingleWaveDropVoteInput.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/drop/SingleWaveDropVoteInput.tsx
🧠 Learnings (3)
📚 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:
components/waves/drop/SingleWaveDropVoteInput.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/drop/SingleWaveDropVoteInput.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 FontAwesome for icons in React components
Applied to files:
components/waves/drop/SingleWaveDropVoteInput.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
components/waves/drop/SingleWaveDropVoteInput.tsx (5)
3-5: LGTM!The imports follow best practices with direct named imports from React and FontAwesome icons as specified in the coding guidelines.
8-16: LGTM!The change from
creditTypetolabelmakes the component more flexible and decoupled from the API type system. All props correctly usereadonlyas required.
18-39: LGTM!The module-level constants and ref types are correctly implemented. The timer refs use
ReturnType<typeof setInterval/setTimeout> | nullfor proper cross-platform type safety, addressing the concerns from previous reviews.
41-109: LGTM!The helper functions are well-structured and correctly implement the memetic-snapping logic. The approach of checking
isPressed.currentin the timeout callback eliminates the need for a separate pause state, resulting in cleaner code than the originally suggested implementation.
149-171: LGTM!The press/release handlers and cleanup effect are correctly implemented. Timers are properly managed, and the cleanup effect ensures no memory leaks on unmount.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
helpers/waves/waves.constants.ts (2)
14-17: Solid centralization of vote stats labels; consider tightening types withas const.The new
WAVE_VOTE_STATS_LABELSkeys/values look good and will help keep labels consistent. For slightly stronger typing and to avoid accidental value changes, you could mark this as immutable:-export const WAVE_VOTE_STATS_LABELS = { - YOUR_VOTES: "Your votes", - TOTAL: "Total", -}; +export const WAVE_VOTE_STATS_LABELS = { + YOUR_VOTES: "Your votes", + TOTAL: "Total", +} as const;
20-23: Labels for new credit types look correct; consider enforcing enum coverage viasatisfies.The updated
WAVE_VOTING_LABELSentries forTdh,Xtdh,TdhPlusXtdh, andReplook consistent with the naming elsewhere. To catch missing/extraApiWaveCreditTypemembers at compile time, you could switch tosatisfies:-export const WAVE_VOTING_LABELS: Record<ApiWaveCreditType, string> = { - [ApiWaveCreditType.Tdh]: "TDH", - [ApiWaveCreditType.Xtdh]: "XTDH", - [ApiWaveCreditType.TdhPlusXtdh]: "TDH + XTDH", - [ApiWaveCreditType.Rep]: "Rep", -}; +export const WAVE_VOTING_LABELS = { + [ApiWaveCreditType.Tdh]: "TDH", + [ApiWaveCreditType.Xtdh]: "XTDH", + [ApiWaveCreditType.TdhPlusXtdh]: "TDH + XTDH", + [ApiWaveCreditType.Rep]: "Rep", +} satisfies Record<ApiWaveCreditType, string>;Also, please double‑check that every
ApiWaveCreditTypevalue that can appear from the API is included here so you never renderundefinedlabels at runtime.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
helpers/waves/waves.constants.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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:
helpers/waves/waves.constants.ts
**/*.{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:
helpers/waves/waves.constants.ts
**/*.{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:
helpers/waves/waves.constants.ts
🔇 Additional comments (1)
helpers/waves/waves.constants.ts (1)
152-156: No functional change detected inCREATE_WAVE_START_DATE_LABELS.The modification here appears to be non-functional (likely formatting or a regenerated line ending); no action needed.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
components/waves/create-wave/voting/CreateWaveVoting.tsx (1)
14-19: Ordering map is redundant without a sort; consider simplifying iteration
VOTING_TYPES_ORDERencodes numeric order but the render logic only filters on!== undefinedand then relies on object key insertion order. If someone later changes the numeric values expecting them to control UI order, nothing will happen.To make the intent explicit and reduce complexity, you can either:
- Drive the UI from an ordered list, or
- Keep the map but sort by the numeric order.
For example, an ordered list keeps things simple and avoids the
Object.keyscast:-const VOTING_TYPES_ORDER: Record<ApiWaveCreditType, number | undefined> = { - [ApiWaveCreditType.TdhPlusXtdh]: 0, - [ApiWaveCreditType.Tdh]: 1, - [ApiWaveCreditType.Rep]: 2, - [ApiWaveCreditType.Xtdh]: undefined, -}; +const ORDERED_VOTING_TYPES: readonly ApiWaveCreditType[] = [ + ApiWaveCreditType.TdhPlusXtdh, + ApiWaveCreditType.Tdh, + ApiWaveCreditType.Rep, +]; @@ - {( - Object.keys(VOTING_TYPES_ORDER) as ApiWaveCreditType[] - ).filter((votingType) => VOTING_TYPES_ORDER[votingType] !== undefined).map((votingType) => ( + {ORDERED_VOTING_TYPES.map((votingType) => (This still hides
ApiWaveCreditType.Xtdhfrom the UI but makes the intended order explicit and easier to maintain.Also applies to: 65-67
__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsx (1)
14-24: Add test coverage for the new "TDH + xTDH" mode.The test correctly includes the
inclusion_strategyproperty, but only tests theTdhmode. Consider adding a test case forApiGroupTdhInclusionStrategy.Bothto verify the label displays as "TDH + xTDH at least".Add a test case:
it('passes correct label for Both inclusion strategy', () => { const setTDH = jest.fn(); const tdh = { min: 5, inclusion_strategy: ApiGroupTdhInclusionStrategy.Both } as any; const { getByTestId } = render(<GroupCreateTDH tdh={tdh} setTDH={setTDH} />); expect(getByTestId('numeric')).toBeInTheDocument(); expect(mockProps.value).toBe(5); expect(mockProps.label).toBe('TDH + xTDH at least'); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsx(2 hunks)__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts(2 hunks)components/groups/page/create/GroupCreate.tsx(1 hunks)components/groups/page/create/config/GroupCreateTDH.tsx(1 hunks)components/waves/create-wave/hooks/useWaveConfig.ts(1 hunks)components/waves/create-wave/voting/CreateWaveVoting.tsx(2 hunks)helpers/waves/create-wave.helpers.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{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/groups/page/create/GroupCreate.tsx__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsxcomponents/groups/page/create/config/GroupCreateTDH.tsxcomponents/waves/create-wave/hooks/useWaveConfig.tshelpers/waves/create-wave.helpers.ts__tests__/components/waves/create-wave/hooks/useWaveConfig.test.tscomponents/waves/create-wave/voting/CreateWaveVoting.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/groups/page/create/GroupCreate.tsx__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsxcomponents/groups/page/create/config/GroupCreateTDH.tsxcomponents/waves/create-wave/voting/CreateWaveVoting.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/groups/page/create/GroupCreate.tsx__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsxcomponents/groups/page/create/config/GroupCreateTDH.tsxcomponents/waves/create-wave/hooks/useWaveConfig.tshelpers/waves/create-wave.helpers.ts__tests__/components/waves/create-wave/hooks/useWaveConfig.test.tscomponents/waves/create-wave/voting/CreateWaveVoting.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/groups/page/create/GroupCreate.tsx__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsxcomponents/groups/page/create/config/GroupCreateTDH.tsxcomponents/waves/create-wave/hooks/useWaveConfig.tshelpers/waves/create-wave.helpers.ts__tests__/components/waves/create-wave/hooks/useWaveConfig.test.tscomponents/waves/create-wave/voting/CreateWaveVoting.tsx
{.env*,*.env,**/config/**}
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Configure Task Master behavior via environment variables: ANTHROPIC_API_KEY (required), MODEL, MAX_TOKENS, TEMPERATURE, DEBUG, LOG_LEVEL, DEFAULT_SUBTASKS, DEFAULT_PRIORITY, PROJECT_NAME, PROJECT_VERSION, PERPLEXITY_API_KEY, and PERPLEXITY_MODEL
Files:
__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsxcomponents/groups/page/create/config/GroupCreateTDH.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/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
**/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Place tests in
__tests__/directory or asComponentName.test.tsxalongside components
Files:
__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
__tests__/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use Jest +
ts-jestfor TypeScript testing
Files:
__tests__/components/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
__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/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
__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/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
__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/groups/page/create/config/GroupCreateTDH.test.tsx__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
🧠 Learnings (7)
📚 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__/components/groups/page/create/config/GroupCreateTDH.test.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/groups/page/create/config/GroupCreateTDH.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 **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests
Applied to files:
__tests__/components/groups/page/create/config/GroupCreateTDH.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__/app/api/**/__tests__/**/*.test.{ts,tsx,js} : API integration tests should be located in `app/api`
Applied to files:
__tests__/components/groups/page/create/config/GroupCreateTDH.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/groups/page/create/config/GroupCreateTDH.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__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)
Applied to files:
__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
📚 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} : Write tests following Arrange – Act – Assert pattern with one behaviour per test and clear, descriptive names
Applied to files:
__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts
🧬 Code graph analysis (2)
__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts (1)
components/waves/create-wave/hooks/useWaveConfig.ts (1)
useWaveConfig(27-358)
components/waves/create-wave/voting/CreateWaveVoting.tsx (1)
helpers/waves/waves.constants.ts (1)
WAVE_VOTING_LABELS(19-24)
🔇 Additional comments (6)
helpers/waves/create-wave.helpers.ts (1)
375-383: Defaulting votingcredit_typetoTdhPlusXtdhmatches the new wave semanticsUsing
config.voting.type ?? ApiWaveCreditType.TdhPlusXtdhis a clean way to make TDH + XTDH the explicit default while still honoring any configured credit type. This is consistent with the PR’s intent and keeps the payload well-defined even ifconfig.voting.typeis unset.components/waves/create-wave/voting/CreateWaveVoting.tsx (1)
73-73: Label composition looks consistent with shared voting labelsThe new
label={By ${WAVE_VOTING_LABELS[votingType]}}usage cleanly centralizes the human-readable text and should stay in sync withWAVE_VOTING_LABELS(including the new TDH + XTDH entry). No issues here.components/groups/page/create/config/GroupCreateTDH.tsx (1)
15-26: LGTM! Mode consolidation is consistent.The updated modes array with "TDH + xTDH" (Both) and "TDH" (Tdh) options is correctly implemented, and the display logic at lines 35-43 and 62-65 properly handles the Both case by showing "TDH + xTDH" labels.
components/waves/create-wave/hooks/useWaveConfig.ts (1)
71-71: LGTM! Default voting type updated to TDH + XTDH.The change from
ApiWaveCreditType.TdhtoApiWaveCreditType.TdhPlusXtdhas the default voting configuration aligns with the broader PR changes introducing combined TDH + XTDH voting.components/groups/page/create/GroupCreate.tsx (1)
99-99: LGTM! Default updated with backward compatibility maintained.The change to default new groups to
ApiGroupTdhInclusionStrategy.Bothis consistent with the PR objectives. Backward compatibility is correctly preserved at lines 134-136 where existing groups maintain their originalinclusion_strategyor default toTdhif not present.__tests__/components/waves/create-wave/hooks/useWaveConfig.test.ts (1)
49-60: LGTM! Test expectations correctly updated.The test description and assertions have been properly updated to reflect the new default voting type of
ApiWaveCreditType.TdhPlusXtdh, matching the implementation changes inuseWaveConfig.ts.
|



Summary by CodeRabbit
New Features
Bug Fixes
Changes
✏️ Tip: You can customize this high-level summary in your review settings.