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; } }