'use client' import { useFormatter, useTranslations } from 'next-intl' import { ExternalLink, Mail, Send } from 'lucide-react' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Separator } from '@/components/ui/separator' import type { InvoiceDelivery, InvoiceDeliveryProviderStatus } from '@/types' export type InvoiceDeliveryView = Pick< InvoiceDelivery, | 'id' | 'channel' | 'to_addresses' | 'cc_addresses' | 'provider' | 'provider_status' | 'provider_status_at' | 'provider_status_detail' | 'provider_recipient_statuses' | 'error_code' | 'document_attachment_id' | 'attachment_filename' | 'sent_at' | 'failed_at' | 'created_at' > & { status: 'pending' | 'sent' | 'failed' | 'marked_sent' } interface InvoiceDeliveryHistoryProps { deliveries: InvoiceDeliveryView[] showLegacyEmptyState: boolean } /** * What the row actually says happened. The send status alone stops at * "handed to the provider", which is why an accepted-but-bounced invoice used * to read as a plain success. When the provider has reported back, its * outcome is what the row shows. */ type DeliveryOutcome = | 'pending' | 'sent' | 'failed' | 'marked_sent' | InvoiceDeliveryProviderStatus function outcomeOf(delivery: InvoiceDeliveryView): DeliveryOutcome { if (delivery.status === 'sent' && delivery.provider_status) return delivery.provider_status return delivery.status } // Green is reserved for a confirmed arrival. "Skickad" without a delivery // report is a neutral, honest in-between state. const outcomeVariant: Record = { pending: 'secondary', sent: 'secondary', delivered: 'success', delayed: 'warning', complained: 'warning', bounced: 'destructive', failed: 'destructive', suppressed: 'destructive', marked_sent: 'outline', } export function InvoiceDeliveryHistory({ deliveries, showLegacyEmptyState, }: InvoiceDeliveryHistoryProps) { const t = useTranslations('invoice_detail') const format = useFormatter() if (deliveries.length === 0 && !showLegacyEmptyState) return null const formatTimestamp = (value: string) => format.dateTime(new Date(value), { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', }) return ( {t('delivery_history_title')} {t('delivery_history_description')} {deliveries.length === 0 ? (

{t('delivery_history_legacy_title')}

{t('delivery_history_legacy_description')}

) : (
{deliveries.map((delivery) => { const occurredAt = delivery.sent_at || delivery.failed_at || delivery.created_at const isManual = delivery.channel === 'manual' const outcome = outcomeOf(delivery) const isEmailSend = !isManual && delivery.status === 'sent' const recipientCount = delivery.to_addresses.length + delivery.cc_addresses.length const recipientStatuses = delivery.provider_recipient_statuses ?? {} const hasRecipientStatuses = Object.keys(recipientStatuses).length > 0 const recipientRows = [ ...delivery.to_addresses.map((address, index) => ({ address, label: t('delivery_to_label'), reference: `to:${index + 1}`, outcome: recipientStatuses[`to:${index + 1}`], })), ...delivery.cc_addresses.map((address, index) => ({ address, label: t('delivery_cc_label'), reference: `cc:${index + 1}`, outcome: recipientStatuses[`cc:${index + 1}`], })), ] return (
{isManual ? : } {isManual ? t('delivery_channel_manual') : t('delivery_channel_email')} {formatTimestamp(occurredAt)} {t(`delivery_status_${outcome}`)}
{isManual ? (

{t('delivery_manual_unknown_details')}

) : (
{t('delivery_to_label')}
{delivery.to_addresses.join(', ')}
{delivery.cc_addresses.length > 0 && ( <>
{t('delivery_cc_label')}
{delivery.cc_addresses.join(', ')}
)}
{isEmailSend && (
{t('delivery_provider_status_label')} {t(`delivery_status_${outcome}`)} {delivery.provider_status_at && ( {formatTimestamp(delivery.provider_status_at)} )}

{hasRecipientStatuses ? t('delivery_recipient_statuses_summary') : t(`delivery_status_explanation_${outcome}`)}

{hasRecipientStatuses && (

{t('delivery_recipient_statuses_label')}

    {recipientRows.map((recipient) => (
  • {recipient.label}: {' '} {recipient.address} {recipient.outcome ? ( {recipient.outcome.status === 'delivered' ? ( {t('delivery_status_delivered')} ) : ( {t(`delivery_status_${recipient.outcome.status}`)} )} {formatTimestamp(recipient.outcome.status_at)} ) : ( {t('delivery_recipient_status_unknown')} )}
  • ))}
)} {delivery.provider_status_detail && (

{t('delivery_provider_reason_label')}: {delivery.provider_status_detail}

)} {recipientCount > 1 && delivery.provider_status && !hasRecipientStatuses && (

{t('delivery_status_whole_send_note')}

)}
)} {delivery.document_attachment_id && ( )} {(delivery.provider || delivery.error_code) && (
{delivery.provider && ( <>
{t('delivery_provider_label')}
{delivery.provider}
)} {delivery.error_code && ( <>
{t('delivery_error_label')}
{delivery.error_code}
)}
)}
)}
) })}
)}
) }