Decouple projects from rounds with RoundProject join table
Projects now exist at the program level instead of being locked to a single round. A new RoundProject join table enables many-to-many relationships with per-round status tracking. Rounds have sortOrder for configurable progression paths. - Add RoundProject model, programId on Project, sortOrder on Round - Migration preserves existing data (roundId -> RoundProject entries) - Update all routers to query through RoundProject join - Add assign/remove/advance/reorder round endpoints - Add Assign, Advance, Remove Projects dialogs on round detail page - Add round reorder controls (up/down arrows) on rounds list - Show all rounds on project detail page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -139,20 +139,29 @@ function ProjectDetailContent({ projectId }: { projectId: string }) {
|
||||
fallback="initials"
|
||||
/>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Link
|
||||
href={`/admin/rounds/${project.round.id}`}
|
||||
className="hover:underline"
|
||||
>
|
||||
{project.round.name}
|
||||
</Link>
|
||||
<div className="flex flex-wrap items-center gap-1 text-sm text-muted-foreground">
|
||||
{project.roundProjects?.length > 0 ? (
|
||||
project.roundProjects.map((rp, i) => (
|
||||
<span key={rp.round.id} className="flex items-center gap-1">
|
||||
{i > 0 && <span className="text-muted-foreground/50">/</span>}
|
||||
<Link
|
||||
href={`/admin/rounds/${rp.round.id}`}
|
||||
className="hover:underline"
|
||||
>
|
||||
{rp.round.name}
|
||||
</Link>
|
||||
</span>
|
||||
))
|
||||
) : (
|
||||
<span>No round</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<h1 className="text-2xl font-semibold tracking-tight">
|
||||
{project.title}
|
||||
</h1>
|
||||
<Badge variant={statusColors[project.status] || 'secondary'}>
|
||||
{project.status.replace('_', ' ')}
|
||||
<Badge variant={statusColors[project.roundProjects?.[0]?.status ?? 'SUBMITTED'] || 'secondary'}>
|
||||
{(project.roundProjects?.[0]?.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
</Badge>
|
||||
</div>
|
||||
{project.teamName && (
|
||||
@@ -504,7 +513,7 @@ function ProjectDetailContent({ projectId }: { projectId: string }) {
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href={`/admin/rounds/${project.roundId}/assignments`}>
|
||||
<Link href={`/admin/rounds/${project.roundProjects?.[0]?.round?.id}/assignments`}>
|
||||
Manage
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user