feat: multi-role jury fix, country flags, applicant deadline banner, timeline
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Fix project list returning empty for users with both SUPER_ADMIN and JURY_MEMBER roles (jury filter now skips admins) in project, assignment, and evaluation routers - Add CountryDisplay component showing flag emoji + name everywhere country is displayed (admin, observer, jury, mentor views — 17 files) - Add countdown deadline banner on applicant dashboard for INTAKE, SUBMISSION, and MENTORING rounds with live timer - Remove quick action buttons from applicant dashboard - Fix competition timeline sidebar: green dots/connectors only up to current round, yellow dot for current round, red connector into rejected round, grey after Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -202,13 +202,35 @@ export function CompetitionTimelineSidebar() {
|
||||
// Is this entry after the elimination point?
|
||||
const isAfterElimination = eliminationIndex >= 0 && index > eliminationIndex
|
||||
|
||||
// Is this the current round the project is in (regardless of round status)?
|
||||
const isCurrent = !!entry.projectState && entry.projectState !== 'PASSED' && entry.projectState !== 'COMPLETED' && entry.projectState !== 'REJECTED'
|
||||
// Is this the current round? Either has an active project state,
|
||||
// or is the first round the project hasn't passed yet (for seed data
|
||||
// where project states may be missing).
|
||||
const hasActiveProjectState = !!entry.projectState && entry.projectState !== 'PASSED' && entry.projectState !== 'COMPLETED' && entry.projectState !== 'REJECTED'
|
||||
const isCurrent = !isAfterElimination && (hasActiveProjectState || (
|
||||
!isPassed && !isRejected && !isCompleted &&
|
||||
data.entries.slice(0, index).every((prev) =>
|
||||
prev.projectState === 'PASSED' || prev.projectState === 'COMPLETED' ||
|
||||
prev.status === 'ROUND_CLOSED' || prev.status === 'ROUND_ARCHIVED'
|
||||
) && index > 0
|
||||
))
|
||||
|
||||
// Determine connector segment color (no icons, just colored lines)
|
||||
// Connector color: green up to and including the current round,
|
||||
// red leading into the rejected round, neutral after.
|
||||
let connectorColor = 'bg-border'
|
||||
if ((isPassed || isCompleted) && !isAfterElimination) connectorColor = 'bg-emerald-400'
|
||||
else if (isRejected) connectorColor = 'bg-destructive/30'
|
||||
const nextEntry = data.entries[index + 1]
|
||||
const nextIsRejected = nextEntry?.projectState === 'REJECTED'
|
||||
if (isAfterElimination) {
|
||||
connectorColor = 'bg-border'
|
||||
} else if (isRejected) {
|
||||
// From rejected round onward = neutral
|
||||
connectorColor = 'bg-border'
|
||||
} else if (nextIsRejected) {
|
||||
// Connector leading INTO the rejected round = red
|
||||
connectorColor = 'bg-destructive/40'
|
||||
} else if (isCompleted || isPassed) {
|
||||
// Rounds the project has passed through = green
|
||||
connectorColor = 'bg-emerald-400'
|
||||
}
|
||||
|
||||
// Dot inner content
|
||||
let dotInner: React.ReactNode = null
|
||||
@@ -222,7 +244,7 @@ export function CompetitionTimelineSidebar() {
|
||||
} else if (isGrandFinale && (isCompleted || isPassed)) {
|
||||
dotClasses = 'bg-yellow-500 border-2 border-yellow-500'
|
||||
dotInner = <Trophy className="h-3.5 w-3.5 text-white" />
|
||||
} else if (isCompleted || isPassed) {
|
||||
} else if (isPassed || (isCompleted && !isCurrent)) {
|
||||
dotClasses = 'bg-emerald-500 border-2 border-emerald-500'
|
||||
dotInner = <Check className="h-3.5 w-3.5 text-white" />
|
||||
} else if (isCurrent) {
|
||||
|
||||
Reference in New Issue
Block a user