import type { UserLoginActivity } from "../../types/api"; export type DisplayLoginActivity = UserLoginActivity & { grouped_count: number }; type ActivityStatus = NonNullable; const activityTime = (value: string) => new Date(value).getTime(); export const activitySourceKey = (item: UserLoginActivity) => { if (!item.login_ip) return `session:${item.id}`; return [item.client_type, item.login_ip].join("|"); }; export const groupLoginActivitiesBySource = ( activities: UserLoginActivity[], resolveStatus: (item: UserLoginActivity) => ActivityStatus, ): DisplayLoginActivity[] => { const grouped = new Map< string, { row: DisplayLoginActivity; firstLoginAt: string; hasOnlineSession: boolean } >(); activities.forEach((item) => { const key = activitySourceKey(item); const status = resolveStatus(item); const existing = grouped.get(key); if (!existing) { grouped.set(key, { row: { ...item, activity_status: status, grouped_count: 1 }, firstLoginAt: item.login_at, hasOnlineSession: status === "ONLINE", }); return; } existing.row.grouped_count += 1; existing.hasOnlineSession ||= status === "ONLINE"; if (activityTime(item.login_at) < activityTime(existing.firstLoginAt)) { existing.firstLoginAt = item.login_at; } if (activityTime(item.last_seen_at) > activityTime(existing.row.last_seen_at)) { const groupedCount = existing.row.grouped_count; existing.row = { ...item, activity_status: status, grouped_count: groupedCount }; } }); return Array.from(grouped.values()) .map(({ row, firstLoginAt, hasOnlineSession }) => ({ ...row, login_at: firstLoginAt, activity_status: hasOnlineSession ? "ONLINE" : row.activity_status, ended_at: hasOnlineSession ? null : row.ended_at, end_reason: hasOnlineSession ? null : row.end_reason, })) .sort((left, right) => activityTime(right.last_seen_at) - activityTime(left.last_seen_at)); };