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..524dcbe 100644 --- a/ui/src/components/loa/loaList.vue +++ b/ui/src/components/loa/loaList.vue @@ -1,138 +1,141 @@ @@ -145,7 +148,7 @@ function setPage(pagenum: number) { + :max-value="props.adminMode ? toCalendarDate(targetEnd).add({ years: 1 }) : toCalendarDate(targetEnd).add({ months: 1 })" /> Quick Options 1 @@ -205,9 +208,10 @@ function setPage(pagenum: number) { - - Extend + {{ (post.extended_till !== null && !props.adminMode) ? 'Extend (Already Extended)' : 'Extend' }} {{ loaStatus(post) === 'Upcoming' ? @@ -256,7 +260,7 @@ function setPage(pagenum: number) { Extended to - {{post.extended_till ? formatDate(post.extended_till) : 'N/A' }} + {{ post.extended_till ? formatDate(post.extended_till) : 'N/A' }}
Quick Options
Extended to
- {{post.extended_till ? formatDate(post.extended_till) : 'N/A' }} + {{ post.extended_till ? formatDate(post.extended_till) : 'N/A' }}