diff --git a/api/src/routes/loa.ts b/api/src/routes/loa.ts index 45d48cc..4c9bc82 100644 --- a/api/src/routes/loa.ts +++ b/api/src/routes/loa.ts @@ -53,6 +53,18 @@ router.get("/me", async (req: Request, res: Response) => { } }) +//get my LOA history +router.get("/history", async (req: Request, res: Response) => { + const user = req.user.id; + try { + const result = await getUserLOA(user); + res.status(200).json(result) + } catch (error) { + console.error(error); + res.status(500).send(error); + } +}) + router.get('/all', async (req, res) => { try { const result = await getAllLOA(); @@ -128,7 +140,7 @@ router.get('/policy', async (req: Request, res: Response) => { if (output.ok) { const out = await output.json(); - res.status(200).json(out.markdown); + res.status(200).json(out.html); } else { console.log("BAD"); res.sendStatus(500); diff --git a/api/src/services/loaService.ts b/api/src/services/loaService.ts index 1446724..19e789e 100644 --- a/api/src/services/loaService.ts +++ b/api/src/services/loaService.ts @@ -32,7 +32,23 @@ export async function getAllLOA(page = 1, pageSize = 20): Promise } export async function getUserLOA(userId: number): Promise { - const result: LOARequest[] = await pool.query("SELECT * FROM leave_of_absences WHERE member_id = ?", [userId]) + const result: LOARequest[] = await pool.query(` + SELECT loa.*, members.name, t.name AS type_name + FROM leave_of_absences AS loa + LEFT JOIN members ON loa.member_id = members.id + LEFT JOIN leave_of_absences_types AS t ON loa.type_id = t.id + WHERE member_id = ? + ORDER BY + CASE + WHEN loa.closed IS NULL + AND NOW() > COALESCE(loa.extended_till, loa.end_date) THEN 1 + WHEN loa.closed IS NULL + AND NOW() BETWEEN loa.start_date AND COALESCE(loa.extended_till, loa.end_date) THEN 2 + WHEN loa.closed IS NULL AND NOW() < loa.start_date THEN 3 + WHEN loa.closed IS NOT NULL THEN 4 + END, + loa.start_date DESC + `, [userId]) return result; } @@ -67,7 +83,7 @@ export async function closeLOA(id: number, closer: number) { export async function getLOAbyID(id: number): Promise { let res = await pool.query(`SELECT * FROM leave_of_absences WHERE id = ?`, [id]); console.log(res); - if (res.length == 1) + if (res.length != 1) throw new Error(`LOA with id ${id} not found`); return res[0]; } diff --git a/ui/src/api/loa.ts b/ui/src/api/loa.ts index fc85bb3..f8ba82b 100644 --- a/ui/src/api/loa.ts +++ b/ui/src/api/loa.ts @@ -72,6 +72,23 @@ export function getAllLOAs(): Promise { }); } +export function getMyLOAs(): Promise { + return fetch(`${addr}/loa/history`, { + method: "GET", + credentials: 'include', + headers: { + "Content-Type": "application/json", + }, + }).then((res) => { + if (res.ok) { + return res.json(); + } else { + return []; + } + }); + +} + export async function getLoaTypes(): Promise { const res = await fetch(`${addr}/loa/types`, { method: "GET", diff --git a/ui/src/assets/base.css b/ui/src/assets/base.css index 0814dcd..b29a3bb 100644 --- a/ui/src/assets/base.css +++ b/ui/src/assets/base.css @@ -165,4 +165,76 @@ body { @apply bg-background text-foreground; } +} + +/* Root container */ +.ListRendererV2-container { + font-family: var(--font-sans, system-ui), sans-serif; + color: var(--foreground); + line-height: 1.45; + max-width: 760px; + margin: 0 auto; + font-size: 0.9rem; +} + +/* Headers */ +.ListRendererV2-container h4 { + margin: 0.9rem 0 0.4rem 0; + font-weight: 600; + line-height: 1.35; + font-size: 1.05rem; + color: var(--foreground); + /* PURE WHITE */ +} + +.ListRendererV2-container h5 { + margin: 0.9rem 0 0.4rem 0; + font-weight: 600; + line-height: 1.35; + font-size: 0.95rem; + color: var(--foreground); + /* Still white (change to muted if desired) */ +} + +/* Lists */ +.ListRendererV2-container ul { + list-style-type: disc; + margin-left: 1.1rem; + margin-bottom: 0.6rem; + padding-left: 0.6rem; + color: var(--muted-foreground); + /* dim text */ +} + +/* Nested lists */ +.ListRendererV2-container ul ul { + list-style-type: circle; + margin-left: 0.9rem; +} + +/* List items */ +.ListRendererV2-container li { + margin: 0.15rem 0; + padding-left: 0.1rem; + color: var(--muted-foreground); +} + +/* Bullet color */ +.ListRendererV2-container li::marker { + color: var(--muted-foreground); +} + +/* Inline elements */ +.ListRendererV2-container li p, +.ListRendererV2-container li span, +.ListRendererV2-container p { + display: inline; + margin: 0; + padding: 0; + color: var(--muted-foreground); +} + +/* Top-level spacing */ +.ListRendererV2-container>ul>li { + margin-top: 0.3rem; } \ No newline at end of file diff --git a/ui/src/components/loa/loaForm.vue b/ui/src/components/loa/loaForm.vue index 4e157bb..df4ddb0 100644 --- a/ui/src/components/loa/loaForm.vue +++ b/ui/src/components/loa/loaForm.vue @@ -90,7 +90,9 @@ onMounted(async () => { } try { if (!props.adminMode) { - policyString.value = await getLoaPolicy(); + let policy = await getLoaPolicy() as any; + policyString.value = policy; + policyRef.value.innerHTML = policyString.value; } } catch (error) { console.error(error); @@ -101,6 +103,8 @@ onMounted(async () => { resetForm({ values: { member_id: currentMember.value?.member_id } }); }); +const policyRef = ref(null); + const defaultPlaceholder = today(getLocalTimeZone()) const minEndDate = computed(() => { @@ -123,14 +127,10 @@ const maxEndDate = computed(() => { \ No newline at end of file diff --git a/ui/src/pages/SubmitLOA.vue b/ui/src/pages/SubmitLOA.vue index 1bed54a..e34dc4c 100644 --- a/ui/src/pages/SubmitLOA.vue +++ b/ui/src/pages/SubmitLOA.vue @@ -2,6 +2,8 @@ import LoaForm from '@/components/loa/loaForm.vue'; import { useUserStore } from '@/stores/user'; import { Member } from '@/api/member'; +import LoaList from '@/components/loa/loaList.vue'; +import { ref } from 'vue'; const userStore = useUserStore(); const user = userStore.user; @@ -13,8 +15,24 @@ const memberFull: Member = { status: null, status_date: null, }; + +const mode = ref<'submit' | 'view'>('submit') \ No newline at end of file