feat: award round reordering, assign-to-first-round, and applicant timeline for award tracks
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m22s
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m22s
- Add drag-and-drop round reordering on award detail Rounds tab (dnd-kit) - Replace "Open Voting" with "Assign to First Round" for SEPARATE_POOL awards - Add reorderAwardRounds mutation (two-phase transaction for unique constraint) - Add assignToFirstRound mutation (re-runnable, moves/creates ProjectRoundState) - Extend applicant timeline to show award-specific rounds for SEPARATE_POOL projects - Hide irrelevant main competition rounds when project is in award track - Prefix award round labels with award name in timeline Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1443,7 +1443,7 @@ export const applicantRouter = router({
|
||||
return { competitionName: null, entries: [] }
|
||||
}
|
||||
|
||||
// Get all rounds ordered by sortOrder
|
||||
// Get all rounds ordered by sortOrder (including award rounds in same competition)
|
||||
const rounds = await ctx.prisma.round.findMany({
|
||||
where: { competitionId: competition.id },
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
@@ -1454,6 +1454,8 @@ export const applicantRouter = router({
|
||||
status: true,
|
||||
windowOpenAt: true,
|
||||
windowCloseAt: true,
|
||||
specialAwardId: true,
|
||||
specialAward: { select: { name: true } },
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1482,12 +1484,29 @@ export const applicantRouter = router({
|
||||
const liveFinalRounds = rounds.filter((r) => r.roundType === 'LIVE_FINAL')
|
||||
const deliberationRounds = rounds.filter((r) => r.roundType === 'DELIBERATION')
|
||||
|
||||
// Check if this project is in any SEPARATE_POOL award track
|
||||
const projectAwardRoundIds = new Set(
|
||||
rounds.filter((r) => r.specialAwardId && stateMap.has(r.id)).map((r) => r.id)
|
||||
)
|
||||
const projectAwardIds = new Set(
|
||||
rounds.filter((r) => r.specialAwardId && stateMap.has(r.id)).map((r) => r.specialAwardId!)
|
||||
)
|
||||
const isInAwardTrack = projectAwardRoundIds.size > 0
|
||||
|
||||
// Process visible rounds: hide FILTERING, LIVE_FINAL, DELIBERATION always.
|
||||
// Also hide MENTORING unless the project is actually participating in it.
|
||||
// For award rounds: only show ones the project is in. For main rounds after
|
||||
// the split point: hide if project isn't in them and is in an award track.
|
||||
const visibleRounds = rounds.filter(
|
||||
(r) => {
|
||||
if (r.roundType === 'FILTERING' || r.roundType === 'LIVE_FINAL' || r.roundType === 'DELIBERATION') return false
|
||||
if (r.roundType === 'MENTORING' && !stateMap.has(r.id)) return false
|
||||
// Award round that project is NOT in → hide
|
||||
if (r.specialAwardId && !stateMap.has(r.id)) return false
|
||||
// Award round for a different award → hide
|
||||
if (r.specialAwardId && !projectAwardIds.has(r.specialAwardId)) return false
|
||||
// Main competition round where project has no state AND project is in award track → hide
|
||||
if (!r.specialAwardId && isInAwardTrack && !stateMap.has(r.id)) return false
|
||||
return true
|
||||
}
|
||||
)
|
||||
@@ -1520,7 +1539,7 @@ export const applicantRouter = router({
|
||||
|
||||
entries.push({
|
||||
id: round.id,
|
||||
label: round.name,
|
||||
label: round.specialAward ? `${round.specialAward.name}: ${round.name}` : round.name,
|
||||
roundType: round.roundType,
|
||||
status: round.status,
|
||||
windowOpenAt: round.windowOpenAt,
|
||||
|
||||
Reference in New Issue
Block a user