diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts index 446f121..15ae4c8 100644 --- a/src/services/attendees/attendee-router.ts +++ b/src/services/attendees/attendee-router.ts @@ -42,26 +42,28 @@ attendeeRouter.get( } ); -// Check if a user email exists -attendeeRouter.get("/:email", async (req, res, next) => { - try { - const { email } = req.params; - - // Check if the user exists in the database - const userExists = await Database.ATTENDEES.exists({ email }); +attendeeRouter.get( + "/", + RoleChecker([Role.Enum.USER]), + async (req, res, next) => { + try { + const payload = res.locals.payload; + const userId = payload.userId; - if (!userExists) { - return { error: "DoesNotExist" }; - } + // Check if the user exists in the database + const user = await Database.ATTENDEES.findOne({ userId }); - const user = await Database.ATTENDEES.findOne({ - email, - }); + if (!user) { + return res + .status(StatusCodes.NOT_FOUND) + .json({ error: "UserNotFound" }); + } - return res.status(StatusCodes.OK).json(user); - } catch (error) { - next(error); + return res.status(StatusCodes.OK).json(user); + } catch (error) { + next(error); + } } -}); +); export default attendeeRouter; diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 358795d..2b7b0db 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -6,9 +6,7 @@ const AttendeeValidator = z.object({ userId: z.string(), name: z.string(), email: z.string().email(), - events: z.array(z.string()), - dietary_restrictions: z.string(), - priority_expiry: z.date().nullable().optional(), + dietaryRestrictions: z.string().array(), points: z.number().min(0).default(0), }); @@ -17,9 +15,7 @@ const AttendeeSchema = new mongoose.Schema({ userId: { type: String, required: true, unique: true }, name: { type: String, required: true }, email: { type: String, required: true, unique: true }, - events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }], - dietary_restrictions: { type: String, required: true }, - priority_expiry: { type: Date, default: null }, + dietaryRestrictions: [{ type: String, required: true }], points: { type: Number, default: 0 }, }); diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index ffbb31f..4da7327 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -5,6 +5,27 @@ import { Database } from "../../database"; const eventsRouter = Router(); +// Get current or next event based on current time +eventsRouter.get("/currentOrNext", async (req, res, next) => { + const currentTime = new Date(); + + try { + const event = await Database.EVENTS.findOne({ + startTime: { $gte: currentTime }, + }).sort({ startTime: 1 }); + + if (event) { + return res.status(StatusCodes.OK).json(event); + } else { + return res + .status(StatusCodes.NO_CONTENT) + .json({ error: "DoesNotExist" }); + } + } catch (error) { + next(error); + } +}); + eventsRouter.post("/", async (req, res, next) => { try { const validatedData = EventValidator.parse(req.body); diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 7789433..0d447f7 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -2,6 +2,8 @@ import { Schema } from "mongoose"; import { z } from "zod"; import { v4 as uuidv4 } from "uuid"; +export const EventType = z.enum(["A", "B", "C"]); + export const EventValidator = z.object({ eventId: z.coerce.string().optional(), name: z.string(), @@ -12,6 +14,7 @@ export const EventValidator = z.object({ isVirtual: z.boolean(), imageUrl: z.string().nullable().optional(), isVisible: z.boolean().default(false), + eventType: EventType, }); export const EventSchema = new Schema({ @@ -53,4 +56,9 @@ export const EventSchema = new Schema({ type: Boolean, default: false, }, + eventType: { + type: String, + required: true, + enum: EventType.Values, + }, }); diff --git a/src/services/registration/registration-router.ts b/src/services/registration/registration-router.ts index a2504e4..d2bff97 100644 --- a/src/services/registration/registration-router.ts +++ b/src/services/registration/registration-router.ts @@ -4,19 +4,16 @@ import { RegistrationValidator } from "./registration-schema"; import { Database } from "../../database"; import RoleChecker from "../../middleware/role-checker"; import { Role } from "../auth/auth-models"; +import { AttendeeValidator } from "../attendees/attendee-schema"; +import { registrationExists } from "./registration-utils"; const registrationRouter = Router(); // A database upsert operation to save registration mid-progress registrationRouter.post("/save", RoleChecker([]), async (req, res, next) => { try { - const registrationData = RegistrationValidator.parse(req.body); - - // Check if user already submitted registration before - const existingRegistration = await Database.REGISTRATION.findOne({ - userId: registrationData.userId, - hasSubmitted: true, - }); + const payload = res.locals.payload; + const existingRegistration = await registrationExists(payload.userId); if (existingRegistration) { return res.status(StatusCodes.CONFLICT).json({ @@ -24,6 +21,11 @@ registrationRouter.post("/save", RoleChecker([]), async (req, res, next) => { }); } + const registrationData = RegistrationValidator.parse({ + ...req.body, + userId: payload.userId, + }); + await Database.REGISTRATION.findOneAndUpdate( { userId: res.locals.payload.userId }, { @@ -41,10 +43,22 @@ registrationRouter.post("/save", RoleChecker([]), async (req, res, next) => { registrationRouter.post("/submit", RoleChecker([]), async (req, res, next) => { try { - const registrationData = RegistrationValidator.parse(req.body); + const payload = res.locals.payload; + const existingRegistration = await registrationExists(payload.userId); + + if (existingRegistration) { + return res.status(StatusCodes.CONFLICT).json({ + error: "AlreadySubmitted", + }); + } + + const registrationData = RegistrationValidator.parse({ + ...req.body, + userId: payload.userId, + }); await Database.REGISTRATION.findOneAndUpdate( - { userId: res.locals.payload.userId }, + { userId: payload.userId }, { ...registrationData, hasSubmitted: true, @@ -53,7 +67,7 @@ registrationRouter.post("/submit", RoleChecker([]), async (req, res, next) => { ); await Database.ROLES.findOneAndUpdate( - { userId: res.locals.payload.userId }, + { userId: payload.userId }, { $addToSet: { roles: Role.Values.USER, @@ -62,6 +76,14 @@ registrationRouter.post("/submit", RoleChecker([]), async (req, res, next) => { { upsert: true } ); + const attendeeData = AttendeeValidator.parse(registrationData); + + await Database.ATTENDEES.findOneAndUpdate( + { userId: payload.userId }, + attendeeData, + { upsert: true, setDefaultsOnInsert: true } + ); + return res.status(StatusCodes.OK).json(registrationData); } catch (error) { next(error); diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts index c2ebf44..bc5b381 100644 --- a/src/services/registration/registration-schema.ts +++ b/src/services/registration/registration-schema.ts @@ -32,7 +32,7 @@ const RegistrationSchema = new mongoose.Schema({ university: { type: String, required: true }, graduation: { type: String, default: null }, major: { type: String, default: null }, - dietaryRstrictions: { type: String, required: true }, + dietaryRestrictions: [{ type: String, required: true }], age: { type: Number, default: null }, gender: { type: String, default: null }, race: [{ type: String }], diff --git a/src/services/registration/registration-utils.ts b/src/services/registration/registration-utils.ts new file mode 100644 index 0000000..b28e301 --- /dev/null +++ b/src/services/registration/registration-utils.ts @@ -0,0 +1,9 @@ +import { Database } from "../../database"; + +export async function registrationExists(userId: string) { + // Check if user already submitted registration before + return Database.REGISTRATION.exists({ + userId: userId, + hasSubmitted: true, + }); +}