import type { FetchDataResult, IngestionSourceResult } from '../api/ingestion'; export type IngestionToastType = 'success' | 'error' | 'info'; export interface IngestionStatusSummary { toastType: IngestionToastType; message: string; } export function summarizeIngestionResult( result: FetchDataResult | null | undefined, fallbackLabel: string, ): IngestionStatusSummary { const sources = result?.sources; if (!sources) { return { toastType: 'success', message: `Data fetched for ${fallbackLabel}`, }; } const entries = Object.entries(sources) as [string, IngestionSourceResult][]; const parts = entries.map(([name, info]) => { const label = name.charAt(0).toUpperCase() + name.slice(1); if (info.status === 'ok') { return `${label} ✓`; } if (info.status === 'warning') { return `${label} ⚠${info.message ? `: ${info.message}` : ': no data'}`; } if (info.status === 'skipped') { return `${label}: skipped${info.message ? ` (${info.message})` : ''}`; } return `${label} ✗${info.message ? `: ${info.message}` : ''}`; }); const hasError = entries.some(([, source]) => source.status === 'error'); const hasWarning = entries.some(([, source]) => source.status === 'warning'); const hasSkip = entries.some(([, source]) => source.status === 'skipped'); // A warning (e.g. 0 bars returned) must not read as success. const toastType: IngestionToastType = hasError ? 'error' : hasWarning || hasSkip ? 'info' : 'success'; return { toastType, message: parts.join(' · '), }; }