Conversation
# Conflicts: # frontend/src/routes/events/$id.tsx
📝 WalkthroughWalkthroughThe event page now displays repository lockdown status with scheduled, reached, and locked states. Scheduled locks show a live countdown, nullable lock dates are supported, tests cover countdown behavior, and local API values enable random game results. ChangesRepository lockdown notice
Local runtime defaults
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant EventRoute
participant RepositoryLockdownNotice
participant BrowserTimer
EventRoute->>RepositoryLockdownNotice: pass repoLockDate and lockedAt
RepositoryLockdownNotice->>BrowserTimer: start 1-second countdown updates
BrowserTimer->>RepositoryLockdownNotice: update current time
RepositoryLockdownNotice-->>EventRoute: render lockdown status and countdown
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/components/repository-lockdown-notice.tsx`:
- Around line 1-108: Apply the mandated Prettier style across
frontend/src/components/repository-lockdown-notice.tsx lines 1-108 and
frontend/src/components/repository-lockdown-notice.test.tsx lines 3-80 by using
double-quoted strings/imports and semicolon-terminated statements; add the
missing semicolon to the interface member in frontend/src/app/actions/event.ts
line 18; and update the import in frontend/src/routes/events/$id.tsx line 16 to
use double quotes and a terminating semicolon.
- Around line 36-39: Rename the React component file containing
RepositoryLockdownNotice to RepositoryLockdownNotice.tsx, then update its
imports in the events route and repository-lockdown-notice test to reference the
new PascalCase filename.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b30942b2-6bcc-4374-8808-b479a4f2f870
📒 Files selected for processing (5)
frontend/src/app/actions/event.tsfrontend/src/components/repository-lockdown-notice.test.tsxfrontend/src/components/repository-lockdown-notice.tsxfrontend/src/routes/events/$id.tsxlocal-setup/local-values/api.yaml
| import { LockKeyhole } from 'lucide-react' | ||
| import { useEffect, useState } from 'react' | ||
| import TimeBadge from '@/components/timeBadge' | ||
| import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' | ||
| import { Badge } from '@/components/ui/badge' | ||
|
|
||
| interface RepositoryLockdownNoticeProps { | ||
| repoLockDate?: string | null | ||
| lockedAt?: string | null | ||
| } | ||
|
|
||
| export function formatRepoLockCountdown(remainingMs: number) { | ||
| const { days, hours, minutes, seconds } = | ||
| getRepoLockCountdownParts(remainingMs) | ||
| const time = `${hours}:${minutes}:${seconds}` | ||
|
|
||
| return days !== '00' ? `${Number(days)}d ${time}` : time | ||
| } | ||
|
|
||
| export function getRepoLockCountdownParts(remainingMs: number) { | ||
| const totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000)) | ||
| const days = Math.floor(totalSeconds / 86_400) | ||
| const hours = Math.floor((totalSeconds % 86_400) / 3_600) | ||
| const minutes = Math.floor((totalSeconds % 3_600) / 60) | ||
| const seconds = totalSeconds % 60 | ||
| const pad = (value: number) => String(value).padStart(2, '0') | ||
|
|
||
| return { | ||
| days: pad(days), | ||
| hours: pad(hours), | ||
| minutes: pad(minutes), | ||
| seconds: pad(seconds), | ||
| } | ||
| } | ||
|
|
||
| export default function RepositoryLockdownNotice({ | ||
| repoLockDate, | ||
| lockedAt, | ||
| }: Readonly<RepositoryLockdownNoticeProps>) { | ||
| const lockTime = repoLockDate ? new Date(repoLockDate).getTime() : Number.NaN | ||
| const [now, setNow] = useState(() => Date.now()) | ||
| const isScheduled = Number.isFinite(lockTime) && lockTime > now && !lockedAt | ||
|
|
||
| useEffect(() => { | ||
| if (!isScheduled) return undefined | ||
|
|
||
| const interval = window.setInterval(() => setNow(Date.now()), 1000) | ||
| return () => window.clearInterval(interval) | ||
| }, [isScheduled, lockTime]) | ||
|
|
||
| if (!Number.isFinite(lockTime)) return null | ||
|
|
||
| const remainingMs = lockTime - now | ||
| const hasReachedLockTime = remainingMs <= 0 | ||
| const isLocked = Boolean(lockedAt) | ||
| const countdownParts = getRepoLockCountdownParts(remainingMs) | ||
|
|
||
| return ( | ||
| <div className="container mx-auto max-w-7xl px-4"> | ||
| <Alert className="border-warning-400/40 bg-warning-100/50 dark:bg-warning-900/20"> | ||
| <div className="flex items-start gap-4"> | ||
| <LockKeyhole className="mt-0.5 size-5 shrink-0" aria-hidden="true" /> | ||
| <div className="min-w-0 flex-1"> | ||
| <AlertTitle> | ||
| {isLocked | ||
| ? 'Team repositories are locked' | ||
| : hasReachedLockTime | ||
| ? 'Repository lockdown time reached' | ||
| : 'Repository lockdown scheduled'} | ||
| </AlertTitle> | ||
| <AlertDescription className="mt-2 flex flex-wrap items-center justify-between gap-4"> | ||
| <div className="flex flex-wrap items-center gap-1"> | ||
| <span>Scheduled for</span> | ||
| <TimeBadge className="font-medium" time={repoLockDate!} /> | ||
| </div> | ||
| {!isLocked && !hasReachedLockTime && ( | ||
| <div | ||
| role="timer" | ||
| aria-label={`Repository lockdown countdown: ${formatRepoLockCountdown(remainingMs)}`} | ||
| className="flex flex-wrap items-center gap-1.5" | ||
| > | ||
| <span className="mr-1 text-xs font-semibold tracking-wide text-muted-foreground uppercase"> | ||
| Locks in | ||
| </span> | ||
| {Object.entries(countdownParts).map(([label, value]) => ( | ||
| <Badge | ||
| key={label} | ||
| variant="secondary" | ||
| aria-label={`${label}: ${value}`} | ||
| className="flex min-w-13 flex-col gap-0.5 px-2 py-1 font-normal tabular-nums" | ||
| > | ||
| <span className="font-mono text-base font-bold leading-none"> | ||
| {value} | ||
| </span> | ||
| <span className="text-[9px] leading-none tracking-wide text-muted-foreground uppercase"> | ||
| {label} | ||
| </span> | ||
| </Badge> | ||
| ))} | ||
| </div> | ||
| )} | ||
| </AlertDescription> | ||
| </div> | ||
| </div> | ||
| </Alert> | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Apply the mandated frontend Prettier style.
frontend/src/components/repository-lockdown-notice.tsx#L1-L108: use double-quoted strings and semicolon-terminated statements.frontend/src/components/repository-lockdown-notice.test.tsx#L3-L80: use double-quoted strings and semicolon-terminated statements.frontend/src/app/actions/event.ts#L18-L18: terminate the interface member with a semicolon.frontend/src/routes/events/$id.tsx#L16-L16: use a double-quoted import and a semicolon.
As per coding guidelines, "frontend/**/*.{ts,tsx}: In the Next.js frontend, use Prettier formatting with 2-space indentation, double-quoted strings and imports, and semicolons."
📍 Affects 4 files
frontend/src/components/repository-lockdown-notice.tsx#L1-L108(this comment)frontend/src/components/repository-lockdown-notice.test.tsx#L3-L80frontend/src/app/actions/event.ts#L18-L18frontend/src/routes/events/$id.tsx#L16-L16
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/repository-lockdown-notice.tsx` around lines 1 - 108,
Apply the mandated Prettier style across
frontend/src/components/repository-lockdown-notice.tsx lines 1-108 and
frontend/src/components/repository-lockdown-notice.test.tsx lines 3-80 by using
double-quoted strings/imports and semicolon-terminated statements; add the
missing semicolon to the interface member in frontend/src/app/actions/event.ts
line 18; and update the import in frontend/src/routes/events/$id.tsx line 16 to
use double quotes and a terminating semicolon.
Source: Coding guidelines
| export default function RepositoryLockdownNotice({ | ||
| repoLockDate, | ||
| lockedAt, | ||
| }: Readonly<RepositoryLockdownNoticeProps>) { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Rename the React component file to PascalCase.
repository-lockdown-notice.tsx should be RepositoryLockdownNotice.tsx; update the imports in frontend/src/routes/events/$id.tsx and frontend/src/components/repository-lockdown-notice.test.tsx accordingly. As per coding guidelines, "frontend/**/*.tsx: Use PascalCase filenames for React components, except use page.tsx and layout.tsx for Next.js App Router files."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/repository-lockdown-notice.tsx` around lines 36 - 39,
Rename the React component file containing RepositoryLockdownNotice to
RepositoryLockdownNotice.tsx, then update its imports in the events route and
repository-lockdown-notice test to reference the new PascalCase filename.
Source: Coding guidelines
Summary by CodeRabbit
New Features
Bug Fixes
Chores