Skip to content

lightinig-bounties - #163

Closed
rosemary21 wants to merge 3 commits into
boundlessfi:mainfrom
rosemary21:lightinig-bounties
Closed

lightinig-bounties#163
rosemary21 wants to merge 3 commits into
boundlessfi:mainfrom
rosemary21:lightinig-bounties

Conversation

@rosemary21

@rosemary21 rosemary21 commented Mar 27, 2026

Copy link
Copy Markdown

closes #145

Endpoint Purpose
GET /health/live Liveness probe (no dependency checks)
GET /health/detailed Full JSON metrics snapshot
GET /health/metrics Prometheus text exposition for scraping

Summary by CodeRabbit

  • New Features
    • Introduced Lightning Rounds — dedicated round pages with live countdowns, status badges, stats, progress bars, and organized category sections linking to bounties
    • Added Lightning Round banner and schedule components to the bounties page and sidebar for quick discovery
    • Added Lightning badge to bounty cards to highlight round-affiliated bounties

@vercel

vercel Bot commented Mar 27, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Mar 27, 2026

Copy link
Copy Markdown

@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! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@Benjtalkshow has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 8 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 20 minutes and 8 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 886be2e3-15d1-4fde-8aee-f4b037689d1f

📥 Commits

Reviewing files that changed from the base of the PR and between 5c8071d and 5c1d400.

📒 Files selected for processing (3)
  • app/bounty/lightning-round/page.tsx
  • components/bounty/lightning-round-schedule.tsx
  • hooks/use-lightning-rounds.ts
📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
Lightning Round Page
app/bounty/lightning-round/page.tsx
New client-side page rendering a selected or active lightning round: groups bounties by category, shows stats, progress, countdown, and round selector via windowId query param.
Hooks / Countdown
hooks/use-lightning-rounds.ts
New hooks exporting useLightningRounds(), useLightningRoundBounties(windowId), and useCountdown(targetDate); transform active bounties into rounds, fetch/organize bounties by category, compute totals/completed counts, and provide live countdown state.
Banner & Schedule UI
components/bounty/lightning-round-banner.tsx, components/bounty/lightning-round-schedule.tsx
New client components: banner with live/upcoming badges, stats, countdown and CTA; schedule card listing next rounds with status, links, and skeleton/loading/empty states.
Bounty Grid Integration
app/bounty/page.tsx
Inserts LightningRoundBanner into the main bounties page (adds spacing).
Bounty Card Enhancement
components/bounty/bounty-card.tsx
Adds conditional "Lightning" Badge with Zap icon when a bounty is associated with a bountyWindow.
Filters Sidebar
components/bounty/filters-sidebar.tsx
Renders LightningRoundSchedule alongside existing sidebar items and adds vertical spacing (space-y-4) in large view.

Sequence Diagrams

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • Benjtalkshow

Poem

🐰⚡ I hopped in with a twitch and cheer,
Rounds lined up, the bounties near,
Tickers ticking, categories bloom,
Zap-badges flash — quick, make room!
Hooray for rounds that sparkle and steer ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'lightinig-bounties' is a typo-ridden and vague reference to the Lightning Bounties feature. While it's tangentially related to the main changeset, it lacks clarity and contains a spelling error ('lightinig' vs 'lightning'). Consider revising the title to be more descriptive and accurate, such as 'Add Lightning Rounds feature with banner, schedule, and dedicated page' to better represent the actual changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR implements most core requirements from issue #145: lightning round banner [#145], dedicated round page [#145], bounty badge [#145], schedule widget [#145], and custom hooks [#145]. However, the PR description mentions health endpoints unrelated to Lightning Rounds, suggesting incomplete scope documentation.
Out of Scope Changes check ✅ Passed All code changes align directly with issue #145 requirements: banner component, dedicated page, bounty badge, schedule widget, and data hooks. The PR description's mention of health endpoints appears to be documentation error rather than actual code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 bountyWindow exists. Two optional enhancements to consider:

  1. The bountyWindow.name field is available (per the GraphQL fragment) and could replace the static "Lightning" text to show the actual round name.
  2. 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 checking bountyWindow.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 isActive is 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 (isEnded is true) but its status is not "active", the code sets countdownTarget to startDate and displays "Starts in". This will show a confusing countdown for a past date (which useCountdown will mark as expired, returning null). While CountdownBlock handles expired by 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3aad250 and 35e49e2.

📒 Files selected for processing (6)
  • app/bounty/lightning-round/page.tsx
  • app/bounty/page.tsx
  • components/bounty/bounty-card.tsx
  • components/bounty/lightning-round-banner.tsx
  • components/bounty/lightning-round-schedule.tsx
  • hooks/use-lightning-rounds.ts

Comment thread hooks/use-lightning-rounds.ts Outdated

@Benjtalkshow Benjtalkshow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (lightiniglightning).

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 35e49e2 and 5c8071d.

📒 Files selected for processing (3)
  • app/bounty/page.tsx
  • components/bounty/bounty-card.tsx
  • components/bounty/filters-sidebar.tsx
✅ Files skipped from review due to trivial changes (2)
  • app/bounty/page.tsx
  • components/bounty/bounty-card.tsx

Comment thread components/bounty/filters-sidebar.tsx
- Skip useLightningRoundBounties query when windowId is empty
  (avoids unnecessary request on initial load before a round is selected)
- Normalize status case in completedCount filter so "COMPLETED" from the
  backend is counted correctly
- Extract hardcoded bounties limit (50) to LIGHTNING_ROUND_BOUNTIES_LIMIT
- Replace eslint-disable in useCountdown with useCallback so getTime
  stays stable and the effect deps are correct
- Handle LightningRoundSchedule query failures with an explicit error
  branch and a retry button instead of the misleading empty state
- Wrap useSearchParams in a Suspense boundary as required by Next.js 13+

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants