import type { ClockEvent } from './clock'; export const workDate = (instant:string) => { const date = new Date(instant); if (!Number.isFinite(date.getTime())) throw new Error('Invalid scan time'); return new Intl.DateTimeFormat('en-CA',{timeZone:'Africa/Johannesburg',year:'numeric',month:'2-digit',day:'2-digit'}).format(date); }; /** Same-day IN closes with OUT; anything else (first scan, new day, after an OUT) is IN. */ export function clockAction(last:ClockEvent|null, now:string):'in'|'out' { return last?.direction==='in' && workDate(last.scanned_at)===workDate(now) ? 'out' : 'in'; } /** An IN never closed on the same day is still missing its physical OUT. */ export function missedClockIns(events:ClockEvent[], now:string):ClockEvent[] { const open=new Map();const missed:ClockEvent[]=[]; for (const event of [...events].sort((a,b)=>Date.parse(a.scanned_at)-Date.parse(b.scanned_at)||a.id.localeCompare(b.id))) { const previous=open.get(event.employee); if (event.direction==='in') { if(previous)missed.push(previous);open.set(event.employee,event); } else if(previous && workDate(previous.scanned_at)===workDate(event.scanned_at)) open.delete(event.employee); } for(const event of open.values())if(workDate(event.scanned_at)