All files / src/features/Settlements/ReconciliationHub/components PerMerchantBreakdownTable.tsx

100% Statements 8/8
100% Branches 4/4
100% Functions 3/3
100% Lines 8/8

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                                                                      2x               2x 15x 15x   15x                                             180x                                                       14x                                               2x      
import { Skeleton, TableBody, TableRow } from "@mui/material";
import TableContainer from "@mui/material/TableContainer";
import GiveText from "@shared/Text/GiveText";
import { useCustomThemeV2 } from "@theme/hooks/useCustomThemeV2";
import { memo } from "react";
import {
  ReconciliationHubMerchantView,
  ReconciliationHubMerchantsTotals,
} from "../types";
import {
  Container,
  StyledBodyCell,
  StyledHeaderCell,
  StyledTable,
  StyledTableHead,
  StyledTableRow,
} from "../../styles";
import PerMerchantBreakdownRow from "./PerMerchantBreakdownRow";
import {
  AMOUNT_COLUMNS,
  COLUMN_COUNT,
  RATE_COLUMNS,
  renderAmountCells,
  renderRateCells,
} from "./PerMerchantBreakdown.constants";
 
interface Props {
  merchants: ReconciliationHubMerchantView[];
  totals?: ReconciliationHubMerchantsTotals | null;
  isLoading: boolean;
}
 
// First column (200px) + one cell per amount/rate column + the status column,
// all at the shared 136px desktop width. Sum drives the table's min width so it
// overflows the container (horizontal scroll) instead of compressing columns.
const TABLE_MIN_WIDTH = 200 + (COLUMN_COUNT - 1) * 136;
 
/**
 * The per-merchant breakdown table: a rounded, bordered container with fixed
 * column widths that scrolls horizontally, per-merchant rows, and a Totals row
 * inside the same bordered structure. Reuses the settlement table styling so it
 * matches the Cost Breakdown table in the same section.
 */
const PerMerchantBreakdownTable = memo(({ merchants, totals, isLoading }: Props) => {
  const { isLargeView } = useCustomThemeV2();
  const isMobileView = !isLargeView;
 
  return (
    <TableContainer
      component={Container}
      isMobileView={isMobileView}
      sx={{ marginTop: 0, marginBottom: 0, maxWidth: "100%" }}
    >
      <StyledTable
        aria-label="per merchant break down"
        isMobileView={isMobileView}
        sx={{ minWidth: TABLE_MIN_WIDTH }}
      >
        <StyledTableHead>
          <TableRow>
            <StyledHeaderCell
              isFirstColumn
              isMobileView={isMobileView}
              data-testid="hub-header-merchant"
            >
              <GiveText variant="bodyS" color="primary">
                Merchant
              </GiveText>
            </StyledHeaderCell>
            {[...AMOUNT_COLUMNS, ...RATE_COLUMNS].map((col) => (
              <StyledHeaderCell key={col.label} align="center" isMobileView={isMobileView}>
                <GiveText variant="bodyS" color="primary" textAlign="center">
                  {col.label}
                </GiveText>
              </StyledHeaderCell>
            ))}
            <StyledHeaderCell
              align="center"
              isMobileView={isMobileView}
              data-testid="hub-header-status"
            >
              <GiveText variant="bodyS" color="primary" textAlign="center">
                Reconciled Status
              </GiveText>
            </StyledHeaderCell>
          </TableRow>
        </StyledTableHead>
 
        <TableBody>
          {isLoading && (
            <StyledTableRow>
              <StyledBodyCell colSpan={COLUMN_COUNT} isMobileView={isMobileView}>
                <Skeleton variant="rectangular" height={24} />
              </StyledBodyCell>
            </StyledTableRow>
          )}
 
          {merchants.map((row) => (
            <PerMerchantBreakdownRow
              key={row.merchantAccID}
              row={row}
              isMobileView={isMobileView}
            />
          ))}
 
          {totals && (
            <StyledTableRow>
              <StyledBodyCell isFirstColumn isMobileView={isMobileView}>
                <GiveText variant="bodyS" color="primary">
                  Totals
                </GiveText>
              </StyledBodyCell>
              {renderAmountCells(totals, isMobileView)}
              {renderRateCells(totals, isMobileView)}
              <StyledBodyCell align="center" isMobileView={isMobileView} />
            </StyledTableRow>
          )}
        </TableBody>
      </StyledTable>
    </TableContainer>
  );
});
PerMerchantBreakdownTable.displayName = "PerMerchantBreakdownTable";
 
export default PerMerchantBreakdownTable;