From c90f0c7a162dea39c64cae153f9a787ddb35e42b Mon Sep 17 00:00:00 2001 From: Andrew Chuang Saladin Date: Mon, 17 Feb 2025 23:17:10 -0500 Subject: [PATCH 1/3] Added events.ts --- src/server/api/events.ts | 121 +++++++++++++++++++++++++++++++++++++++ src/server/index.ts | 4 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/server/api/events.ts diff --git a/src/server/api/events.ts b/src/server/api/events.ts new file mode 100644 index 0000000..5ae54b0 --- /dev/null +++ b/src/server/api/events.ts @@ -0,0 +1,121 @@ +import { db } from "@/server/db/db"; +import * as Schema from "@/server/db/tables"; +import { createErrorResponse } from "@shared/utils"; +import { and, eq, gte, like, lte } from "drizzle-orm"; +import { Hono } from "hono"; + +const eventRoutes = new Hono(); + +// Fetch all events +eventRoutes.get("/events/all", async (c) => { + try { + const result = await db.select().from(Schema.events); + return c.json(result); + } catch (error) { + console.log(error); + return createErrorResponse(c, "MISSING_EVENT", "Cannot fetch events", 400); + } +}); + +// Fetch events between a start and end date +eventRoutes.get("/events", async (c) => { + try { + // Collect startDate and endDate + const startDateStr = c.req.query("start_date"); + const endDateStr = c.req.query("end_date"); + if (!startDateStr || !endDateStr) { + return createErrorResponse(c, "", "Start and end dates are required", 400); + } + + // Parse startDare and endDate into Date objects + const startDate = new Date(startDateStr); + const endDate = new Date(endDateStr); + + // Validate the Date format + if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { + return createErrorResponse(c, "", "Invalid date format", 400); + } + + const eventsData = await db + .select() + .from(Schema.events) + .where(and(lte(Schema.events.start_time, endDate), gte(Schema.events.end_time, startDate))); + return c.json(eventsData); + } catch (error) { + if (error) return createErrorResponse(c, "FETCH_EVENTS_ERROR", error.toString(), 500); + } +}); + +// Fetch event by ID +eventRoutes.get("/events/:eventID", async (c) => { + try { + const eventID = c.req.param("eventID"); + if (!eventID) { + return createErrorResponse(c, "MISSING_EVENT_ID", "Event Id required", 400); + } + const result = await db.select().from(Schema.events).where(eq(Schema.events.id, eventID)).limit(1); + if (result.length === 0) { + return createErrorResponse(c, "EVENT_NOT_FOUND", "Event not found", 404); + } + return c.json(result[0]); + } catch (error) { + if (error) return createErrorResponse(c, "FETCH_EVENT_ERROR", error.toString(), 500); + } +}); + +// Fetch event by name +eventRoutes.get("/events/search/:name", async (c) => { + try { + const searchName = c.req.param("name"); + console.log(searchName); + const result = await db + .select({ resEventIDs: Schema.events.id }) + .from(Schema.events) + .where(like(Schema.events.name, `%${searchName}%`)); // Approximate search + const eventIDs = result.map((row) => row.resEventIDs); + return c.json(eventIDs); + } catch (error) { + if (error) return createErrorResponse(c, "SEARCH_EVENTS_ERROR", error.toString(), 500); + } +}); + +// Add event +eventRoutes.post("/events/add", async (c) => { + try { + const eventData = await c.req.json(); + const newEvent = await db + .insert(Schema.events) + .values({ + ...eventData, + }) + .returning(); + return c.json(`Inserted event with ID: ${newEvent[0].id}`); + } catch (error) { + if (error) return createErrorResponse(c, "ADD_EVENT_ERROR", error.toString(), 500); + } +}); + +// Update event +eventRoutes.post("/events/update", async (c) => { + try { + const body = await c.req.json(); + const { id, ...update } = body; + if (!id) { + return createErrorResponse(c, "MISSING_EVENT_ID", "Event ID required", 400); + } + const updatedEvent = await db + .update(Schema.events) + .set({ + ...update, + timeUpdated: new Date(), + lastUpdateDate: new Date(), + }) + .where(eq(Schema.events.id, id)) + .returning(); + return c.json(`Updated event with ID: ${updatedEvent[0].id}`); + } catch (error) { + if (error) return createErrorResponse(c, "UPDATE_EVENT_ERROR", error.toString(), 500); + } +}); + +export default eventRoutes; diff --git a/src/server/index.ts b/src/server/index.ts index fee8ed2..a82c01c 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -4,6 +4,7 @@ import authRoutes from "@api/auth"; import blogRoutes from "@api/blogs"; import contactRoutes from "@api/contact"; import emailRoutes from "@api/email"; +import eventRoutes from "@api/events"; import profileRoutes from "@api/profile"; import saseRoutes from "@api/saseInfo"; import tagRoutes from "@api/tags"; @@ -41,4 +42,5 @@ app .route("/api", authRoutes) .route("/api", emailRoutes) .route("/api", profileRoutes) - .route("/api", contactRoutes); + .route("/api", contactRoutes) + .route("/api", eventRoutes); From 63ab14d701cf1bd0e146de531ea973c36353bb89 Mon Sep 17 00:00:00 2001 From: Andrew Chuang Saladin Date: Tue, 18 Feb 2025 19:50:32 -0500 Subject: [PATCH 2/3] Removed console logs --- src/server/api/events.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/server/api/events.ts b/src/server/api/events.ts index 5ae54b0..b99b7b8 100644 --- a/src/server/api/events.ts +++ b/src/server/api/events.ts @@ -11,16 +11,15 @@ eventRoutes.get("/events/all", async (c) => { try { const result = await db.select().from(Schema.events); return c.json(result); - } catch (error) { - console.log(error); + } catch { return createErrorResponse(c, "MISSING_EVENT", "Cannot fetch events", 400); } }); -// Fetch events between a start and end date +// Fetch events between a start and end date (inclusive of partial overlaps) eventRoutes.get("/events", async (c) => { try { - // Collect startDate and endDate + // Collect startDate and endDate in UTC format const startDateStr = c.req.query("start_date"); const endDateStr = c.req.query("end_date"); if (!startDateStr || !endDateStr) { @@ -33,7 +32,7 @@ eventRoutes.get("/events", async (c) => { // Validate the Date format if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { - return createErrorResponse(c, "", "Invalid date format", 400); + return createErrorResponse(c, "DATE_FORMAT_INVALID", "Invalid date format", 400); } const eventsData = await db @@ -63,11 +62,10 @@ eventRoutes.get("/events/:eventID", async (c) => { } }); -// Fetch event by name +// Fetch event ID by name eventRoutes.get("/events/search/:name", async (c) => { try { const searchName = c.req.param("name"); - console.log(searchName); const result = await db .select({ resEventIDs: Schema.events.id }) .from(Schema.events) From 9c99246545c8d13ba61f9e6353f83aaea696f370 Mon Sep 17 00:00:00 2001 From: Andrew Chuang Saladin Date: Fri, 21 Feb 2025 00:16:03 -0500 Subject: [PATCH 3/3] Consolidated and fixed routes --- src/server/api/events.ts | 132 +++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 55 deletions(-) diff --git a/src/server/api/events.ts b/src/server/api/events.ts index b99b7b8..2107047 100644 --- a/src/server/api/events.ts +++ b/src/server/api/events.ts @@ -6,31 +6,20 @@ import { Hono } from "hono"; const eventRoutes = new Hono(); -// Fetch all events -eventRoutes.get("/events/all", async (c) => { - try { - const result = await db.select().from(Schema.events); - return c.json(result); - } catch { - return createErrorResponse(c, "MISSING_EVENT", "Cannot fetch events", 400); - } -}); - -// Fetch events between a start and end date (inclusive of partial overlaps) +// Fetch events between a start and end date eventRoutes.get("/events", async (c) => { try { - // Collect startDate and endDate in UTC format const startDateStr = c.req.query("start_date"); const endDateStr = c.req.query("end_date"); + if (!startDateStr || !endDateStr) { - return createErrorResponse(c, "", "Start and end dates are required", 400); + const result = await db.select().from(Schema.events); + return c.json(result); } - // Parse startDare and endDate into Date objects const startDate = new Date(startDateStr); const endDate = new Date(endDateStr); - // Validate the Date format if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { return createErrorResponse(c, "DATE_FORMAT_INVALID", "Invalid date format", 400); } @@ -41,79 +30,112 @@ eventRoutes.get("/events", async (c) => { .where(and(lte(Schema.events.start_time, endDate), gte(Schema.events.end_time, startDate))); return c.json(eventsData); } catch (error) { - if (error) return createErrorResponse(c, "FETCH_EVENTS_ERROR", error.toString(), 500); + if (error) return createErrorResponse(c, "MISSING_EVENT", error.toString(), 500); } }); -// Fetch event by ID -eventRoutes.get("/events/:eventID", async (c) => { +// Add event +eventRoutes.post("/events", async (c) => { try { - const eventID = c.req.param("eventID"); - if (!eventID) { - return createErrorResponse(c, "MISSING_EVENT_ID", "Event Id required", 400); + const body = await c.req.json(); + + const requiredFields = ["name", "location", "start_time", "end_time"]; + for (const field of requiredFields) { + if (!body[field]) { + return createErrorResponse(c, "MISSING_REQUIRED_FIELD", `Field '${field}' is required`, 400); + } } - const result = await db.select().from(Schema.events).where(eq(Schema.events.id, eventID)).limit(1); - if (result.length === 0) { - return createErrorResponse(c, "EVENT_NOT_FOUND", "Event not found", 404); + + const startTime = new Date(body.start_time); + const endTime = new Date(body.end_time); + if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) { + return createErrorResponse(c, "TIME_FORMAT_INVALID", "Invalid start_time or end_time format", 400); } - return c.json(result[0]); - } catch (error) { - if (error) return createErrorResponse(c, "FETCH_EVENT_ERROR", error.toString(), 500); - } -}); -// Fetch event ID by name -eventRoutes.get("/events/search/:name", async (c) => { - try { - const searchName = c.req.param("name"); const result = await db - .select({ resEventIDs: Schema.events.id }) - .from(Schema.events) - .where(like(Schema.events.name, `%${searchName}%`)); // Approximate search - const eventIDs = result.map((row) => row.resEventIDs); - return c.json(eventIDs); - } catch (error) { - if (error) return createErrorResponse(c, "SEARCH_EVENTS_ERROR", error.toString(), 500); - } -}); - -// Add event -eventRoutes.post("/events/add", async (c) => { - try { - const eventData = await c.req.json(); - const newEvent = await db .insert(Schema.events) .values({ - ...eventData, + ...body, + start_time: startTime, + end_time: endTime, }) .returning(); - return c.json(`Inserted event with ID: ${newEvent[0].id}`); + + return c.json({ + message: `Inserted event with ID: ${result[0].id}`, + data: result[0], + }); } catch (error) { - if (error) return createErrorResponse(c, "ADD_EVENT_ERROR", error.toString(), 500); + if (error) return createErrorResponse(c, "ADD_BLOG_ERROR", error.toString(), 500); } }); // Update event -eventRoutes.post("/events/update", async (c) => { +eventRoutes.patch("/events", async (c) => { try { const body = await c.req.json(); const { id, ...update } = body; if (!id) { return createErrorResponse(c, "MISSING_EVENT_ID", "Event ID required", 400); } + const existingEvent = await db.select().from(Schema.events).where(eq(Schema.events.id, id)).get(); + if (!existingEvent) { + return createErrorResponse(c, "EVENT_NOT_FOUND", `No event with ID ${id}`, 404); + } + const startTime = new Date(body.start_time); + const endTime = new Date(body.end_time); + if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) { + return createErrorResponse(c, "TIME_FORMAT_INVALID", "Invalid start_time or end_time format", 400); + } const updatedEvent = await db .update(Schema.events) .set({ ...update, - timeUpdated: new Date(), - lastUpdateDate: new Date(), + start_time: startTime, + end_time: endTime, + time_updated: new Date(), }) .where(eq(Schema.events.id, id)) .returning(); - return c.json(`Updated event with ID: ${updatedEvent[0].id}`); + return c.json({ + message: `Updated event with ID: ${updatedEvent[0].id}`, + data: updatedEvent[0], + }); } catch (error) { if (error) return createErrorResponse(c, "UPDATE_EVENT_ERROR", error.toString(), 500); } }); +// Fetch event by ID +eventRoutes.get("/events/:eventID", async (c) => { + try { + const eventID = c.req.param("eventID"); + if (!eventID) { + return createErrorResponse(c, "MISSING_EVENT_ID", "Event Id required", 400); + } + const result = await db.select().from(Schema.events).where(eq(Schema.events.id, eventID)).limit(1); + if (result.length === 0) { + return createErrorResponse(c, "EVENT_NOT_FOUND", "Event not found", 404); + } + return c.json(result[0]); + } catch (error) { + if (error) return createErrorResponse(c, "FETCH_EVENT_ERROR", error.toString(), 500); + } +}); + +// Fetch event ID by name +eventRoutes.get("/events/search/:name", async (c) => { + try { + const searchName = c.req.param("name"); + const result = await db + .select({ resEventIDs: Schema.events.id }) + .from(Schema.events) + .where(like(Schema.events.name, `%${searchName}%`)); // Approximate search + const eventIDs = result.map((row) => row.resEventIDs); + return c.json(eventIDs); + } catch (error) { + if (error) return createErrorResponse(c, "SEARCH_EVENTS_ERROR", error.toString(), 500); + } +}); + export default eventRoutes;