implemented most of the viewing training reports UI

This commit is contained in:
2025-11-17 00:21:38 -05:00
parent 1d35fe1cf5
commit 1df4893c67
2 changed files with 71 additions and 10 deletions

View File

@@ -13,3 +13,14 @@ export async function getTrainingReports(): Promise<CourseEventSummary[]> {
throw new Error("Failed to load training reports");
}
}
export async function getTrainingReport(id: number): Promise<CourseEventDetails> {
const res = await fetch(`${addr}/courseEvent/${id}`);
if (res.ok) {
return await res.json() as Promise<CourseEventDetails>;
} else {
console.error("Something went wrong");
throw new Error("Failed to load training reports");
}
}

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { getTrainingReports } from '@/api/trainingReport';
import { getTrainingReport, getTrainingReports } from '@/api/trainingReport';
import { trainingReportSchema, courseEventAttendeeSchema } from '@shared/schemas/trainingReportSchema'
import { CourseEventDetails, CourseEventSummary } from '@shared/types/course';
import { CourseAttendee, CourseEventDetails, CourseEventSummary } from '@shared/types/course';
import { toTypedSchema } from '@vee-validate/zod';
import { onMounted, ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
import {
Table,
TableBody,
@@ -14,11 +14,28 @@ import {
TableHeader,
TableRow,
} from '@/components/ui/table'
import { Separator } from '@/components/ui/separator'
import { X } from 'lucide-vue-next';
const trainingReports = ref<CourseEventSummary[] | null>(null);
const loaded = ref(false);
const focusedTrainingReport = ref<CourseEventDetails | null>(null);
const focusedTrainingTrainees = computed<CourseAttendee[] | null>(() => {
if (focusedTrainingReport == null) return null;
return focusedTrainingReport.value.attendees.filter((attendee) => attendee.attendee_role_id == 2);
})
const focusedTrainingTrainers = computed<CourseAttendee[] | null>(() => {
if (focusedTrainingReport == null) return null;
return focusedTrainingReport.value.attendees.filter((attendee) => attendee.attendee_role_id != 2);
})
async function viewTrainingReport(id: number) {
focusedTrainingReport.value = await getTrainingReport(id);
}
async function closeTrainingReport() {
focusedTrainingReport.value = null;
}
onMounted(async () => {
trainingReports.value = await getTrainingReports();
@@ -27,8 +44,9 @@ onMounted(async () => {
</script>
<template>
<div class="max-w-5xl mx-auto">
<div>
<div class="max-w-7xl mx-auto flex">
<!-- training report list -->
<div class="px-4" :class="focusedTrainingReport == null ? 'w-full' : 'w-1/2'">
<Table>
<TableHeader>
<TableRow>
@@ -42,18 +60,50 @@ onMounted(async () => {
</TableRow>
</TableHeader>
<TableBody v-if="loaded">
<TableRow v-for="report in trainingReports" @click="console.log(report.event_id);">
<TableRow class="cursor-pointer" v-for="report in trainingReports" :key="report.event_id"
@click="viewTrainingReport(report.event_id);">
<TableCell class="font-medium">{{ report.course_name }}</TableCell>
<TableCell>{{ report.date }}</TableCell>
<TableCell class="text-right">{{ report.created_by === null ? "Unknown User" : report.created_by }}</TableCell>
<TableCell class="text-right">{{ report.created_by === null ? "Unknown User" : report.created_by
}}</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- view training report section -->
<div v-if="focusedTrainingReport != null" class="px-4 border-l w-1/2">
<div class="flex justify-between my-3">
<div class="flex gap-5">
<p>{{ focusedTrainingReport.course_name }}</p>
<p class="text-muted-foreground">{{ focusedTrainingReport.event_date }}</p>
</div>
<button @click="closeTrainingReport">
<X></X>
</button>
</div>
<div class="flex flex-col gap-5">
<!-- {{ focusedTrainingReport }} -->
<div>
DETAILS
<label>Trainers</label>
<div v-for="person in focusedTrainingTrainers" class="grid grid-cols-4 my-2">
<p>{{ person.attendee_id }}</p>
<p class="text-right px-5">{{ person.passed }}</p>
<p class="bg-muted p-2 rounded-lg min-h-[1lh] col-span-2 text-right">{{ person.remarks }}</p>
</div>
</div>
<div>
<label>Trainees</label>
<div v-for="person in focusedTrainingTrainees" class="grid grid-cols-4 my-2">
<p>{{ person.attendee_id }}</p>
<p class="text-right px-5">{{ person.passed }}</p>
<p class="bg-muted p-2 rounded-lg min-h-[1lh] col-span-2 text-right">{{ person.remarks }}</p>
</div>
</div>
<div>
<label>Remarks</label>
<p class="bg-muted p-2 rounded-lg min-h-24"> {{ focusedTrainingReport.remarks }}</p>
</div>
</div>
</div>
</div>
</template>