From 1d1d82fa600e1198cf2d9c6e48000cd7b1e3dfd0 Mon Sep 17 00:00:00 2001 From: JamesFlare1212 Date: Mon, 12 May 2025 01:38:25 -0400 Subject: [PATCH] feat: new api endpoint, /v1/activity/category and /v1/activity/academicYear --- index.ts | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/index.ts b/index.ts index 8301695..0bdf38b 100644 --- a/index.ts +++ b/index.ts @@ -125,6 +125,8 @@ app.get('/', (_req: Request, res: Response) => { res.send('Welcome to the DSAS CCA API!

\ API Endpoints:
\ GET /v1/activity/list
\ + GET /v1/activity/category
\ + GET /v1/activity/academicYear
\ GET /v1/activity/:activityId (ID must be 1-4 digits)
\ GET /v1/staffs'); }); @@ -168,6 +170,90 @@ app.get('/v1/activity/list', async (_req: Request, res: Response) => { } }); +// Category endpoint +app.get('/v1/activity/category', async (_req: Request, res: Response) => { + try { + logger.info('Request received for /v1/activity/category'); + const activityKeys = await getAllActivityKeys(); + const categoryMap: Record = {}; + + if (!activityKeys || activityKeys.length === 0) { + logger.info('No activity keys found in Redis for categories.'); + return res.json({}); + } + + // Fetch all activity data in parallel + const allActivityDataPromises = activityKeys.map(async (key) => { + const activityId = key.substring(ACTIVITY_KEY_PREFIX.length); + return getActivityData(activityId); + }); + + const allActivities = await Promise.all(allActivityDataPromises); + + allActivities.forEach((activityData: ActivityData | null) => { + if (activityData && + activityData.category && + !activityData.error && + activityData.source !== 'api-fetch-empty') { + if (categoryMap[activityData.category]) { + categoryMap[activityData.category] = (categoryMap[activityData.category] ?? 0) + 1; + } else { + categoryMap[activityData.category] = 1; + } + } + }); + + logger.info(`Returning list of ${Object.keys(categoryMap).length} categories.`); + res.json(categoryMap); + + } catch (error) { + logger.error('Error in /v1/activity/category endpoint:', error); + res.status(500).json({ error: 'An internal server error occurred while generating category list.' }); + } +}); + +// Academic Year endpoint +app.get('/v1/activity/academicYear', async (_req: Request, res: Response) => { + try { + logger.info('Request received for /v1/activity/academicYear'); + const activityKeys = await getAllActivityKeys(); + const academicYearMap: Record = {}; + + if (!activityKeys || activityKeys.length === 0) { + logger.info('No activity keys found in Redis for academic years.'); + return res.json({}); + } + + // Fetch all activity data in parallel + const allActivityDataPromises = activityKeys.map(async (key) => { + const activityId = key.substring(ACTIVITY_KEY_PREFIX.length); + return getActivityData(activityId); + }); + + const allActivities = await Promise.all(allActivityDataPromises); + + allActivities.forEach((activityData: ActivityData | null) => { + if (activityData && + activityData.academicYear && + !activityData.error && + activityData.source !== 'api-fetch-empty') { + if (academicYearMap[activityData.academicYear]) { + academicYearMap[activityData.academicYear] = (academicYearMap[activityData.academicYear] ?? 0) + 1; + } else { + academicYearMap[activityData.academicYear] = 1; + } + } + }); + + logger.info(`Returning list of ${Object.keys(academicYearMap).length} academic years.`); + res.json(academicYearMap); + + } catch (error) { + logger.error('Error in /v1/activity/academicYear endpoint:', error); + res.status(500).json({ error: 'An internal server error occurred while generating academic year list.' }); + } +}); + // Single activity endpoint app.get('/v1/activity/:activityId', async (req: Request, res: Response) => { const { activityId } = req.params;