github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/IntegerDisplay/index.tsx (about)

     1  import isNil from "lodash/isNil";
     2  import isObject from "lodash/isObject";
     3  
     4  type IntegerDisplayProps = {
     5    num: number | null;
     6    className?: string;
     7    startAt?: "k" | "100k" | "m";
     8    withTitle?: boolean;
     9  };
    10  
    11  // Adapted from https://stackoverflow.com/questions/42658221/vanilla-javascript-function-to-round-to-nearest-hundred-or-100k-plus-symbol
    12  // const truncate = (num: number) => {
    13  //   const p = Math.floor(Math.log(num) / Math.LN10);
    14  //   const l = Math.min(2, Math.ceil(p / 3));
    15  //   return (
    16  //     Math.pow(10, p - l * 3) * +(num / Math.pow(10, p)).toFixed(1) +
    17  //     ["", "k", "M"][l]
    18  //   );
    19  // };
    20  
    21  const ten_million = 10000000;
    22  const one_million = 1000000;
    23  const one_hundred_thousand = 100000;
    24  const one_thousand = 1000;
    25  
    26  const roundToThousands = (num) => {
    27    return (num / 1000).toFixed(1).replace(/\.0$/, "") + "k";
    28  };
    29  
    30  const roundToNearestThousand = (num) => {
    31    const toNearest1k = Math.round(num / one_thousand) * one_thousand;
    32    if (toNearest1k >= one_million) {
    33      return roundToMillions(num);
    34    }
    35    return roundToThousands(toNearest1k);
    36  };
    37  
    38  const roundToMillions = (num, fixedDigits = 2) => {
    39    return (num / one_million).toFixed(fixedDigits).replace(/\.0+$/, "") + "M";
    40  };
    41  
    42  const IntegerDisplay = ({
    43    num,
    44    className,
    45    startAt = "m",
    46    withTitle = true,
    47  }: IntegerDisplayProps) => {
    48    const levels = {
    49      k: one_thousand,
    50      "100k": one_hundred_thousand,
    51      m: one_million,
    52    };
    53    const numberFormatter = (num) => {
    54      if (isNil(num) || isObject(num)) {
    55        return;
    56      }
    57  
    58      const threshold = levels[startAt];
    59  
    60      if (threshold <= one_million && num >= ten_million) {
    61        return roundToMillions(num, 1);
    62      }
    63      if (threshold <= one_million && num >= one_million) {
    64        return roundToMillions(num);
    65      }
    66      if (threshold <= one_hundred_thousand && num >= one_hundred_thousand) {
    67        return roundToNearestThousand(num);
    68      }
    69      if (threshold <= one_thousand) {
    70        if (num >= one_million) {
    71          return roundToMillions(num);
    72        }
    73        if (num >= one_hundred_thousand) {
    74          return roundToNearestThousand(num);
    75        }
    76        if (num >= one_thousand) {
    77          return roundToThousands(num);
    78        }
    79      }
    80      // display number as-is but separated with commas
    81      return num.toLocaleString();
    82    };
    83    return (
    84      <span
    85        className={className}
    86        title={withTitle && num ? num.toLocaleString() : undefined}
    87      >
    88        {numberFormatter(num)}
    89      </span>
    90    );
    91  };
    92  
    93  export default IntegerDisplay;