Remove dynamic form builder and complete RoundProject→roundId migration
Major cleanup and schema migration: - Remove unused dynamic form builder system (ApplicationForm, ApplicationFormField, etc.) - Complete migration from RoundProject junction table to direct Project.roundId - Add sortOrder and entryNotificationType fields to Round model - Add country field to User model for mentor matching - Enhance onboarding with profile photo and country selection steps - Fix all TypeScript errors related to roundProjects references - Remove unused libraries (@radix-ui/react-toast, embla-carousel-react, vaul) Files removed: - admin/forms/* pages and related components - admin/onboarding/* pages - applicationForm.ts and onboarding.ts routers - Dynamic form builder Prisma models and enums Schema changes: - Removed ApplicationForm, ApplicationFormField, OnboardingStep, ApplicationFormSubmission, SubmissionFile models - Removed FormFieldType and SpecialFieldType enums - Added Round.sortOrder, Round.entryNotificationType - Added User.country Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,7 +121,7 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
|
||||
// Fetch existing tags for suggestions
|
||||
const { data: existingTags } = trpc.project.getTags.useQuery({
|
||||
roundId: project?.roundProjects?.[0]?.round?.id,
|
||||
roundId: project?.roundId ?? undefined,
|
||||
})
|
||||
|
||||
// Mutations
|
||||
@@ -167,7 +167,7 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
title: project.title,
|
||||
teamName: project.teamName || '',
|
||||
description: project.description || '',
|
||||
status: (project.roundProjects?.[0]?.status ?? 'SUBMITTED') as UpdateProjectForm['status'],
|
||||
status: (project.status ?? 'SUBMITTED') as UpdateProjectForm['status'],
|
||||
tags: project.tags || [],
|
||||
})
|
||||
}
|
||||
@@ -202,7 +202,7 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
teamName: data.teamName || null,
|
||||
description: data.description || null,
|
||||
status: data.status,
|
||||
roundId: project?.roundProjects?.[0]?.round?.id,
|
||||
roundId: project?.roundId ?? undefined,
|
||||
tags: data.tags,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ function MentorAssignmentContent({ projectId }: { projectId: string }) {
|
||||
<p className="text-sm text-muted-foreground">{project.mentorAssignment!.mentor.email}</p>
|
||||
{project.mentorAssignment!.mentor.expertiseTags && project.mentorAssignment!.mentor.expertiseTags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{project.mentorAssignment!.mentor.expertiseTags.slice(0, 3).map((tag) => (
|
||||
{project.mentorAssignment!.mentor.expertiseTags.slice(0, 3).map((tag: string) => (
|
||||
<Badge key={tag} variant="secondary" className="text-xs">{tag}</Badge>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -140,18 +140,13 @@ function ProjectDetailContent({ projectId }: { projectId: string }) {
|
||||
/>
|
||||
<div className="space-y-1">
|
||||
<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>
|
||||
))
|
||||
{project.roundId ? (
|
||||
<Link
|
||||
href={`/admin/rounds/${project.roundId}`}
|
||||
className="hover:underline"
|
||||
>
|
||||
{project.round?.name ?? 'Round'}
|
||||
</Link>
|
||||
) : (
|
||||
<span>No round</span>
|
||||
)}
|
||||
@@ -160,8 +155,8 @@ function ProjectDetailContent({ projectId }: { projectId: string }) {
|
||||
<h1 className="text-2xl font-semibold tracking-tight">
|
||||
{project.title}
|
||||
</h1>
|
||||
<Badge variant={statusColors[project.roundProjects?.[0]?.status ?? 'SUBMITTED'] || 'secondary'}>
|
||||
{(project.roundProjects?.[0]?.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
<Badge variant={statusColors[project.status ?? 'SUBMITTED'] || 'secondary'}>
|
||||
{(project.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
</Badge>
|
||||
</div>
|
||||
{project.teamName && (
|
||||
@@ -513,7 +508,7 @@ function ProjectDetailContent({ projectId }: { projectId: string }) {
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href={`/admin/rounds/${project.roundProjects?.[0]?.round?.id}/assignments`}>
|
||||
<Link href={`/admin/rounds/${project.roundId}/assignments`}>
|
||||
Manage
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -121,7 +121,6 @@ function NewProjectPageContent() {
|
||||
})
|
||||
|
||||
createProject.mutate({
|
||||
programId: selectedRound!.programId,
|
||||
roundId: selectedRoundId,
|
||||
title: title.trim(),
|
||||
teamName: teamName.trim() || undefined,
|
||||
|
||||
@@ -359,7 +359,7 @@ export default function ProjectsPage() {
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{data.projects.map((project) => {
|
||||
const isEliminated = project.roundProjects?.[0]?.status === 'REJECTED'
|
||||
const isEliminated = project.status === 'REJECTED'
|
||||
return (
|
||||
<TableRow
|
||||
key={project.id}
|
||||
@@ -388,15 +388,15 @@ export default function ProjectsPage() {
|
||||
<TableCell>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<p>{project.roundProjects?.[0]?.round?.name ?? '-'}</p>
|
||||
{project.roundProjects?.[0]?.status === 'REJECTED' && (
|
||||
<p>{project.round?.name ?? '-'}</p>
|
||||
{project.status === 'REJECTED' && (
|
||||
<Badge variant="destructive" className="text-xs">
|
||||
Eliminated
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{project.program?.name}
|
||||
{project.round?.program?.name}
|
||||
</p>
|
||||
</div>
|
||||
</TableCell>
|
||||
@@ -409,9 +409,9 @@ export default function ProjectsPage() {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge
|
||||
variant={statusColors[project.roundProjects?.[0]?.status ?? 'SUBMITTED'] || 'secondary'}
|
||||
variant={statusColors[project.status ?? 'SUBMITTED'] || 'secondary'}
|
||||
>
|
||||
{(project.roundProjects?.[0]?.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
{(project.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="relative z-10 text-right">
|
||||
@@ -478,11 +478,11 @@ export default function ProjectsPage() {
|
||||
</CardTitle>
|
||||
<Badge
|
||||
variant={
|
||||
statusColors[project.roundProjects?.[0]?.status ?? 'SUBMITTED'] || 'secondary'
|
||||
statusColors[project.status ?? 'SUBMITTED'] || 'secondary'
|
||||
}
|
||||
className="shrink-0"
|
||||
>
|
||||
{(project.roundProjects?.[0]?.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
{(project.status ?? 'SUBMITTED').replace('_', ' ')}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription>{project.teamName}</CardDescription>
|
||||
@@ -493,8 +493,8 @@ export default function ProjectsPage() {
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="text-muted-foreground">Round</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{project.roundProjects?.[0]?.round?.name ?? '-'}</span>
|
||||
{project.roundProjects?.[0]?.status === 'REJECTED' && (
|
||||
<span>{project.round?.name ?? '-'}</span>
|
||||
{project.status === 'REJECTED' && (
|
||||
<Badge variant="destructive" className="text-xs">
|
||||
Eliminated
|
||||
</Badge>
|
||||
|
||||
@@ -72,7 +72,7 @@ export interface ProjectFilters {
|
||||
}
|
||||
|
||||
interface FilterOptions {
|
||||
rounds: Array<{ id: string; name: string; sortOrder: number; program: { name: string; year: number } }>
|
||||
rounds: Array<{ id: string; name: string; program: { name: string; year: number } }>
|
||||
countries: string[]
|
||||
categories: Array<{ value: string; count: number }>
|
||||
issues: Array<{ value: string; count: number }>
|
||||
|
||||
Reference in New Issue
Block a user