Conversation
|
Someone is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
@rosemary21 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
📝 WalkthroughWalkthroughAdds a Lightning Rounds feature: new landing page, banner, schedule widget, bounty-card badge, and hooks for round aggregation and countdown; integrates banner/schedule into existing bounty pages and provides client-side countdowns and per-round bounty grouping. Changes
Sequence DiagramssequenceDiagram
participant User
participant Page as Lightning Round Page
participant Hooks as useLightningRounds / useLightningRoundBounties
participant Query as GraphQL Query
participant Countdown as useCountdown
User->>Page: Navigate to /bounty/lightning-round (optional windowId)
Page->>Hooks: useLightningRounds()
Hooks->>Query: useActiveBountiesQuery()
Query-->>Hooks: Active bounties with bountyWindow info
Hooks->>Hooks: Group by window, compute rounds & activeRound
Hooks-->>Page: rounds[], activeRound
Page->>Hooks: useLightningRoundBounties(windowId)
Hooks->>Query: useBountiesQuery(windowId, limit=50)
Query-->>Hooks: Bounties for window
Hooks->>Hooks: Bucket by category, calc totals, completedCount
Hooks-->>Page: bounties, byCategory, totals
Page->>Countdown: useCountdown(targetDate)
Countdown->>Countdown: tick every second
Countdown-->>Page: days,hours,minutes,seconds,expired
Page-->>User: Render categories, stats, progress bar, and countdown
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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: 1
🧹 Nitpick comments (3)
components/bounty/bounty-card.tsx (1)
112-117: Consider displaying round name or checking round status.The implementation correctly shows the Lightning badge when
bountyWindowexists. Two optional enhancements to consider:
- The
bountyWindow.namefield is available (per the GraphQL fragment) and could replace the static "Lightning" text to show the actual round name.- The badge displays regardless of
bountyWindow.status— a completed or cancelled round will still show the badge. If the intent is to highlight only active lightning rounds, consider checkingbountyWindow.status === 'ACTIVE'.These are optional improvements; the current implementation meets the basic acceptance criteria.
💡 Optional: Show round name and check status
- {bounty.bountyWindow && ( + {bounty.bountyWindow && bounty.bountyWindow.status === 'ACTIVE' && ( <Badge className="text-[10px] px-1.5 py-0.5 gap-1 bg-yellow-500/15 text-yellow-400 border-yellow-500/30"> <Zap className="h-2.5 w-2.5 fill-yellow-400" /> - Lightning + {bounty.bountyWindow.name} </Badge> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/bounty/bounty-card.tsx` around lines 112 - 117, The badge currently renders whenever bounty.bountyWindow is truthy and shows static "Lightning"; update the JSX in the component that renders Badge (the block using Badge and Zap) to instead display bounty.bountyWindow.name when available and to only render the Badge for active rounds by checking bounty.bountyWindow.status === 'ACTIVE' (fall back to the static label if name is missing). Keep the existing Badge and Zap usage but add the conditional on bounty.bountyWindow.status and replace the hardcoded text with bounty.bountyWindow.name || 'Lightning'.app/bounty/lightning-round/page.tsx (2)
255-258: Label mismatch for ended rounds.The label shows "Starts in" when
isActiveis false, but this includes ended rounds. Consider adjusting the label logic to avoid showing a countdown label at all for ended rounds.Proposed fix
- <CountdownBlock - targetDate={countdownTarget ?? null} - label={isActive ? "Ends in" : "Starts in"} - /> + {!isEnded && ( + <CountdownBlock + targetDate={countdownTarget ?? null} + label={isActive ? "Ends in" : "Starts in"} + /> + )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/bounty/lightning-round/page.tsx` around lines 255 - 258, The current CountdownBlock is given label based only on isActive which causes ended rounds (isActive false but past targetDate) to show "Starts in"; update the logic around CountdownBlock/props (CountdownBlock, targetDate, label, countdownTarget, isActive) to detect an ended round and either omit the label or skip rendering the component: e.g., compute an isEnded check (targetDate in the past) and then pass label={isActive ? "Ends in" : (isEnded ? undefined : "Starts in")} or conditionally render CountdownBlock only when not ended so ended rounds do not display a countdown label.
179-186: Countdown may show "Starts in" for already-ended rounds.When a round has ended (
isEndedis true) but its status is not"active", the code setscountdownTargettostartDateand displays "Starts in". This will show a confusing countdown for a past date (whichuseCountdownwill mark as expired, returning null). WhileCountdownBlockhandlesexpiredby returning null, the label "Starts in" is still set—this is potentially misleading if there's any race condition or the countdown hasn't yet recalculated.Consider explicitly handling the ended state:
Proposed fix
const isActive = currentRound?.status.toLowerCase() === "active"; const isEnded = currentRound?.endDate && new Date(currentRound.endDate) < new Date(); - const countdownTarget = isActive ? currentRound?.endDate : currentRound?.startDate; + const countdownTarget = isActive + ? currentRound?.endDate + : isEnded + ? null + : currentRound?.startDate;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/bounty/lightning-round/page.tsx` around lines 179 - 186, The countdown can show a "Starts in" label for already-ended rounds because countdownTarget is set to startDate when isActive is false; update the logic that computes countdownTarget (and any label selection) in the component using currentRound, isActive and isEnded so that when isEnded is true you set countdownTarget to null/undefined (or otherwise skip rendering the CountdownBlock) instead of using currentRound.startDate; change the assignment of countdownTarget and any related label computation (references: isActive, isEnded, countdownTarget, currentRound, useCountdown, CountdownBlock) so ended rounds do not render a "Starts in" countdown.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@hooks/use-lightning-rounds.ts`:
- Around line 83-86: The hook useLightningRoundBounties currently calls
useBountiesQuery with query: { bountyWindowId: windowId, limit: 50 } even when
windowId is empty, causing unnecessary requests; update the call to pass an
enabled flag (e.g., enabled: Boolean(windowId)) so the query is skipped when
windowId is falsy, and keep the query object intact (bountyWindowId and limit)
to preserve behavior when enabled.
---
Nitpick comments:
In `@app/bounty/lightning-round/page.tsx`:
- Around line 255-258: The current CountdownBlock is given label based only on
isActive which causes ended rounds (isActive false but past targetDate) to show
"Starts in"; update the logic around CountdownBlock/props (CountdownBlock,
targetDate, label, countdownTarget, isActive) to detect an ended round and
either omit the label or skip rendering the component: e.g., compute an isEnded
check (targetDate in the past) and then pass label={isActive ? "Ends in" :
(isEnded ? undefined : "Starts in")} or conditionally render CountdownBlock only
when not ended so ended rounds do not display a countdown label.
- Around line 179-186: The countdown can show a "Starts in" label for
already-ended rounds because countdownTarget is set to startDate when isActive
is false; update the logic that computes countdownTarget (and any label
selection) in the component using currentRound, isActive and isEnded so that
when isEnded is true you set countdownTarget to null/undefined (or otherwise
skip rendering the CountdownBlock) instead of using currentRound.startDate;
change the assignment of countdownTarget and any related label computation
(references: isActive, isEnded, countdownTarget, currentRound, useCountdown,
CountdownBlock) so ended rounds do not render a "Starts in" countdown.
In `@components/bounty/bounty-card.tsx`:
- Around line 112-117: The badge currently renders whenever bounty.bountyWindow
is truthy and shows static "Lightning"; update the JSX in the component that
renders Badge (the block using Badge and Zap) to instead display
bounty.bountyWindow.name when available and to only render the Badge for active
rounds by checking bounty.bountyWindow.status === 'ACTIVE' (fall back to the
static label if name is missing). Keep the existing Badge and Zap usage but add
the conditional on bounty.bountyWindow.status and replace the hardcoded text
with bounty.bountyWindow.name || 'Lightning'.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 15eb379c-b598-49ee-8995-7de9514ad08b
📒 Files selected for processing (6)
app/bounty/lightning-round/page.tsxapp/bounty/page.tsxcomponents/bounty/bounty-card.tsxcomponents/bounty/lightning-round-banner.tsxcomponents/bounty/lightning-round-schedule.tsxhooks/use-lightning-rounds.ts
| export function useLightningRoundBounties(windowId: string) { | ||
| const { data, isLoading, isError, error } = useBountiesQuery({ | ||
| query: { bountyWindowId: windowId, limit: 50 }, | ||
| }); |
There was a problem hiding this comment.
Query executes with empty windowId when no round is selected.
Based on the context snippet showing useBountiesQuery does not skip when bountyWindowId is empty, this hook will fire a query with bountyWindowId: "" when called with an empty string (e.g., from the page when currentRound?.id ?? ""). This results in an unnecessary network request that likely returns zero or unexpected results.
Consider adding an enabled option to skip the query when windowId is falsy:
Proposed fix
export function useLightningRoundBounties(windowId: string) {
const { data, isLoading, isError, error } = useBountiesQuery({
query: { bountyWindowId: windowId, limit: 50 },
+ }, {
+ enabled: !!windowId,
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function useLightningRoundBounties(windowId: string) { | |
| const { data, isLoading, isError, error } = useBountiesQuery({ | |
| query: { bountyWindowId: windowId, limit: 50 }, | |
| }); | |
| export function useLightningRoundBounties(windowId: string) { | |
| const { data, isLoading, isError, error } = useBountiesQuery({ | |
| query: { bountyWindowId: windowId, limit: 50 }, | |
| }, { | |
| enabled: !!windowId, | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@hooks/use-lightning-rounds.ts` around lines 83 - 86, The hook
useLightningRoundBounties currently calls useBountiesQuery with query: {
bountyWindowId: windowId, limit: 50 } even when windowId is empty, causing
unnecessary requests; update the call to pass an enabled flag (e.g., enabled:
Boolean(windowId)) so the query is skipped when windowId is falsy, and keep the
query object intact (bountyWindowId and limit) to preserve behavior when
enabled.
There was a problem hiding this comment.
Hi @rosemary21 , great work on the Lightning Rounds feature,
There are a few things to address before merging:
The useLightningRoundBounties hook fires a query even when windowId is empty, so it should include enabled: !!windowId as suggested.
Both useLightningRounds and useLightningRoundBounties redundantly fetch bounties for the same window on the lightning round page, which leads to unnecessary data duplication.
The b.status === "completed" check in the hook is case-sensitive, while the rest of the codebase uses .toLowerCase(), so the completed count will likely always be 0.
Additionally, please address the following:
The light mode compatibility needs attention, as the text-yellow-300 countdown text and from-yellow-950/40 gradients will have poor contrast or appear muddy on light backgrounds.
Fix the PR title typo (lightinig → lightning).
Add a Suspense boundary around useSearchParams() as required by Next.js 13+.
Apply the suggested correction for handling the empty windowId query and fix conflict.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@components/bounty/filters-sidebar.tsx`:
- Around line 212-214: The LightningRoundSchedule component currently renders an
empty-state when the rounds query fails; update
components/bounty/lightning-round-schedule.tsx to explicitly handle the query
error by checking the query's isError (or error) state from whatever data hook
(e.g., useRounds or useQuery) you use, and add an error UI branch that shows a
clear error message plus a retry action that calls the query's refetch (or
retry) method; ensure the component still handles loading and success branches
but returns the new error view when isError is true so the sidebar (where
LightningRoundSchedule is mounted) won’t display the misleading empty state.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2756d2da-4797-41b3-a64f-0447ac935a0b
📒 Files selected for processing (3)
app/bounty/page.tsxcomponents/bounty/bounty-card.tsxcomponents/bounty/filters-sidebar.tsx
✅ Files skipped from review due to trivial changes (2)
- app/bounty/page.tsx
- components/bounty/bounty-card.tsx
| <div className="hidden lg:block space-y-4"> | ||
| <MiniLeaderboard className="w-full" /> | ||
| <LightningRoundSchedule className="w-full" /> |
There was a problem hiding this comment.
Handle Lightning schedule query failures explicitly.
By rendering LightningRoundSchedule in the sidebar (Line 214), users can now see a misleading empty-state message when the rounds query fails, since the component currently ignores isError. Please add an error branch (with retry) in components/bounty/lightning-round-schedule.tsx.
💡 Proposed fix (in components/bounty/lightning-round-schedule.tsx)
-export function LightningRoundSchedule({
+export function LightningRoundSchedule({
className,
maxItems = 3,
}: LightningRoundScheduleProps) {
- const { rounds, isLoading } = useLightningRounds();
+ const { rounds, isLoading, isError, refetch } = useLightningRounds();
const displayed = rounds.slice(0, maxItems);
return (
@@
<CardContent className="p-0">
{isLoading ? (
<ScheduleSkeleton />
+ ) : isError ? (
+ <div className="px-4 py-6 text-center text-sm text-muted-foreground">
+ Failed to load round schedule.
+ <button
+ type="button"
+ onClick={() => refetch()}
+ className="ml-2 underline hover:text-foreground"
+ >
+ Retry
+ </button>
+ </div>
) : displayed.length === 0 ? (
<div className="px-4 py-6 text-center text-sm text-muted-foreground">
No upcoming rounds scheduled.
</div>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@components/bounty/filters-sidebar.tsx` around lines 212 - 214, The
LightningRoundSchedule component currently renders an empty-state when the
rounds query fails; update components/bounty/lightning-round-schedule.tsx to
explicitly handle the query error by checking the query's isError (or error)
state from whatever data hook (e.g., useRounds or useQuery) you use, and add an
error UI branch that shows a clear error message plus a retry action that calls
the query's refetch (or retry) method; ensure the component still handles
loading and success branches but returns the new error view when isError is true
so the sidebar (where LightningRoundSchedule is mounted) won’t display the
misleading empty state.
closes #145
Summary by CodeRabbit