Files
gongxue-base/apps/admin/src/pages/Attendance/attendance-workspace.ts

85 lines
2.1 KiB
TypeScript

export type AttendanceExperience = 'teacher' | 'admin';
export type SchedulePhase = 'upcoming' | 'ongoing' | 'ended';
import { getRoleDomains } from '../../auth/menu-policy';
export function getAttendanceExperience(
permissions: readonly string[],
roles: readonly string[],
): AttendanceExperience {
const domains = getRoleDomains(roles, permissions);
if (
permissions.includes('attendance:manage') ||
domains.has('academic') ||
domains.has('super')
) {
return 'admin';
}
return 'teacher';
}
function toMinuteOfDay(time: string): number {
const [hour = 0, minute = 0] = time.split(':').map(Number);
return hour * 60 + minute;
}
export function getSchedulePhase(
startTime: string,
endTime: string,
now = new Date(),
): SchedulePhase {
const current = now.getHours() * 60 + now.getMinutes();
if (current < toMinuteOfDay(startTime)) return 'upcoming';
if (current <= toMinuteOfDay(endTime)) return 'ongoing';
return 'ended';
}
export function canPullAttendance(phase: SchedulePhase): boolean {
return phase !== 'upcoming';
}
export interface AttendanceSummary {
total: number;
present: number;
late: number;
absent: number;
leave: number;
pending: number;
}
export function summarizeAttendance(records: readonly { status: string }[]): AttendanceSummary {
const summary: AttendanceSummary = {
total: records.length,
present: 0,
late: 0,
absent: 0,
leave: 0,
pending: 0,
};
for (const record of records) {
if (record.status in summary && record.status !== 'total') {
summary[record.status as Exclude<keyof AttendanceSummary, 'total'>] += 1;
}
}
return summary;
}
export interface LessonCheckinSummary {
total: number;
checkedIn: number;
notCheckedIn: number;
}
export function summarizeLessonCheckins(
records: readonly { status: string }[],
): LessonCheckinSummary {
const checkedIn = records.filter(
(record) => record.status === 'present' || record.status === 'late',
).length;
return {
total: records.length,
checkedIn,
notCheckedIn: records.length - checkedIn,
};
}