Files
fusion/packages/dashboard/app/utils/taskAgeStalenessCopy.ts
Fusion 927a32182d feat(FN-4465): complete Step 4 — dashboard stale signal surfacing
Fusion-Task-Id: FN-4465
Fusion-Task-Lineage: 4365d4cb-ab93-4ed5-add9-3e14b26237ad
2026-05-14 05:55:16 -07:00

38 lines
1.4 KiB
TypeScript

import type { Task, TaskAgeStalenessSignal } from "@fusion/core";
export interface TaskAgeStalenessCopy {
badgeLabel: string;
badgeTone: "warning" | "critical";
headline: string;
description: string;
}
function formatAge(ageMs: number): string {
const totalMinutes = Math.max(1, Math.floor(ageMs / 60_000));
const days = Math.floor(totalMinutes / 1440);
const hours = Math.floor((totalMinutes % 1440) / 60);
const minutes = totalMinutes % 60;
const parts: string[] = [];
if (days > 0) parts.push(`${days}d`);
if (hours > 0) parts.push(`${hours}h`);
if (minutes > 0 && days === 0) parts.push(`${minutes}m`);
return parts.join(" ");
}
export function getTaskAgeStalenessCopy(signal: TaskAgeStalenessSignal | undefined | null): TaskAgeStalenessCopy | null {
if (!signal) return null;
const ageLabel = formatAge(signal.ageMs);
const pausedNote = signal.paused ? " while paused" : "";
const tone = signal.level === "critical" ? "critical" : "warning";
return {
badgeLabel: tone === "critical" ? "Stale (critical)" : "Stale",
badgeTone: tone,
headline: `${signal.column} task stale for ${ageLabel}`,
description: `Task has been stale for ${ageLabel}${pausedNote}. Thresholds: warning ${formatAge(signal.warningThresholdMs)}, critical ${formatAge(signal.criticalThresholdMs)}.`,
};
}
export function shouldShowTaskAgeStalenessBadge(task: Pick<Task, "ageStaleness">): boolean {
return task.ageStaleness != null;
}