DeFiCh/wallet

View on GitHub
mobile-app/app/components/TransactionCard.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import {
  ThemedProps,
  ThemedTextV2,
  ThemedTouchableOpacityV2,
  ThemedViewV2,
} from "@components/themed";
import BigNumber from "bignumber.js";
import { tailwind } from "@tailwind";
import { translate } from "@translations";
import { StyleProp, ViewStyle } from "react-native";
import { useState } from "react";

interface TransactionCardProps {
  maxValue: BigNumber;
  onChange: (amount: string, type: AmountButtonTypes) => void;
  status?: TransactionCardStatus;
  componentStyle?: ThemedProps & { style?: ThemedProps & StyleProp<ViewStyle> };
  containerStyle?: ThemedProps & { style?: ThemedProps & StyleProp<ViewStyle> };
  amountButtonsStyle?: ThemedProps & {
    style?: ThemedProps & StyleProp<ViewStyle>;
  };
  showAmountsBtn?: boolean;
  disabled?: boolean;
}

export enum AmountButtonTypes {
  TwentyFive = "25%",
  Half = "50%",
  SeventyFive = "75%",
  Max = "MAX",
}

export enum TransactionCardStatus {
  Default,
  Active,
  Error,
}

export function TransactionCard({
  maxValue,
  onChange,
  status,
  componentStyle,
  containerStyle,
  amountButtonsStyle,
  disabled,
  showAmountsBtn = true,
  children,
}: React.PropsWithChildren<TransactionCardProps>): JSX.Element {
  return (
    <ThemedViewV2
      light={
        componentStyle?.light ??
        tailwind("bg-mono-light-v2-00", {
          "border-0.5 border-mono-light-v2-800":
            status === TransactionCardStatus.Active,
        })
      }
      dark={
        componentStyle?.dark ??
        tailwind("bg-mono-dark-v2-00", {
          "border-0.5 border-mono-dark-v2-800":
            status === TransactionCardStatus.Active,
        })
      }
      style={[
        tailwind("rounded-lg-v2", {
          "border-0.5 border-red-v2": status === TransactionCardStatus.Error,
        }),
        componentStyle?.style,
      ]}
    >
      <ThemedViewV2
        light={containerStyle?.light ?? tailwind("bg-mono-light-v2-00")}
        dark={containerStyle?.dark ?? tailwind("bg-mono-dark-v2-00")}
        style={containerStyle?.style}
      >
        {children}
      </ThemedViewV2>
      {showAmountsBtn && (
        <ThemedViewV2
          light={
            amountButtonsStyle?.light ?? tailwind("border-mono-light-v2-300")
          }
          dark={amountButtonsStyle?.dark ?? tailwind("border-mono-dark-v2-300")}
          style={[
            tailwind("flex flex-row justify-center items-center py-2"),
            amountButtonsStyle?.style,
          ]}
        >
          {Object.values(AmountButtonTypes).map((type, index, { length }) => {
            return (
              <SetAmountButton
                key={type}
                amount={maxValue}
                onPress={onChange}
                type={type}
                hasBorder={length - 1 !== index}
                disabled={disabled}
              />
            );
          })}
        </ThemedViewV2>
      )}
    </ThemedViewV2>
  );
}

interface SetAmountButtonProps {
  type: AmountButtonTypes;
  onPress: (amount: string, type: AmountButtonTypes) => void;
  amount: BigNumber;
  hasBorder?: boolean;
  disabled?: boolean;
}

function SetAmountButton({
  type,
  onPress,
  amount,
  hasBorder,
  disabled,
}: SetAmountButtonProps): JSX.Element {
  const decimalPlace = 8;
  let value = amount.toFixed(decimalPlace);
  const [isPressed, setIsPressed] = useState(false);

  switch (type) {
    case AmountButtonTypes.TwentyFive:
      value = amount.multipliedBy(0.25).toFixed(decimalPlace);
      break;
    case AmountButtonTypes.Half:
      value = amount.multipliedBy(0.5).toFixed(decimalPlace);
      break;
    case AmountButtonTypes.SeventyFive:
      value = amount.multipliedBy(0.75).toFixed(decimalPlace);
      break;
    case AmountButtonTypes.Max:
      value = amount.toFixed(decimalPlace);
      break;
  }

  return (
    <ThemedTouchableOpacityV2
      style={tailwind("border-0")}
      onPress={() => {
        onPress(value, type);
      }}
      onPressIn={() => setIsPressed(true)}
      onPressOut={() => setIsPressed(false)}
      testID={`${type}_amount_button`}
      disabled={disabled}
    >
      <ThemedViewV2
        light={tailwind("border-mono-light-v2-300")}
        dark={tailwind("border-mono-dark-v2-300")}
        style={tailwind({ "border-r-0.5": hasBorder })}
      >
        <ThemedViewV2
          light={tailwind({
            "bg-mono-light-v2-100 rounded-lg-v2": isPressed,
          })}
          dark={tailwind({
            "bg-mono-dark-v2-100 rounded-lg-v2": isPressed,
          })}
          style={tailwind("mx-1")}
        >
          <ThemedTextV2
            light={tailwind("text-mono-light-v2-700", {
              "opacity-30": disabled,
            })}
            dark={tailwind("text-mono-dark-v2-700", {
              "opacity-30": disabled,
            })}
            style={tailwind("font-semibold-v2 text-xs px-6 py-1")}
          >
            {translate("component/max", type)}
          </ThemedTextV2>
        </ThemedViewV2>
      </ThemedViewV2>
    </ThemedTouchableOpacityV2>
  );
}