teacher-tools/app/src/apps/classroom_compliance/StudentView.vue

126 lines
4.0 KiB
Vue

<script setup lang="ts">
import { ClassroomComplianceAPIClient, type Class, type Entry, type Student, type StudentStatisticsOverview } from '@/api/classroom_compliance'
import ConfirmDialog from '@/components/ConfirmDialog.vue'
import { useAuthStore } from '@/stores/auth'
import { onMounted, ref, useTemplateRef, type Ref } from 'vue'
import { useRouter } from 'vue-router'
import StudentEntriesList from './StudentEntriesList.vue'
const props = defineProps<{
classId: string
studentId: string
}>()
const authStore = useAuthStore()
const router = useRouter()
const cls: Ref<Class | null> = ref(null)
const student: Ref<Student | null> = ref(null)
const entries: Ref<Entry[]> = ref([])
const statistics: Ref<StudentStatisticsOverview | null> = ref(null)
const apiClient = new ClassroomComplianceAPIClient(authStore)
const deleteConfirmDialog = useTemplateRef('deleteConfirmDialog')
onMounted(async () => {
const classIdNumber = parseInt(props.classId, 10)
cls.value = await apiClient.getClass(classIdNumber).handleErrorsWithAlert()
if (!cls.value) {
await router.replace('/classroom-compliance')
return
}
const studentIdNumber = parseInt(props.studentId, 10)
student.value = await apiClient.getStudent(classIdNumber, studentIdNumber).handleErrorsWithAlert()
if (!student.value) {
await router.replace(`/classroom-compliance/classes/${cls.value.id}`)
return
}
apiClient.getStudentEntries(cls.value.id, student.value.id).handleErrorsWithAlert()
.then(values => {
if (values !== null) {
entries.value = values
}
})
apiClient.getStudentStatisticsOverview(cls.value.id, student.value.id).handleErrorsWithAlert()
.then(stats => statistics.value = stats)
})
async function deleteThisStudent() {
if (!cls.value || !student.value) return
const choice = await deleteConfirmDialog.value?.show()
if (!choice) return
await apiClient.deleteStudent(cls.value.id, student.value.id)
await router.replace(`/classroom-compliance/classes/${cls.value.id}`)
}
</script>
<template>
<div v-if="student" class="centered-content">
<h2 class="align-center" v-text="student.name"></h2>
<p class="align-center">
From
<RouterLink :to="'/classroom-compliance/classes/' + classId">
<span v-text="'class ' + cls?.number + ', ' + cls?.schoolYear"></span>
</RouterLink>
</p>
<div class="button-bar align-center">
<button type="button"
@click="router.push(`/classroom-compliance/classes/${student.classId}/edit-student?studentId=${student.id}`)">Edit</button>
<button type="button" @click="deleteThisStudent">Delete</button>
</div>
<table class="student-properties-table">
<tbody>
<tr>
<th>Desk Number</th>
<td>{{ student.deskNumber }}</td>
</tr>
<tr>
<th>Removed</th>
<td>{{ student.removed ? 'True' : 'False' }}</td>
</tr>
<tr v-if="statistics">
<th>Attendance Rate</th>
<td>{{ (statistics.attendanceRate * 100).toFixed(1) }}%</td>
</tr>
<tr v-if="statistics">
<th>Phone Compliance Rate</th>
<td>{{ (statistics.phoneComplianceRate * 100).toFixed(1) }}%</td>
</tr>
<tr v-if="statistics">
<th>Behavior Score</th>
<td>{{ (statistics.behaviorScore * 100).toFixed(1) }}%</td>
</tr>
<tr v-if="statistics">
<th>Total Entries</th>
<td>{{ statistics.entryCount }}</td>
</tr>
</tbody>
</table>
<StudentEntriesList :student="student" />
<ConfirmDialog ref="deleteConfirmDialog">
<p>
Are you sure you want to delete <span v-text="student.name"></span>? This will permanently
delete all records for them.
</p>
<p>This <strong>cannot</strong> be undone!</p>
</ConfirmDialog>
</div>
</template>
<style scoped>
.student-properties-table {
width: 100%;
border-collapse: collapse;
}
.student-properties-table :is(th, td) {
border: 1px solid gray;
padding: 0.25em;
}
.student-properties-table td {
text-align: right;
}
</style>