import { useStore } from '@renderer/store'; import { formatDistanceToNowStrict } from 'date-fns'; import { ExternalLink, Square, Terminal } from 'lucide-react'; import { MemberBadge } from './MemberBadge'; function formatShortTime(date: Date): string { const distance = formatDistanceToNowStrict(date, { addSuffix: false }); return distance .replace(' seconds', 's') .replace(' second', 's') .replace(' minutes', 'm') .replace(' minute', 'm') .replace(' hours', 'h') .replace(' hour', 'h') .replace(' days', 'd') .replace(' day', 'd') .replace(' weeks', 'w') .replace(' week', 'w') .replace(' months', 'mo') .replace(' month', 'mo') .replace(' years', 'y') .replace(' year', 'y'); } export const ProcessesSection = (): React.JSX.Element | null => { const teamName = useStore((s) => s.selectedTeamName); const data = useStore((s) => s.selectedTeamData); if (!teamName || !data?.processes?.length) return null; const memberColorMap = new Map(data.members.map((m) => [m.name, m.color])); const sorted = [...data.processes].sort((a, b) => { const aAlive = !a.stoppedAt; const bAlive = !b.stoppedAt; if (aAlive !== bAlive) return aAlive ? -1 : 1; return Date.parse(b.registeredAt) - Date.parse(a.registeredAt); }); return (
{sorted.map((proc) => { const alive = !proc.stoppedAt; const timeStr = alive ? `${formatShortTime(new Date(proc.registeredAt))} ago` : `stopped ${formatShortTime(new Date(proc.stoppedAt!))} ago`; return (
{/* Status indicator */} {alive && ( )} {/* Icon + label — takes available space */} {proc.label} {/* Port + URL inline — only when present */} {(proc.port != null || proc.url) && ( {proc.port != null && !proc.url && `:${proc.port}`} {proc.url && ( )} )} {/* Right-aligned group: Kill button, Open button, member badge, PID, time */} {alive && ( )} {alive && proc.url && ( )} PID{proc.pid} {proc.registeredBy && ( )} {timeStr}
); })}
); };