import { useAppTranslation } from '@features/localization/renderer'; import { MemberExecutionLog } from '@renderer/components/team/members/MemberExecutionLog'; import { ChevronDown, ChevronRight, Clock, FileText, Loader2 } from 'lucide-react'; import type { asEnhancedChunkArray } from '@renderer/types/data'; import type { BoardTaskExactLogSummary } from '@shared/types'; export interface ExactTaskLogDetailState { status: 'idle' | 'loading' | 'ok' | 'missing' | 'error'; generation?: string; chunks?: ReturnType; error?: string; } function formatRelativeTime(isoString: string): string { const date = new Date(isoString); const diffMs = Date.now() - date.getTime(); const diffMin = Math.floor(diffMs / 60_000); const diffHours = Math.floor(diffMin / 60); const diffDays = Math.floor(diffHours / 24); if (!Number.isFinite(diffMs)) return '--'; if (diffMin < 1) return 'just now'; if (diffMin < 60) return `${diffMin}m ago`; if (diffHours < 24) return `${diffHours}h ago`; return `${diffDays}d ago`; } function actorLabel(summary: BoardTaskExactLogSummary): string { if (summary.actor.memberName) { return summary.actor.memberName; } if (summary.actor.role === 'lead' || summary.actor.isSidechain === false) { return 'lead session'; } return 'unknown actor'; } function describeSummary(summary: BoardTaskExactLogSummary): string { return summary.actionLabel; } function anchorKindLabel(summary: BoardTaskExactLogSummary): string { return summary.anchorKind === 'tool' ? 'tool' : 'message'; } function describeDetailState(state: ExactTaskLogDetailState | undefined): string | null { if (!state) return null; if (state.status === 'missing') { return 'Exact detail is no longer available for this transcript slice.'; } if (state.status === 'error') { return state.error ?? 'Failed to load exact detail.'; } return null; } interface ExactTaskLogCardProps { summary: BoardTaskExactLogSummary; expanded: boolean; detailState?: ExactTaskLogDetailState; onToggle: () => void; } export const ExactTaskLogCard = ({ summary, expanded, detailState, onToggle, }: ExactTaskLogCardProps): React.JSX.Element => { const { t } = useAppTranslation('team'); const loadStateText = describeDetailState(detailState); return (
{expanded ? (
{detailState?.status === 'loading' ? (
{t('taskLogs.exact.loading')}
) : null} {detailState?.status === 'ok' && detailState.chunks ? (
) : null} {detailState?.status !== 'loading' && loadStateText ? (
{loadStateText}
) : null}
) : null}
); };