import { useT } from "@agent-native/core/client/i18n"; import { Skeleton } from "./ui/skeleton"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; /** * Shared between the transactional email list and detail pages so both * render the same "unknown vs. zero" and provider-availability rules. */ export interface EmailEngagement { templateId: string; delivered: number; uniqueOpens: number; uniqueClicks: number; /** null when nothing was delivered in the window, so there is no rate yet. */ openRate: number | null; } export type ProviderMetricsResult = | { available: true; data: T } | { available: false; reason: string }; /** * Renders a metric the backend could not read. "Unknown" and "zero" must stay * visibly different — a dash with a reason is the only honest rendering. */ export function UnknownMetric({ reason }: { reason: string }) { return ( {reason} ); } export function SendsCell({ sent, failed, }: { sent: number | null; failed: number | null; }) { const t = useT(); if (sent === null) { return ( ); } return ( {sent} {failed !== null && failed > 0 ? ( {t("dispatch.transactionalEmail.failedCount", { count: failed })} ) : null} {failed === null ? ( {t("dispatch.transactionalEmail.failuresUnknown")} ) : null} ); } export function OpenRateCell({ engagement, unavailableReason, loading, }: { engagement: EmailEngagement | undefined; unavailableReason: string | null; loading: boolean; }) { const t = useT(); if (unavailableReason) { return ; } if (loading) return ; if (!engagement) { return ( ); } if (engagement.openRate === null) { return ( {t("dispatch.transactionalEmail.noDeliveredMail")} ); } return ( {`${(engagement.openRate * 100).toFixed(1)}%`} ); } export function LastSentCell({ lastSentAt, sent, }: { lastSentAt: number | null; sent: number | null; }) { const t = useT(); if (lastSentAt !== null) { return <>{new Date(lastSentAt).toLocaleString()}; } if (sent === 0) { return ( {t("dispatch.transactionalEmail.neverSent")} ); } return ( ); }