import { IFormatterNumberOptions } from "shared/model/types";
import { addParentheses } from "./addParentheses";
/**
* @param {(number | null | undefined)} value Money amount to be formatted.
* @param {Object} [options] Formatting options.
* @param {boolean} [options.currencySymbol = ""] Currency symbol.
* @param {number} [options.decimalPlaces = 2] Number of decimal places.
* @param {string} [options.decimalSeparator = "."] Decimal separator.
* @param {boolean} options.negativeClass Style class name for negative numbers.
* @param {boolean} [options.negativeInParentheses = true] Enclose negative numbers in parentheses.
* @param {boolean} [options.noHTML = false] Return plain text without HTML.
* @param {boolean} options.positiveClass Style class name for positive numbers.
* @param {string} [options.thousandsSeparator = ","] Thousands separator.
* @param {boolean} [options.zeroAsBlank = false] Display zero as en empty string.
* */
export function formatNumber(
value: number | string | null | undefined,
options: IFormatterNumberOptions = {},
): string {
const {
currencySymbol = "",
decimalPlaces = 2,
decimalSeparator = ".",
negativeClass,
negativeInParentheses = true,
noHTML = false,
positiveClass,
thousandsSeparator = ",",
zeroAsBlank = false,
} = options;
if (value === undefined || value === null || value === "") {
return "";
} else if (!Number(value) && zeroAsBlank) return "";
const isNegative = (Number(value) || 0) < 0;
const valueFixed = Math.abs(Number(value) || 0).toFixed(decimalPlaces);
const integerPart = parseInt(valueFixed).toString();
const remainder = integerPart.length > 3 ? integerPart.length % 3 : 0;
const withThousandsSeparator =
(remainder ? integerPart.slice(0, remainder) + thousandsSeparator : "") +
integerPart
.slice(remainder)
.replace(/(\d{3})(?=\d)/g, `$1${thousandsSeparator}`);
const withDecimalPlaces =
withThousandsSeparator +
(decimalPlaces ? decimalSeparator + valueFixed.slice(-decimalPlaces) : "");
const withCurrency = `${currencySymbol}${withDecimalPlaces}`;
const withMinus = isNegative ? `-${withCurrency}` : withCurrency;
const withParentheses =
isNegative && negativeInParentheses ? addParentheses(withMinus) : withMinus;
if (noHTML) {
return withParentheses;
} else if (isNegative) {
return negativeClass
? `${withParentheses}`
: withParentheses;
} else {
return positiveClass
? `${withParentheses}`
: withParentheses;
}
}