All files / src/features/Events/EventDetail EventTransactionsTable.atoms.tsx

70.58% Statements 12/17
16.66% Branches 2/12
57.14% Functions 4/7
70.58% Lines 12/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127                                                                        5x                               5x 1x       1x                       5x 1x           5x 2x         5x 1x                       5x                                         5x                    
import { Stack } from "@mui/material";
import { TransactionTableRow } from "@components/ManageMoney/TransactionTable/transactions.types";
import { StatusTextColumn } from "@features/MerchantPortal/ManageMoney/ManageMoneyTable.atoms";
import GiveText from "@shared/Text/GiveText";
import GiveTruncateText from "@shared/Text/GiveTruncateText";
import { toEnFormat } from "@utils/index";
 
/**
 * PayBuilder 032-b AC006.1 — cell renderers for the Event Detail transactions
 * table. One renderer per column, matching the mockup exactly:
 * Date · Customer · Ticket Name · Price (USD) · Subtotal (USD) · Status.
 *
 * Status is intentionally absent here — it re-uses the shared
 * `PaymentFormStatusColumn` chip so every existing transaction status keeps
 * rendering the way it does everywhere else in the portal (AC006.2).
 */
 
export type EventTransactionRow = {
  createdAtTimestamp?: number;
  customer?: {
    firstName?: string;
    lastName?: string;
    email?: string;
  };
  product?: { variant?: { name?: string } };
  quantity?: number;
  unitPrice?: number;
  price?: number;
};
 
/** Matches the loose signature of `useFormatDateInTimezone().formatInTimezone`. */
type FormatInTimezone = (
  date: Date | string | number,
  format?: string,
) => string | number | Date | null;
 
export const DateColumn = (
  row: EventTransactionRow,
  formatInTimezone: FormatInTimezone,
) => {
  // A null/0 timestamp means "unset" — render nothing rather than 1970.
  const formatted = row.createdAtTimestamp
    ? formatInTimezone(row.createdAtTimestamp, "MMM d, yyyy HH:mm")
    : null;
 
  return (
    <GiveText variant="bodyS" color="primary">
      {formatted ? String(formatted) : ""}
    </GiveText>
  );
};
 
export const CustomerColumn = (row: EventTransactionRow) => {
  const fullName = [row.customer?.firstName, row.customer?.lastName]
    .filter(Boolean)
    .join(" ");
 
  return (
    <Stack minWidth={0}>
      <GiveTruncateText variant="bodyS" color="primary" lineClamp={1}>
        {fullName}
      </GiveTruncateText>
      <GiveTruncateText variant="bodyS" color="secondary" lineClamp={1}>
        {row.customer?.email}
      </GiveTruncateText>
    </Stack>
  );
};
 
export const TicketNameColumn = (row: EventTransactionRow) => (
  <GiveTruncateText variant="bodyS" color="primary" lineClamp={1}>
    {row.product?.variant?.name}
  </GiveTruncateText>
);
 
/** "2 × 50.00" — quantity times the unit price, as shown in the mockup. */
export const PriceColumn = (row: EventTransactionRow) => (
  <GiveText variant="bodyS" color="primary">
    {`${row.quantity ?? 0} × ${toEnFormat(row.unitPrice)}`}
  </GiveText>
);
 
export const SubtotalColumn = (row: EventTransactionRow) => (
  <Stack flexGrow={1} alignItems="flex-end">
    <GiveText variant="bodyS" color="primary">
      {toEnFormat(row.price)}
    </GiveText>
  </Stack>
);
 
/**
 * Below `v2_sm` the mockup drops the column grid for a two-part row: date,
 * ticket name and a plain-text status on the left, totals on the right. The
 * chevron is added by the table itself.
 */
export const MobileDescriptionColumn = (
  row: EventTransactionRow,
  formatInTimezone: FormatInTimezone,
) => {
  const formatted = row.createdAtTimestamp
    ? formatInTimezone(row.createdAtTimestamp, "MMM d, yyyy HH:mm")
    : null;
 
  return (
    <Stack gap="4px" minWidth={0}>
      <GiveText variant="bodyS" color="primary">
        {formatted ? String(formatted) : ""}
      </GiveText>
      <GiveTruncateText variant="bodyS" color="secondary" lineClamp={1}>
        {row.product?.variant?.name}
      </GiveTruncateText>
      <StatusTextColumn row={row as TransactionTableRow} />
    </Stack>
  );
};
 
export const MobileAmountColumn = (row: EventTransactionRow) => (
  <Stack flexGrow={1} alignItems="flex-end" gap="4px">
    <GiveText variant="bodyS" color="primary">
      {`${toEnFormat(row.price)} USD`}
    </GiveText>
    <GiveText variant="bodyXS" color="secondary">
      {`${row.quantity ?? 0} × ${toEnFormat(row.unitPrice)}`}
    </GiveText>
  </Stack>
);