feat: admin UI for finalist slot quotas + waitlist on grand-finale round
- New components/admin/grand-finale/finalist-slots-card: per-category quota editor with confirmed/pending counts, dirty-tracking, save button. Renders an empty editor for both Startup and Business Concept categories even when no quota exists yet. - New components/admin/grand-finale/waitlist-card: per-category ranked waitlist display with status badges + manual-promote AlertDialog (audit-logged via FINALIST_MANUAL_PROMOTE). - Round detail page: embeds both cards conditionally when roundType === 'LIVE_FINAL'. - New finalist router queries: listQuotas, listCategoryCounts (groupBy on category+status), listWaitlist (rank-ordered with project relation). Smoke-tested: setting Startup quota to 3 persists to DB; UI renders quota editor and waitlist card cleanly with empty state.
This commit is contained in:
@@ -92,6 +92,8 @@ import { ProjectStatesTable } from '@/components/admin/round/project-states-tabl
|
||||
import { FileRequirementsEditor } from '@/components/admin/round/file-requirements-editor'
|
||||
import { FilteringDashboard } from '@/components/admin/round/filtering-dashboard'
|
||||
import { MentoringRoundOverview } from '@/components/admin/round/mentoring-round-overview'
|
||||
import { FinalistSlotsCard } from '@/components/admin/grand-finale/finalist-slots-card'
|
||||
import { WaitlistCard } from '@/components/admin/grand-finale/waitlist-card'
|
||||
import { RankingDashboard } from '@/components/admin/round/ranking-dashboard'
|
||||
import { CoverageReport } from '@/components/admin/assignment/coverage-report'
|
||||
import { AssignmentPreviewSheet } from '@/components/admin/assignment/assignment-preview-sheet'
|
||||
@@ -583,6 +585,7 @@ export default function RoundDetailPage() {
|
||||
const isFiltering = round?.roundType === 'FILTERING'
|
||||
const isEvaluation = round?.roundType === 'EVALUATION'
|
||||
const isMentoring = round?.roundType === 'MENTORING'
|
||||
const isGrandFinale = round?.roundType === 'LIVE_FINAL'
|
||||
|
||||
// Mentor pool size — used by Round Details panel below to replace the
|
||||
// always-empty "Jury Group" row on MENTORING rounds.
|
||||
@@ -1481,6 +1484,14 @@ export default function RoundDetailPage() {
|
||||
{/* Mentoring-specific stats \u2014 only on MENTORING rounds */}
|
||||
{isMentoring && <MentoringRoundOverview roundId={roundId} />}
|
||||
|
||||
{/* Grand-finale logistics \u2014 only on LIVE_FINAL rounds */}
|
||||
{isGrandFinale && programId && (
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<FinalistSlotsCard programId={programId} />
|
||||
<WaitlistCard programId={programId} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Round Info + Project Breakdown */}
|
||||
<div className="grid gap-4 sm:grid-cols-2">
|
||||
<AnimatedCard index={2}>
|
||||
|
||||
Reference in New Issue
Block a user