fabro/apps/fabro-web/app/lib/time.ts
Bryan Helmkamp 3a6ec9b9ef Rename Arc to Fabro in TypeScript/JavaScript
Rename directories (arc-web → fabro-web, arc-api-client → fabro-api-client),
update package names, import paths, TS-only identifiers (theme key, session
cookie, demo cookie, OAuth state, db filename, mock data), and supporting
files (Dockerfile, docker-compose, entrypoint, CI workflow, CLAUDE.md).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:13:18 -04:00

67 lines
2.1 KiB
TypeScript

function relativeTime(seconds: number, past: boolean): string {
if (seconds < 60) return past ? "just now" : "in <1m";
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return past ? `${minutes}m ago` : `in ${minutes}m`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return past ? `${hours}h ago` : `in ${hours}h`;
const days = Math.floor(hours / 24);
return past ? `${days}d ago` : `in ${days}d`;
}
/**
* Format an ISO 8601 timestamp as a relative past time string (e.g. "2h ago", "3d ago").
*/
export function timeAgo(iso: string): string {
return relativeTime(Math.floor((Date.now() - new Date(iso).getTime()) / 1000), true);
}
/**
* Format an ISO 8601 timestamp as a relative future time string (e.g. "in 2h", "in 3d").
*/
export function timeUntil(iso: string): string {
return relativeTime(Math.floor((new Date(iso).getTime() - Date.now()) / 1000), false);
}
/**
* Return a human-readable date label for grouping (e.g. "Today", "Yesterday", "Previous 7 days").
*/
function dateLabel(iso: string): string {
const now = new Date();
const date = new Date(iso);
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const startOfYesterday = new Date(startOfToday.getTime() - 86_400_000);
const startOf7DaysAgo = new Date(startOfToday.getTime() - 7 * 86_400_000);
if (date >= startOfToday) return "Today";
if (date >= startOfYesterday) return "Yesterday";
if (date >= startOf7DaysAgo) return "Previous 7 days";
return "Older";
}
interface SessionItem {
id: string;
title: string;
created_at: string;
}
interface SessionGroup {
label: string;
sessions: SessionItem[];
}
/**
* Group a flat list of sessions (already sorted newest-first) into date-labeled groups.
*/
export function groupSessionsByDate(sessions: SessionItem[]): SessionGroup[] {
const groups: SessionGroup[] = [];
let current: SessionGroup | undefined;
for (const s of sessions) {
const label = dateLabel(s.created_at);
if (!current || current.label !== label) {
current = { label, sessions: [] };
groups.push(current);
}
current.sessions.push(s);
}
return groups;
}