import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { X } from 'lucide-react' import { useT } from '../i18n/useT' import type { Order } from '../services/orderService' import { formatCellForDisplay } from '../lib/cellNumber' import { formatIrtPrice } from '../utils/irtPrice' import modalStyles from './VariationsModal.module.css' import styles from './OrderItemsModal.module.css' interface OrderItemsModalProps { open: boolean order: Order | null onClose: () => void } const ANIMATION_MS = 220 function displayName(order: Order) { const name = [order.customer.firstName, order.customer.lastName].filter(Boolean).join(' ').trim() return name || '—' } function formatVariantLabel(selections: Order['items'][number]['selections']) { if (!selections.length) return '—' return selections.map((s) => `${s.variationName}: ${s.value}`).join(' · ') } function totalQuantity(order: Order) { return order.items.reduce((sum, item) => sum + item.quantity, 0) } function asRecord(value: unknown): Record | null { return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record) : null } function parseOrderShipping(shippingAddress: Record) { const root = asRecord(shippingAddress) ?? {} const deliveryMode = root.deliveryMode === 'pickup' || root.deliveryMode === 'delivery' ? root.deliveryMode : root.province === 'Pickup' ? 'pickup' : 'delivery' const shipping = asRecord(root.shipping) const groupsRaw = Array.isArray(shipping?.groups) ? shipping.groups : [] const groups = groupsRaw .map((entry) => { const row = asRecord(entry) if (!row) return null const groupId = typeof row.groupId === 'string' ? row.groupId : '' if (!groupId) return null return { groupId, title: typeof row.title === 'string' ? row.title : '', methodLabel: typeof row.methodLabel === 'string' ? row.methodLabel : null, amount: typeof row.amount === 'number' && Number.isFinite(row.amount) ? row.amount : 0, itemNames: Array.isArray(row.itemNames) ? row.itemNames.filter((name): name is string => typeof name === 'string') : [], } }) .filter((group): group is NonNullable => Boolean(group)) const addressParts = [ typeof root.province === 'string' ? root.province : '', typeof root.city === 'string' ? root.city : '', typeof root.address === 'string' ? root.address : '', typeof root.postalCode === 'string' ? root.postalCode : '', ].filter((part) => part && part !== 'Pickup' && part !== 'Store' && part !== 'In-store pickup') return { deliveryMode, addressLine: addressParts.join(' · '), groups, } } export function OrderItemsModal({ open, order, onClose }: OrderItemsModalProps) { const t = useT() const [mounted, setMounted] = useState(open) const [closing, setClosing] = useState(false) 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 const itemCount = totalQuantity(order) return createPortal(
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="order-items-title" >

{t('orderItems.title')}

{order.orderNumber}

{t('orderItems.customer')}: {displayName(order)} {t('orderItems.phone')}:{' '} {formatCellForDisplay(order.customer.cellNumber)} {t('orderItems.items')}: {itemCount}
{(() => { const shippingInfo = parseOrderShipping(order.shippingAddress) return (
{t('orderItems.delivery')}
{shippingInfo.deliveryMode === 'pickup' ? (

{t('orderItems.pickup')}

) : shippingInfo.addressLine ? (

{shippingInfo.addressLine}

) : null} {shippingInfo.groups.length > 0 ? (
    {shippingInfo.groups.map((group) => (
  • {group.title} {group.amount > 0 ? formatIrtPrice(group.amount) : t('orderItems.freeShipping')}
    {group.methodLabel ? (
    {group.methodLabel}
    ) : null} {group.itemNames.length > 0 ? (
      {group.itemNames.map((name) => (
    • {name}
    • ))}
    ) : null}
  • ))}
) : null}
) })()} {order.items.length === 0 ? (

{t('orderItems.empty')}

) : (
    {order.items.map((item) => (
  • {item.productImage ? ( ) : (
    )}
    {item.productTitle}
    {formatVariantLabel(item.selections)}
    {item.variantSku && (
    {t('orderItems.sku', { sku: item.variantSku })}
    )}
    {item.quantity}
    {formatIrtPrice(item.unitPrice)}
    {formatIrtPrice(item.lineTotal)}
  • ))}
)}
{t('orderItems.subtotal')} {formatIrtPrice(order.subtotal)}
{t('orderItems.shipping')} {order.shippingTotal > 0 ? formatIrtPrice(order.shippingTotal) : t('orderItems.freeShipping')}
{order.discountTotal > 0 ? (
{t('orderItems.discount')} {formatIrtPrice(order.discountTotal)}
) : null}
{t('orderItems.summary', { count: itemCount, itemsLabel: itemCount === 1 ? t('orderItems.item') : t('orderItems.itemsPlural'), })} {formatIrtPrice(order.total)}
, document.body, ) }