All files / src/features/TransactionPanel/modals BinDetailsModal.tsx

100% Statements 9/9
100% Branches 16/16
100% Functions 2/2
100% Lines 9/9

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                        2x                               2x 5x 5x   5x       5x                                     5x   5x                       30x                                                    
import { Box, Stack } from "@mui/material";
import useNiceModal from "@common/Modal/ModalFactory/hooks/useNiceModal";
import NiceModal from "@ebay/nice-modal-react";
import GiveBaseModal from "@shared/modals/GiveBaseModal";
import GiveText from "@shared/Text/GiveText";
import { useAppTheme } from "@theme/v2/Provider";
import { capitalize } from "lodash";
import { cardIconsMap } from "features/MerchantPortal/ManageMoney/ManageMoneyTable.atoms";
import type { ReactNode } from "react";
import type { TCardBin } from "../types";
 
// Figma: unavailable fields render as a dash (AC002.3 / AC005.3).
const DASH = "-";
 
type Props = {
  bin?: Partial<TCardBin> | null;
  cardBrand?: string;
};
 
type Row = { label: string; value: string; icon?: ReactNode };
 
/**
 * TRA013 AC002 — read-only "Bank Identification Number" modal opened from the
 * Bank link in the Payment Method card. Rendered as a zebra-striped two-column
 * table (Figma): grey label on the left, value on the right, alternating row
 * backgrounds. Missing fields render as "-" (AC002.3). Keyboard + ESC
 * accessibility (AC002.4) is provided by GiveBaseModal's MUI Dialog.
 */
const BinDetailsModal = NiceModal.create(({ bin, cardBrand }: Props) => {
  const { open, onClose } = useNiceModal();
  const theme = useAppTheme();
 
  const brandIcon = cardBrand
    ? cardIconsMap()[cardBrand as keyof ReturnType<typeof cardIconsMap>]
    : undefined;
 
  const rows: Row[] = [
    { label: "Issuing Bank Name", value: bin?.issuingBankName || DASH },
    { label: "BIN", value: bin?.number || DASH },
    {
      label: "Card Brand",
      value: cardBrand ? capitalize(cardBrand) : DASH,
      icon: brandIcon,
    },
    {
      label: "Card Type",
      value: bin?.cardType ? capitalize(bin.cardType) : DASH,
    },
    { label: "Country of Issuance", value: bin?.countryOfIssuance || DASH },
    {
      label: "Card Category",
      value: bin?.cardCategory ? capitalize(bin.cardCategory) : DASH,
    },
  ];
 
  const stripeColor = theme.palette.surface?.secondary;
 
  return (
    <GiveBaseModal
      open={open}
      onClose={onClose}
      title="Bank Identification Number"
      width="648px"
      height="fit-content"
      showFooter={false}
      customContentPadding="72px 20px 20px 20px"
    >
      <Stack>
        {rows.map((row, index) => (
          <Box
            key={row.label}
            sx={{
              display: "grid",
              gridTemplateColumns: "1fr 1fr",
              alignItems: "center",
              columnGap: "16px",
              padding: "14px 24px",
              backgroundColor: index % 2 === 1 ? stripeColor : "transparent",
            }}
          >
            <GiveText variant="bodyS" color="secondary">
              {row.label}
            </GiveText>
            <Stack direction="row" spacing={1} alignItems="center">
              {row.icon}
              <GiveText variant="bodyS">{row.value}</GiveText>
            </Stack>
          </Box>
        ))}
      </Stack>
    </GiveBaseModal>
  );
});
 
export default BinDetailsModal;