189 lines
4.7 KiB
TypeScript
189 lines
4.7 KiB
TypeScript
import { APIClient, type APIResponse, type AuthStoreType } from './base'
|
|
|
|
const BASE_URL = import.meta.env.VITE_API_URL + '/classroom-compliance'
|
|
|
|
export const EMOJI_PHONE_COMPLIANT = '📱'
|
|
export const EMOJI_PHONE_NONCOMPLIANT = '📵'
|
|
export const EMOJI_PRESENT = '✅'
|
|
export const EMOJI_ABSENT = '❌'
|
|
export const EMOJI_BEHAVIOR_GOOD = '😇'
|
|
export const EMOJI_BEHAVIOR_MEDIOCRE = '😐'
|
|
export const EMOJI_BEHAVIOR_POOR = '😡'
|
|
|
|
export interface Class {
|
|
id: number
|
|
number: number
|
|
schoolYear: string
|
|
}
|
|
|
|
export interface ClassesResponseClass {
|
|
id: number
|
|
number: number
|
|
schoolYear: string
|
|
studentCount: number
|
|
entryCount: number
|
|
lastEntryDate: string
|
|
}
|
|
|
|
export interface Student {
|
|
id: number
|
|
name: string
|
|
classId: number
|
|
deskNumber: number
|
|
removed: boolean
|
|
}
|
|
|
|
export interface Entry {
|
|
id: number
|
|
date: string
|
|
createdAt: number
|
|
absent: boolean
|
|
phoneCompliant: boolean | null
|
|
behaviorRating: number | null
|
|
comment: string
|
|
}
|
|
|
|
export function getDefaultEntry(dateStr: string): Entry {
|
|
return {
|
|
id: 0,
|
|
date: dateStr,
|
|
createdAt: Date.now(),
|
|
absent: false,
|
|
phoneCompliant: true,
|
|
behaviorRating: 3,
|
|
comment: '',
|
|
}
|
|
}
|
|
|
|
export interface EntriesResponseStudent {
|
|
id: number
|
|
name: string
|
|
deskNumber: number
|
|
removed: boolean
|
|
entries: Record<string, Entry | null>
|
|
score: number | null
|
|
}
|
|
|
|
export interface EntriesResponse {
|
|
students: EntriesResponseStudent[]
|
|
dates: string[]
|
|
}
|
|
|
|
export interface StudentDataPayload {
|
|
name: string
|
|
deskNumber: number
|
|
removed: boolean
|
|
}
|
|
|
|
export interface EntriesPayloadStudent {
|
|
id: number
|
|
entries: Record<string, Entry | null>
|
|
}
|
|
|
|
export interface EntriesPayload {
|
|
students: EntriesPayloadStudent[]
|
|
}
|
|
|
|
export interface StudentScore {
|
|
id: number
|
|
score: number | null
|
|
}
|
|
|
|
export interface ScoresResponse {
|
|
scores: StudentScore[]
|
|
}
|
|
|
|
export interface StudentStatisticsOverview {
|
|
attendanceRate: number
|
|
phoneComplianceRate: number
|
|
behaviorScore: number
|
|
entryCount: number
|
|
}
|
|
|
|
export class ClassroomComplianceAPIClient extends APIClient {
|
|
constructor(authStore: AuthStoreType) {
|
|
super(BASE_URL, authStore)
|
|
}
|
|
|
|
createClass(number: number, schoolYear: string): APIResponse<Class> {
|
|
return super.post('/classes', { number: number, schoolYear: schoolYear })
|
|
}
|
|
|
|
getClasses(): APIResponse<ClassesResponseClass[]> {
|
|
return super.get('/classes')
|
|
}
|
|
|
|
getClass(classId: number): APIResponse<Class> {
|
|
return super.get(`/classes/${classId}`)
|
|
}
|
|
|
|
deleteClass(classId: number): APIResponse<void> {
|
|
return super.delete(`/classes/${classId}`)
|
|
}
|
|
|
|
getStudents(classId: number): APIResponse<Student[]> {
|
|
return super.get(`/classes/${classId}/students`)
|
|
}
|
|
|
|
getStudent(classId: number, studentId: number): APIResponse<Student> {
|
|
return super.get(`/classes/${classId}/students/${studentId}`)
|
|
}
|
|
|
|
createStudent(classId: number, data: StudentDataPayload): APIResponse<Student> {
|
|
return super.post(`/classes/${classId}/students`, data)
|
|
}
|
|
|
|
updateStudent(
|
|
classId: number,
|
|
studentId: number,
|
|
data: StudentDataPayload,
|
|
): APIResponse<Student> {
|
|
return super.put(`/classes/${classId}/students/${studentId}`, data)
|
|
}
|
|
|
|
moveStudentToOtherClass(
|
|
classId: number,
|
|
studentId: number,
|
|
newClassId: number,
|
|
): APIResponse<void> {
|
|
return super.put(`/classes/${classId}/students/${studentId}/class`, { classId: newClassId })
|
|
}
|
|
|
|
deleteStudent(classId: number, studentId: number): APIResponse<void> {
|
|
return super.delete(`/classes/${classId}/students/${studentId}`)
|
|
}
|
|
|
|
getEntries(classId: number, fromDate?: Date, toDate?: Date): APIResponse<EntriesResponse> {
|
|
const params = new URLSearchParams()
|
|
if (fromDate) {
|
|
params.append('from', fromDate.toISOString().substring(0, 10))
|
|
}
|
|
if (toDate) {
|
|
params.append('to', toDate.toISOString().substring(0, 10))
|
|
}
|
|
return super.get(`/classes/${classId}/entries?${params.toString()}`)
|
|
}
|
|
|
|
saveEntries(classId: number, payload: EntriesPayload): APIResponse<void> {
|
|
return super.postWithNoExpectedResponse(`/classes/${classId}/entries`, payload)
|
|
}
|
|
|
|
getScores(classId: number, fromDate: Date, toDate: Date): APIResponse<ScoresResponse> {
|
|
const params = new URLSearchParams()
|
|
params.append('from', fromDate.toISOString().substring(0, 10))
|
|
params.append('to', toDate.toISOString().substring(0, 10))
|
|
return super.get(`/classes/${classId}/scores?${params.toString()}`)
|
|
}
|
|
|
|
getStudentEntries(classId: number, studentId: number): APIResponse<Entry[]> {
|
|
return super.get(`/classes/${classId}/students/${studentId}/entries`)
|
|
}
|
|
|
|
getStudentStatisticsOverview(
|
|
classId: number,
|
|
studentId: number,
|
|
): APIResponse<StudentStatisticsOverview> {
|
|
return super.get(`/classes/${classId}/students/${studentId}/overview`)
|
|
}
|
|
}
|