All files / src/features/TransactionPanel/components/history HistoryIcon.tsx

66.66% Statements 18/27
40% Branches 12/30
100% Functions 4/4
70.83% Lines 17/24

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                            52x                 52x             2x 2x 2x   2x   1x   1x   1x           2x           2x 2x             2x                       2x 1x             1x           2x                                
import { TransactionStatus } from "@features/TransactionPanel/types";
import { Box, Stack } from "@mui/material";
import { CheckIcon, XCircleIcon } from "@phosphor-icons/react";
import { useAppTheme } from "@theme/v2/Provider";
import { ReactNode, useMemo } from "react";
 
type Props = {
  status?: string;
  isLast: boolean;
  isFirst: boolean;
  isTransferFunds?: boolean;
  isRefund?: boolean;
};
 
const FAILURE_STATUSES = [
  "error",
  "declined",
  "chargeback",
  "voided",
  "processing_issue",
  "canceled",
];
 
const HistoryIcon = ({
  status = "default",
  isLast,
  isFirst,
  isTransferFunds,
  isRefund,
}: Props) => {
  const { palette } = useAppTheme();
  const inBetween = !(isFirst || isLast);
  const colorDensity = inBetween ? 25 : 50;
 
  const resolvedStatus: TransactionStatus = useMemo(() => {
    const isPendingRefund =
      isRefund && !["settled", "canceled"].includes(status);
 
    const shouldDefault = (isFirst && !isTransferFunds) || isPendingRefund;
 
    Eif (shouldDefault) return "default";
    if (status === "settled") return "settled";
    if (FAILURE_STATUSES.includes(status)) return "error";
    return "default";
  }, [status]);
 
  const iconColor = inBetween
    ? resolvedStatus === "settled"
      ? palette.primitive?.success[50]
      : palette.primitive?.error[50]
    : palette.icon?.["remain-light"];
 
  const renderIcon = (): ReactNode => {
    switch (resolvedStatus) {
      case "settled":
        return <CheckIcon color={iconColor} />;
      case "error":
        return <XCircleIcon color={iconColor} />;
      case "default":
      default:
        return (
          <Box
            width={8}
            height={8}
            borderRadius="50%"
            bgcolor={palette.icon?.["icon-secondary"]}
            zIndex={1}
          />
        );
    }
  };
 
  const backgroundColor = useMemo(() => {
    switch (resolvedStatus) {
      case "settled":
        return palette.primitive?.success[colorDensity];
      case "error":
        return palette.primitive?.error[colorDensity];
      case "default":
      default:
        return isLast
          ? palette.primitive?.transparent["darken-5"]
          : "transparent";
    }
  }, [resolvedStatus, isLast, colorDensity, palette]);
 
  return (
    <Stack
      width={24}
      height={24}
      justifyContent="center"
      alignItems="center"
      mb={1}
      bgcolor={backgroundColor}
      borderRadius="50%"
    >
      {renderIcon()}
    </Stack>
  );
};
 
export default HistoryIcon;