import { Request, Response } from "express"; import { createEvent, getEventAttendance, getEventDetails, getShortEventsInRange, setAttendanceStatus, setEventCancelled, updateEvent } from "../services/db/calendarService"; import { CalendarAttendance, CalendarEvent } from "@app/shared/types/calendar"; import { requireLogin, requireMemberState, requireRole } from "../middleware/auth"; import { MemberState } from "@app/shared/types/member"; import { logger } from "../services/logging/logger"; import { audit } from "../services/logging/auditLog"; const express = require('express'); const r = express.Router(); function addMonths(date: Date, months: number): Date { const d = new Date(date) d.setMonth(d.getMonth() + months) return d } //get calendar events paged, requires a query string with from= and to= as mariadb ISO strings r.get('/', async (req, res) => { try { const fromDate: string = req.query.from; const toDate: string = req.query.to; if (fromDate === undefined || toDate === undefined) { res.status(400).send("Missing required query parameters 'from' and 'to'"); return; } const events = await getShortEventsInRange(fromDate, toDate); res.status(200).json(events); } catch (error) { logger.error( 'app', 'Failed to get calendar events', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500).send('Error fetching calendar events'); } }); r.get('/upcoming', async (req, res) => { res.sendStatus(501); }) r.post('/:id/cancel', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => { let member = req.user.id; try { const eventID = Number(req.params.id); await setEventCancelled(eventID, true); audit.calendar('cancelled', { actorId: member, targetId: eventID }); logger.info('app', 'Calendar event cancelled', { event: eventID, user: req.user.id }) res.sendStatus(200); } catch (error) { logger.error( 'app', 'Failed to get cancel calendar event', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500).send('Error setting cancel status'); } }) r.post('/:id/uncancel', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => { let member = req.user.id; try { const eventID = Number(req.params.id); setEventCancelled(eventID, false); audit.calendar('un-cancelled', { actorId: member, targetId: eventID }); logger.info('app', 'Calendar event un-cancelled', { event: eventID, user: req.user.id }) res.sendStatus(200); } catch (error) { logger.error( 'app', 'Failed to uncancel calendar event', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500).send('Error setting cancel status'); } }) r.post('/:id/attendance', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => { try { let member = req.user.id; let event = Number(req.params.id); let state = req.query.state as CalendarAttendance; await setAttendanceStatus(member, event, state); audit.calendar('attendance_set', { actorId: member, targetId: event }, { attendanceState: state }); logger.info('app', 'Member set calendar event attendance', { event: event, user: req.user.id, state: state }) res.sendStatus(200); } catch (error) { logger.error( 'app', 'Failed to set attendance', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500).json(error); } }) //get event details r.get('/:id', async (req: Request, res: Response) => { try { const eventID: number = Number(req.params.id); let details: CalendarEvent = await getEventDetails(eventID); details.eventSignups = await getEventAttendance(eventID); res.status(200).json(details); } catch (error) { logger.error( 'app', 'Failed to get calendar event details', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500); } }) //post a new calendar event r.post('/', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => { try { const member = req.user.id; let event: CalendarEvent = req.body; event.creator_id = member; event.start = new Date(event.start); event.end = new Date(event.end); let eventID = await createEvent(event); audit.calendar('event_created', { actorId: member, targetId: eventID }); logger.info('app', 'Calendar event posted', { event: event.id, user: req.user.id }) res.sendStatus(200); } catch (error) { logger.error( 'app', 'Failed to create calendar event', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500).json(error); } }) r.put('/', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => { let member = req.user.id; try { let event: CalendarEvent = req.body; event.start = new Date(event.start); event.end = new Date(event.end); updateEvent(event); audit.calendar('event_updated', { actorId: member, targetId: event.id }); logger.info('app', 'Calendar event updated', { event: event.id, user: req.user.id }) res.sendStatus(200); } catch (error) { logger.error( 'app', 'Failed to update calendar event', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, } ); res.status(500).json(error); } }) export const calendarRouter = r;