Reference
Complete technical reference for the Staff Attendance module.
TypeScript types
StaffAttendanceStatus
type StaffAttendanceStatus =
| "present"
| "absent"
| "late"
| "half_day"
| "on_leave"
| "holiday"
| "weekend";
StaffAttendanceMarkingMethod
type StaffAttendanceMarkingMethod =
| "biometric"
| "rfid"
| "face_recognition"
| "app"
| "manual"
| "barcode";
StaffAttendanceLeaveType
type StaffAttendanceLeaveType =
| "annual"
| "sick"
| "maternity"
| "paternity"
| "unpaid"
| "study"
| "compassionate";
StaffAttendanceRecord
interface StaffAttendanceRecord {
id: string;
staffId: string;
schoolId: string;
tenantId: string;
attendanceDate: string; // YYYY-MM-DD
checkInTime?: string | null; // HH:mm
checkOutTime?: string | null; // HH:mm
totalHoursWorked?: number | null;
attendanceStatus: StaffAttendanceStatus;
markingMethod: StaffAttendanceMarkingMethod;
isLate?: boolean | null;
minutesLate?: number | null;
leaveType?: StaffAttendanceLeaveType | null;
leaveRequestId?: string | null;
isRemoteWork?: boolean | null;
overtimeHours?: number | null;
overtimeApproved?: boolean | null;
verifiedBy?: string | null; // UUID of verifier
verifiedAt?: string | null; // ISO datetime
notes?: string | null; // visible to staff member
supervisorNotes?: string | null; // internal only
createdAt: string;
updatedAt: string;
staff?: StaffAttendanceStaffContext | null;
}
StaffAttendanceStatistics
interface StaffAttendanceStatistics {
totalRecords: number;
totalStaff: number;
checkedInStaff: number;
present: number;
absent: number;
late: number;
halfDay: number;
onLeave: number;
latePercentage?: number | null;
absenteeismRate?: number | null;
byDepartment?: StaffAttendanceDepartmentSummary[];
byMarkingMethod?: Record<StaffAttendanceMarkingMethod, number>;
dailySummary?: Array<{
date: string;
present: number;
absent: number;
late: number;
}>;
}
StaffAttendanceKioskStation
interface StaffAttendanceKioskStation {
id: string;
schoolId: string;
name: string;
code: string;
location?: string | null;
allowedMarkingMethods: StaffAttendanceMarkingMethod[];
tokenVersion?: number | null;
tokenExpiresAt?: string | null;
isActive: boolean;
revokedAt?: string | null;
lastUsedAt?: string | null;
createdAt: string;
updatedAt: string;
}
React Query hooks
All hooks are exported from @/lib/api/domains/operations/staff-attendance.
Query hooks
| Hook | Signature | Description |
|---|---|---|
useStaffAttendanceRecords | (schoolId, params?, options?) | Paginated list of records |
useSearchStaffAttendance | (schoolId, params?, options?) | Full-text search |
useStaffAttendanceRecord | (schoolId, staffId, options?) | Single record |
useStaffAttendanceStatistics | (schoolId, params?, options?) | Aggregated stats |
useStaffAttendanceKioskStations | (schoolId, params?, options?) | List stations |
usePublicStaffAttendanceKioskSession | (stationCode, options?) | Public kiosk session (no auth) |
Mutation hooks
| Hook | Signature | Description |
|---|---|---|
useCreateStaffAttendance | (schoolId) | Create a single record |
useUpdateStaffAttendance | (schoolId) | Update an existing record |
useDeleteStaffAttendance | (schoolId) | Delete a record |
useVerifyStaffAttendance | (schoolId) | Mark a record as verified |
useBulkCreateStaffAttendance | (schoolId) | Create many records in one request |
useCreateStaffAttendanceKioskStation | (schoolId) | Create a new station |
useUpdateStaffAttendanceKioskStation | (schoolId, stationId) | Edit station fields |
useRotateStaffAttendanceKioskStationToken | (schoolId, stationId) | Generate a new signed URL |
useRevokeStaffAttendanceKioskStation | (schoolId, stationId) | Revoke station access |
useDeleteStaffAttendanceKioskStation | (schoolId, stationId) | Delete a station |
API endpoints
Base path: /api/v1/staff-attendance (scoped per school via schoolId header or query parameter).
Records
| Method | Path | Description |
|---|---|---|
GET | / | List records with optional filters |
POST | / | Create a single record |
PUT | /{id} | Update a record |
DELETE | /{id} | Delete a record |
POST | /{id}/verify | Verify a record |
POST | /bulk | Bulk create records |
GET | /search | Full-text search |
GET | /statistics | Aggregated statistics |
Kiosk stations
| Method | Path | Description |
|---|---|---|
GET | /kiosk-stations | List stations |
POST | /kiosk-stations | Create a station |
PUT | /kiosk-stations/{id} | Update a station |
DELETE | /kiosk-stations/{id} | Delete a station |
POST | /kiosk-stations/{id}/rotate-token | Rotate the signed URL |
POST | /kiosk-stations/{id}/revoke | Revoke station access |
Zod validators
Located at src/lib/validators/domains/operations/staff-attendance.ts.
import {
staffAttendanceStatusSchema,
staffAttendanceMarkingMethodSchema,
staffAttendanceLeaveTypeSchema,
staffAttendanceSortBySchema,
createStaffAttendanceSchema,
updateStaffAttendanceSchema,
bulkCreateStaffAttendanceSchema,
verifyStaffAttendanceSchema,
listStaffAttendanceParamsSchema,
createKioskStationSchema,
updateKioskStationSchema,
} from "@/lib/validators/domains/operations/staff-attendance";
Permissions
| Resource | Action | Grants |
|---|---|---|
staff_attendance | view | Read attendance records and statistics |
staff_attendance | create | Create and self check-in records |
staff_attendance | manage | Edit, delete, verify, manage kiosk stations |
Use useUserPermissions() in components:
const { canView, canCreate, canEdit } = useUserPermissions();
const showVerifyButton = canEdit("staff_attendance");
const showCreateButton = canCreate("staff_attendance");
Query keys
import { staffAttendanceKeys } from "@/lib/api/domains/operations/staff-attendance";
// Invalidate all records for a school after a mutation
queryClient.invalidateQueries({ queryKey: staffAttendanceKeys.list(schoolId) });
// Invalidate statistics
queryClient.invalidateQueries({ queryKey: staffAttendanceKeys.statistics(schoolId) });
// Invalidate kiosk stations
queryClient.invalidateQueries({ queryKey: staffAttendanceKeys.kioskStations(schoolId) });