import { useEffect, useMemo, useState } from 'react' import { createPortal } from 'react-dom' import { X } from 'lucide-react' import { useLocale } from '@meshkee/dashboard-ui' import { useT } from '../i18n/useT' import type { BusinessMessageKey } from '../i18n/messages' import type { Order, OrderTransaction, TransactionStatus, TransactionType } from '../services/orderService' import { formatIrtPrice } from '../utils/irtPrice' import modalStyles from './VariationsModal.module.css' import styles from './OrderTransactionsModal.module.css' interface OrderTransactionsModalProps { open: boolean order: Order | null onClose: () => void } const ANIMATION_MS = 220 const TYPE_KEYS: Record = { pos: 'orderTransactions.type.pos', cash: 'orderTransactions.type.cash', transfer: 'orderTransactions.type.transfer', e_payment_gate: 'orderTransactions.type.e_payment_gate', } const STATUS_KEYS: Record = { pending: 'orderTransactions.status.pending', completed: 'orderTransactions.status.completed', failed: 'orderTransactions.status.failed', refunded: 'orderTransactions.status.refunded', } function statusClass(status: TransactionStatus) { switch (status) { case 'completed': return styles.statusCompleted case 'failed': return styles.statusFailed case 'refunded': return styles.statusRefunded case 'pending': default: return styles.statusPending } } function formatDateTime(value: string, locale: 'en' | 'fa') { const d = new Date(value) if (Number.isNaN(d.getTime())) return value return d.toLocaleString(locale === 'fa' ? 'fa-IR' : 'en-US', { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit', }) } export function OrderTransactionsModal({ open, order, onClose }: OrderTransactionsModalProps) { const t = useT() const { locale } = useLocale() const dateLocale = locale === 'fa' ? 'fa' : 'en' const [mounted, setMounted] = useState(open) const [closing, setClosing] = useState(false) const transactions = order?.transactions ?? [] const totalPaid = useMemo( () => transactions.reduce((sum, tx) => sum + tx.amount, 0), [transactions], ) useEffect(() => { if (open) { setMounted(true) setClosing(false) } else if (mounted) { setClosing(true) const timer = setTimeout(() => { setMounted(false) setClosing(false) }, ANIMATION_MS) return () => clearTimeout(timer) } }, [open, mounted]) useEffect(() => { if (!mounted || closing) return const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() } document.addEventListener('keydown', onKey) return () => document.removeEventListener('keydown', onKey) }, [mounted, closing, onClose]) if (!mounted || !order) return null function transactionDetails(transaction: OrderTransaction) { const rows: { label: string; value: string; isStatus?: boolean }[] = [ { label: t('orderTransactions.status'), value: t(STATUS_KEYS[transaction.status] ?? 'orderTransactions.status.pending'), isStatus: true, }, { label: t('orderTransactions.date'), value: formatDateTime(transaction.createdAt, dateLocale), }, ] if (transaction.type === 'pos' && transaction.posType) { rows.push({ label: t('orderTransactions.posType'), value: transaction.posType }) } if (transaction.type === 'transfer') { if (transaction.transferAccount) { rows.push({ label: t('orderTransactions.account'), value: transaction.transferAccount }) } if (transaction.transferRefNumber) { rows.push({ label: t('orderTransactions.refCode'), value: transaction.transferRefNumber }) } } if (transaction.type === 'e_payment_gate' && transaction.gatewayType) { rows.push({ label: t('orderTransactions.gateway'), value: transaction.gatewayType }) } if (transaction.notes) { rows.push({ label: t('orderTransactions.notes'), value: transaction.notes }) } return rows } return createPortal(
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="order-transactions-title" >

{t('orderTransactions.title')}

{order.orderNumber}

{transactions.length === 0 ? (

{t('orderTransactions.empty')}

) : (
    {transactions.map((transaction) => { const details = transactionDetails(transaction) return (
  • {t(TYPE_KEYS[transaction.type] ?? 'orderTransactions.type.e_payment_gate')}
    {formatIrtPrice(transaction.amount)}
    {details.map((detail) => (
    {detail.label}:{' '} {detail.isStatus ? ( {detail.value} ) : ( {detail.value} )}
    ))}
  • ) })}
)}
{t('orderTransactions.summary', { count: transactions.length, txLabel: transactions.length === 1 ? t('orderTransactions.one') : t('orderTransactions.many'), })} {formatIrtPrice(totalPaid)}
, document.body, ) }