diff --git a/prisma/migrations/20241015130402_change_unique_hacker/migration.sql b/prisma/migrations/20241015130402_change_unique_hacker/migration.sql new file mode 100644 index 0000000..346f697 --- /dev/null +++ b/prisma/migrations/20241015130402_change_unique_hacker/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - A unique constraint covering the columns `[userId,hackathonId]` on the table `Hacker` will be added. If there are existing duplicate values, this will fail. + +*/ +-- DropIndex +DROP INDEX "Hacker_userId_key"; + +-- CreateIndex +CREATE UNIQUE INDEX "Hacker_userId_hackathonId_key" ON "Hacker"("userId", "hackathonId"); diff --git a/prisma/migrations/20241015132032_remove_unique/migration.sql b/prisma/migrations/20241015132032_remove_unique/migration.sql new file mode 100644 index 0000000..052a8bf --- /dev/null +++ b/prisma/migrations/20241015132032_remove_unique/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "Hacker_userId_hackathonId_key"; diff --git a/prisma/migrations/20241015134428_change_unique_hacker_to_composite/migration.sql b/prisma/migrations/20241015134428_change_unique_hacker_to_composite/migration.sql new file mode 100644 index 0000000..30dfc99 --- /dev/null +++ b/prisma/migrations/20241015134428_change_unique_hacker_to_composite/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - A unique constraint covering the columns `[userId,hackathonId]` on the table `Hacker` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "Hacker_userId_hackathonId_key" ON "Hacker"("userId", "hackathonId"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f1d60a0..8a88646 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -41,7 +41,7 @@ model User { forgotPasswordLastRequest DateTime? image String? accounts Account[] - hacker Hacker? + hacker Hacker[] organizer Organizer? sponsor Sponsor? } @@ -70,7 +70,7 @@ model Hackathon { model Hacker { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) - userId Int @unique + userId Int team Team? @relation(fields: [teamId], references: [id]) ownedTeam Team? @relation(name: "TeamOwner") teamId Int? @@ -80,6 +80,7 @@ model Hacker { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt travelReimbursementRequest TravelReimbursementRequest? + @@unique([userId, hackathonId], name: "hackerApplication") } model Team { diff --git a/src/app/application/form/step/[stepId]/page.tsx b/src/app/application/form/step/[stepId]/page.tsx index db295df..724c149 100644 --- a/src/app/application/form/step/[stepId]/page.tsx +++ b/src/app/application/form/step/[stepId]/page.tsx @@ -3,6 +3,8 @@ import ApplicationFormStep from "@/scenes/ApplicationFormStep/ApplicationFormSte import getApplicationFormStep from "@/server/getters/application/applicationFormStep"; import { Metadata } from "next"; import requireNonOrganizer from "@/services/helpers/requireNonOrganizer"; +import getActiveHackathonId from "@/server/getters/getActiveHackathonId"; +import { prisma } from "@/services/prisma"; export const metadata: Metadata = { title: "Application Form", @@ -14,8 +16,14 @@ const ApplicationFormStepPage = async ({ params: { stepId: string }; }) => { await requireNonOrganizer(); + const hackathonId = await getActiveHackathonId(prisma); + if (!hackathonId) { + return null; + } + const applicationFormStepData = await getApplicationFormStep( - Number(params.stepId) + Number(params.stepId), + hackathonId ); return ( step.isCompleted) && session.emailVerified; // Get list of all free tables if user doesn't have table assigned - const tableCode = user.hacker?.team?.table?.code; + const hacker = user.hacker.find((h) => h.hackathonId === hackathonId); + const tableCode = hacker?.team?.table?.code; let freeTables = [] as string[]; if (!tableCode) { const tables = await prisma.table.findMany({ @@ -217,7 +219,8 @@ const getApplicationData = async ({ steps, canSubmit, hackathonName: hackathon.name, - tableCode: user.hacker?.team?.table?.code, + tableCode: user.hacker.find((h) => h.hackathonId === hackathonId)?.team + ?.table?.code, freeTables, }, }; diff --git a/src/server/getters/application/applicationFormStep.ts b/src/server/getters/application/applicationFormStep.ts index ac62c68..62ecd9e 100644 --- a/src/server/getters/application/applicationFormStep.ts +++ b/src/server/getters/application/applicationFormStep.ts @@ -21,7 +21,8 @@ export type ApplicationFormStepData = { }; const getApplicationFormStep = async ( - stepId: number + stepId: number, + hackathonId: number ): Promise => { const session = await getServerSession(authOptions); @@ -38,9 +39,10 @@ const getApplicationFormStep = async ( }; } - const hacker = await prisma.hacker.findUnique({ + const hacker = await prisma.hacker.findFirst({ where: { userId: session.id, + hackathonId: hackathonId, }, }); diff --git a/src/server/services/helpers/applications/isApplicationComplete.ts b/src/server/services/helpers/applications/isApplicationComplete.ts index fc64e47..0898db2 100644 --- a/src/server/services/helpers/applications/isApplicationComplete.ts +++ b/src/server/services/helpers/applications/isApplicationComplete.ts @@ -41,7 +41,36 @@ const isApplicationComplete = async ( }, }); + const application = await prisma.application.findUnique({ + where: { + id: applicationId, + }, + select: { + id: true, + hacker: { + select: { + hackathonId: true, + }, + }, + formValues: { + select: { + fieldId: true, + value: true, + }, + }, + }, + }); + + if (!application || !application.hacker) { + throw new Error("Application or hacker not found"); + } + + const { hackathonId } = application.hacker; + const stepsDb = await prisma.applicationFormStep.findMany({ + where: { + hackathonId, + }, select: { formFields: { select: { diff --git a/src/server/services/helpers/auth/requireHackerSession.ts b/src/server/services/helpers/auth/requireHackerSession.ts index 3cbe181..007cf37 100644 --- a/src/server/services/helpers/auth/requireHackerSession.ts +++ b/src/server/services/helpers/auth/requireHackerSession.ts @@ -3,6 +3,7 @@ import "server-only"; import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { prisma } from "@/services/prisma"; +import getActiveHackathonId from "@/server/getters/getActiveHackathonId"; type RequireHackerSessionOptions = { verified?: boolean; @@ -20,10 +21,13 @@ const requireHackerSession = async ({ throw new Error("User email not verified"); } - const hacker = await prisma.hacker.findUnique({ + const hacker = await prisma.hacker.findFirst({ where: { userId: session.id, }, + orderBy: { + createdAt: "desc", + }, }); if (!hacker) {