From 575455a0fc96a148bb9bf50125b99ce13f34fe0d Mon Sep 17 00:00:00 2001 From: ajdj100 Date: Fri, 5 Dec 2025 16:04:32 -0500 Subject: [PATCH] overhauled attendance visualization to be more useful for planning --- api/src/services/calendarService.ts | 14 +-- shared/types/calendar.ts | 1 + .../components/calendar/ViewCalendarEvent.vue | 107 +++++++++++++----- 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/api/src/services/calendarService.ts b/api/src/services/calendarService.ts index c88f671..7aa2cee 100644 --- a/api/src/services/calendarService.ts +++ b/api/src/services/calendarService.ts @@ -123,15 +123,9 @@ export async function setAttendanceStatus(memberID: number, eventID: number, sta } export async function getEventAttendance(eventID: number): Promise { - const sql = ` - SELECT - s.member_id, - s.status, - m.name AS member_name - FROM calendar_events_signups s - LEFT JOIN members m ON s.member_id = m.id - WHERE s.event_id = ? - `; - return await pool.query(sql, [eventID]); + const sql = "CALL `sp_GetCalendarEventSignups`(?)" + const res = await pool.query(sql, [eventID]); + console.log(res[0]); + return res[0]; } \ No newline at end of file diff --git a/shared/types/calendar.ts b/shared/types/calendar.ts index 526068f..5a62a8b 100644 --- a/shared/types/calendar.ts +++ b/shared/types/calendar.ts @@ -26,6 +26,7 @@ export interface CalendarSignup { eventID: number; status: CalendarAttendance; member_name?: string; + member_unit?: string; } export interface CalendarEventShort { diff --git a/ui/src/components/calendar/ViewCalendarEvent.vue b/ui/src/components/calendar/ViewCalendarEvent.vue index 9bcacc9..45bfa74 100644 --- a/ui/src/components/calendar/ViewCalendarEvent.vue +++ b/ui/src/components/calendar/ViewCalendarEvent.vue @@ -108,6 +108,67 @@ const isPast = computed(() => { return new Date() < end; }) +const attendanceTab = ref<"Alpha" | "Echo" | "Other">("Alpha"); +const attendanceList = computed(() => { + let out: CalendarSignup[] = []; + if (attendanceTab.value === 'Alpha') { + out = activeEvent.value.eventSignups?.filter((s) => s.member_unit === 'Alpha Company'); + } else if (attendanceTab.value === 'Echo') { + out = activeEvent.value.eventSignups?.filter((s) => s.member_unit === 'Echo Company') + } else { + out = activeEvent.value.eventSignups?.filter((s) => s.member_unit != 'Alpha Company' && s.member_unit != 'Echo Company') + } + + const statusOrder: Record = { + [CalendarAttendance.Attending]: 1, + [CalendarAttendance.Maybe]: 2, + [CalendarAttendance.NotAttending]: 3, + }; + + out.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]); + + return out; +}) + +const attendanceCounts = computed(() => { + const signups = activeEvent.value.eventSignups ?? []; + + return { + Alpha: signups.filter(s => s.member_unit === "Alpha Company").length, + Echo: signups.filter(s => s.member_unit === "Echo Company").length, + Other: signups.filter(s => + s.member_unit !== "Alpha Company" && + s.member_unit !== "Echo Company" + ).length, + }; +}); + +const statusColor = (status: CalendarAttendance) => { + switch (status) { + case CalendarAttendance.Attending: + return "text-success"; + case CalendarAttendance.Maybe: + return "text-yellow-600"; + case CalendarAttendance.NotAttending: + return "text-destructive"; + default: + return ""; + } +}; + +const displayStatus = (status: CalendarAttendance) => { + switch (status) { + case CalendarAttendance.Attending: + return "Attending"; + case CalendarAttendance.Maybe: + return "Maybe"; + case CalendarAttendance.NotAttending: + return "Declined"; + default: + return status; + } +}; + defineExpose({ forceReload }) @@ -188,46 +249,34 @@ defineExpose({ forceReload }) {{ activeEvent.description }}

- +

Attendance

- - - + + +
-
-
-

{{ person.member_name }}

+
+
+

Name

+

Status

-
-

{{ person.member_name }}

-
-
+ +

{{ person.member_name }}

+

+ {{ displayStatus(person.status) }} +

- - - \ No newline at end of file