From 86d069651cf1a4e28a14c22a354df98aeb3664d8 Mon Sep 17 00:00:00 2001 From: ajdj100 Date: Fri, 20 Feb 2026 00:10:08 -0500 Subject: [PATCH 1/2] Implemented self extension --- api/src/routes/loa.ts | 45 +++++- ui/src/api/loa.ts | 17 +++ ui/src/components/loa/loaList.vue | 242 +++++++++++++++--------------- 3 files changed, 184 insertions(+), 120 deletions(-) diff --git a/api/src/routes/loa.ts b/api/src/routes/loa.ts index a3e2206..f89fa5a 100644 --- a/api/src/routes/loa.ts +++ b/api/src/routes/loa.ts @@ -189,7 +189,50 @@ router.post('/adminCancel/:id', [requireRole(['17th Administrator', '17th HQ', ' }) // extend LOA -router.post('/extend/:id', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => { +router.post('/extend/:id', async (req: Request, res: Response) => { + const to: Date = req.body.to; + + const member = req.user.id; + + let LOA = await getLOAbyID(Number(req.params.id)); + if (!LOA) { + return res.status(404).send("LOA not found"); + } + + if (LOA.member_id !== member) { + return res.status(403).send("You do not have permission to extend this LOA"); + } + + if (LOA.extended_till !== null) { + return res.status(409).send("You must contact the administration team to extend your LOA again"); + } + + if (!to) { + return res.status(400).send("Extension length is required"); + } + + try { + await setLOAExtension(Number(req.params.id), to); + + audit.leaveOfAbsence('extended', { actorId: req.user.id, targetId: Number(req.params.id) }); + logger.info('app', 'LOA Extended', { extended_by: req.user.id, LOA: req.params.id }) + + res.sendStatus(200); + } catch (error) { + logger.error( + 'app', + 'Failed to extend LOA', + { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + } + ); + res.status(500).json(error); + } +}) + +// admin extend LOA +router.post('/extendAdmin/:id', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => { const to: Date = req.body.to; if (!to) { diff --git a/ui/src/api/loa.ts b/ui/src/api/loa.ts index ee2f82e..785a20e 100644 --- a/ui/src/api/loa.ts +++ b/ui/src/api/loa.ts @@ -169,6 +169,23 @@ export async function extendLOA(id: number, to: Date) { } }); + if (res.ok) { + return + } else { + throw new Error("Could not extend LOA"); + } +} + +export async function adminExtendLOA(id: number, to: Date) { + const res = await fetch(`${addr}/loa/extendAdmin/${id}`, { + method: "POST", + credentials: 'include', + body: JSON.stringify({ to }), + headers: { + "Content-Type": "application/json", + } + }); + if (res.ok) { return } else { diff --git a/ui/src/components/loa/loaList.vue b/ui/src/components/loa/loaList.vue index 3a43837..f010d70 100644 --- a/ui/src/components/loa/loaList.vue +++ b/ui/src/components/loa/loaList.vue @@ -1,138 +1,141 @@