33 lines
1.8 KiB
TypeScript
33 lines
1.8 KiB
TypeScript
/** Collapse legacy-compatible work segments into complete persisted attendances for widgets. */
|
|
export function staffTimeRows(spans: any[], userId: string, now = Date.now()) {
|
|
const seen = new Set<string>();
|
|
return (spans || []).filter(span => {
|
|
if (span.model !== 'spans-v2') return true;
|
|
if (seen.has(span.id)) return false;
|
|
seen.add(span.id);
|
|
return true;
|
|
}).map(span => {
|
|
const s = span.attendance;
|
|
if (s) {
|
|
const entry = {
|
|
id: s.id, eventIds: [s.id], state: s.status, started_at: s.started_at,
|
|
stopped_at: s.ended_at, user_id: s.user_id, type: s.type, description: s.description,
|
|
breaks: s.breaks, paused: s.breaks.some((p: any) => !p.ended_at), model: 'spans-v2',
|
|
};
|
|
return { ...entry, duration_minutes: workingMinutes(entry, now) };
|
|
}
|
|
return {
|
|
id: span.sourceEventIds?.[0] || null, eventIds: span.sourceEventIds || [], state: span.status,
|
|
started_at: span.startedAt, stopped_at: span.endedAt, user_id: userId, type: span.type,
|
|
description: span.description || span.payload?.description || '',
|
|
duration_minutes: Math.floor(((span.endedAt ? Date.parse(span.endedAt) : now) - Date.parse(span.startedAt)) / 60000),
|
|
};
|
|
}).sort((a, b) => Date.parse(b.started_at) - Date.parse(a.started_at));
|
|
}
|
|
export function workingMinutes(entry: any, now = Date.now()) {
|
|
if (!entry.started_at) return 0;
|
|
const end = entry.stopped_at ? Date.parse(entry.stopped_at) : now;
|
|
const pauses = (entry.breaks || []).reduce((total: number, p: any) => total + ((p.ended_at ? Date.parse(p.ended_at) : end) - Date.parse(p.started_at)), 0);
|
|
return Math.max(0, Math.floor((end - Date.parse(entry.started_at) - pauses) / 60000));
|
|
}
|