diff --git a/packages/api/src/routers/hackathon.ts b/packages/api/src/routers/hackathon.ts index bd5da5e..94aa956 100644 --- a/packages/api/src/routers/hackathon.ts +++ b/packages/api/src/routers/hackathon.ts @@ -267,6 +267,13 @@ export const hackathonRouter = createTRPCRouter({ const participants = await ctx.db!.query.hackathonParticipants.findMany({ where: eq(hackathonParticipants.hackathonId, input.hackathonId), + columns: { + id: true, + hackathonId: true, + userId: true, + teamId: true, + registrationStatus: true, + }, with: { user: { columns: { @@ -357,6 +364,13 @@ export const hackathonRouter = createTRPCRouter({ team: { with: { participants: { + columns: { + id: true, + hackathonId: true, + userId: true, + teamId: true, + registrationStatus: true, + }, with: { user: { columns: { diff --git a/packages/api/src/routers/judge.ts b/packages/api/src/routers/judge.ts index 00c134c..17750bf 100644 --- a/packages/api/src/routers/judge.ts +++ b/packages/api/src/routers/judge.ts @@ -389,6 +389,9 @@ export const judgeRouter = createTRPCRouter({ tableNumber: project.tableNumber, category: project.category, teamMembers: project.teamMembers, + tracks: project.tracks, + challenges: project.challenges, + isCreateX: project.isCreateX, }, totalScore, voteCount, @@ -554,6 +557,7 @@ export const judgeRouter = createTRPCRouter({ judgeId: z.string().uuid(), hackathonId: z.string().uuid(), isLead: z.boolean().optional(), + track: z.string().optional(), }) ) .mutation(async ({ ctx, input }) => { @@ -577,17 +581,28 @@ export const judgeRouter = createTRPCRouter({ judgeId: input.judgeId, hackathonId: input.hackathonId, isLead: input.isLead || false, + track: input.track, }) .returning(); - const projects = await ctx.db!.query.judgingProjects.findMany({ + // Fetch all projects for this hackathon + const allProjects = await ctx.db!.query.judgingProjects.findMany({ where: eq(judgingProjects.hackathonId, input.hackathonId), orderBy: [asc(judgingProjects.tableNumber)], }); - if (projects.length > 0) { + // Filter based on track if assigned + const assignedProjects = input.track + ? allProjects.filter((p) => { + const inTracks = p.tracks?.includes(input.track!) ?? false; + const inChallenges = p.challenges?.includes(input.track!) ?? false; + return inTracks || inChallenges; + }) + : allProjects; + + if (assignedProjects.length > 0) { await ctx.db!.insert(judgeQueue).values( - projects.map((p, idx) => ({ + assignedProjects.map((p, idx) => ({ judgeId: input.judgeId, hackathonId: input.hackathonId, projectId: p.id, @@ -609,6 +624,9 @@ export const judgeRouter = createTRPCRouter({ teamMembers: z.string().max(500).optional(), projectUrl: z.string().url().optional(), repoUrl: z.string().url().optional(), + tracks: z.array(z.string()).optional(), + challenges: z.array(z.string()).optional(), + isCreateX: z.boolean().default(false), }) ) .mutation(async ({ ctx, input }) => { @@ -631,6 +649,9 @@ export const judgeRouter = createTRPCRouter({ tableNumber: z.number().min(1), category: z.string().max(100).optional(), teamMembers: z.string().max(500).optional(), + tracks: z.array(z.string()).optional(), + challenges: z.array(z.string()).optional(), + isCreateX: z.boolean().default(false), }) ), }) @@ -685,11 +706,29 @@ export const judgeRouter = createTRPCRouter({ ) ); - let projects = await ctx.db!.query.judgingProjects.findMany({ + // Get judge assignment to check for track restriction + const assignment = await ctx.db!.query.judgeAssignments.findFirst({ + where: and( + eq(judgeAssignments.judgeId, input.judgeId), + eq(judgeAssignments.hackathonId, input.hackathonId) + ), + }); + + // Fetch all projects (or filter in query if possible, but JS filter matches assignToHackathon logic) + const allProjects = await ctx.db!.query.judgingProjects.findMany({ where: eq(judgingProjects.hackathonId, input.hackathonId), orderBy: [asc(judgingProjects.tableNumber)], }); + // Filter based on track if assigned + let projects = (assignment?.track) + ? allProjects.filter((p) => { + const inTracks = p.tracks?.includes(assignment.track!) ?? false; + const inChallenges = p.challenges?.includes(assignment.track!) ?? false; + return inTracks || inChallenges; + }) + : allProjects; + if (input.shuffle) { projects = shuffleArray(projects); } diff --git a/packages/db/src/schemas/hackathons.ts b/packages/db/src/schemas/hackathons.ts index 81456a3..aee7e5d 100644 --- a/packages/db/src/schemas/hackathons.ts +++ b/packages/db/src/schemas/hackathons.ts @@ -101,6 +101,10 @@ export const hackathonProjects = pgTable("hackathon_project", { name: text("name").notNull(), description: text("description").notNull(), technologies: text("technologies").array(), + tracks: text("tracks").array(), // Enum: GEN-AI, SPORTS, FINANCE, HEALTH, CYBER, NONE + challenges: text("challenges").array(), // Enum: AGG, ASSURANT, AWS, CAPONE, GROWTH, MLH_MONGODB, MLH_STREAMLIT, MLH_TECH, MLH_CLOUDFLARE, MLH_REACH_CAPITAL + isCreateX: boolean("is_create_x").default(false), + teamMembers: text("team_members").array(), // Store names/emails if not fully linked githubUrl: text("github_url"), demoUrl: text("demo_url"), videoUrl: text("video_url"), diff --git a/packages/db/src/schemas/judge.ts b/packages/db/src/schemas/judge.ts index f984314..a6718a9 100644 --- a/packages/db/src/schemas/judge.ts +++ b/packages/db/src/schemas/judge.ts @@ -28,6 +28,7 @@ export const judgeAssignments = pgTable("judge_assignment", { .references(() => hackathons.id, { onDelete: "cascade" }), assignedAt: timestamp("assigned_at").defaultNow().notNull(), isLead: boolean("is_lead").notNull().default(false), + track: text("track"), // Optional: if set, judge only sees projects in this track/challenge }, (table) => [ index("assignment_judge_id_idx").on(table.judgeId), index("assignment_hackathon_id_idx").on(table.hackathonId), @@ -44,6 +45,9 @@ export const judgingProjects = pgTable("judging_project", { description: text("description"), tableNumber: integer("table_number").notNull(), category: text("category"), // e.g., "AI", "Web3", "Health", "Sustainability" + tracks: text("tracks").array(), + challenges: text("challenges").array(), + isCreateX: boolean("is_create_x").default(false), teamMembers: text("team_members"), // comma-separated or JSON string projectUrl: text("project_url"), repoUrl: text("repo_url"), diff --git a/sites/mainweb/app/(portal)/admin-judging/page.tsx b/sites/mainweb/app/(portal)/admin-judging/page.tsx index 93c78de..197bcc2 100644 --- a/sites/mainweb/app/(portal)/admin-judging/page.tsx +++ b/sites/mainweb/app/(portal)/admin-judging/page.tsx @@ -227,6 +227,116 @@ export default function AdminResultsPage() { )} + {/* Projected Winners Section */} + {rankings && rankings.rankings.length > 0 && ( +
+ {i === 0 ? 'Grand Prize' : i === 1 ? '2nd Place' : '3rd Place'} +
+{w.totalScore}
+ID: {w.project.id.slice(-6).toUpperCase()}
+{track}
+{w.totalScore}
+{challenge}
+{w.totalScore}
+ {overallWinnerIds.has(w.project.id) && ( + Also Overall + )} +{project.teamMembers}
} + {project.teamMembers &&{project.teamMembers}
} + +{project.teamMembers}
} + {project.teamMembers &&{project.teamMembers}
} + +