From e2a147d1e29b91db21c897fff273e9fc8af34f2a Mon Sep 17 00:00:00 2001 From: ajdj100 Date: Fri, 17 Oct 2025 13:26:46 -0400 Subject: [PATCH] implemented calendar DB systems --- api/src/db.ts | 2 +- api/src/services/calendarService.ts | 102 ++++++++++++++++++++++++---- 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/api/src/db.ts b/api/src/db.ts index 40fde15..96158ba 100644 --- a/api/src/db.ts +++ b/api/src/db.ts @@ -16,4 +16,4 @@ const pool = mariadb.createPool({ ssl: false, }); -module.exports = pool; \ No newline at end of file +export default pool; \ No newline at end of file diff --git a/api/src/services/calendarService.ts b/api/src/services/calendarService.ts index 48ea943..d8bf4d3 100644 --- a/api/src/services/calendarService.ts +++ b/api/src/services/calendarService.ts @@ -4,33 +4,111 @@ import pool from '../db'; export interface CalendarEvent { id: number; name: string; - start: Date; // DATETIME → Date - end: Date; // DATETIME → Date + start: Date; // DATETIME -> Date + end: Date; // DATETIME -> Date location: string; - color: string; // CHAR(7) like "#3b82f6" + color: string; // 7 character hex string description?: string | null; creator?: number | null; // foreign key to members.id, nullable - cancelled: boolean; // TINYINT(1) → boolean - created_at: Date; // TIMESTAMP → Date - updated_at: Date; // TIMESTAMP → Date + cancelled: boolean; // TINYINT(1) -> boolean + created_at: Date; // TIMESTAMP -> Date + updated_at: Date; // TIMESTAMP -> Date } -export async function createEvent(eventObject) { +export type Attendance = 'attending' | 'maybe' | 'not_attending'; +export async function createEvent(eventObject: Omit) { + const sql = ` + INSERT INTO calendar_events + (name, start, end, location, color, description, creator) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + `; + const params = [ + eventObject.name, + eventObject.start, + eventObject.end, + eventObject.location, + eventObject.color, + eventObject.description ?? null, + eventObject.creator, + ]; + + const result = await pool.query(sql, params); + return { id: result.insertId, ...eventObject }; } -export async function updateEvent(eventObject) { +export async function updateEvent(eventObject: CalendarEvent) { + if (!eventObject.id) { + throw new Error("updateEvent: Missing event ID."); + } + const sql = ` + UPDATE calendar_events + SET + name = ?, + start = ?, + end = ?, + location = ?, + color = ?, + description = ?, + WHERE id = ? + `; + + const params = [ + eventObject.name, + eventObject.start, + eventObject.end, + eventObject.location, + eventObject.color, + eventObject.description ?? null, + eventObject.id + ]; + + await pool.query(sql, params); + return { success: true }; } -export async function cancelEvent(eventID) { - +export async function cancelEvent(eventID: number) { + const sql = ` + UPDATE calendar_events + SET cancelled = 1 + WHERE id = ? + `; + await pool.query(sql, [eventID]); + return { success: true }; } -export async function getShortEventsInRange(startDate, endDate) { +export async function getEventsInRange(startDate: Date, endDate: Date) { + const sql = ` + SELECT id, name, start, end, color + FROM calendar_events + WHERE start BETWEEN ? AND ? + ORDER BY start ASC + `; + return await pool.query(sql, [startDate, endDate]); } -export async function getEventDetailed(eventID) { +export async function getUpcomingEvents(date: Date, limit: number) { + const sql = ` + SELECT id, name, start, end, color + FROM calendar_events + WHERE start >= ? + AND cancelled = 0 + ORDER BY start ASC + LIMIT ? + `; + return await pool.query(sql, [date, limit]); +} + +export async function setAttendanceStatus(memberID: number, eventID: number, status: Attendance) { + const sql = ` + INSERT INTO calendar_events_signups (member_id, event_id, status) + VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE status = VALUES(status), updated_at = CURRENT_TIMESTAMP + `; + await pool.query(sql, [memberID, eventID, status]); + + return { success: true } } \ No newline at end of file