From 77515067c80e65e716055eacd74daa2ae1c5e92d Mon Sep 17 00:00:00 2001 From: Duddino <duddino@duddino.com> Date: Wed, 29 Jan 2025 14:31:19 +0100 Subject: [PATCH] Fix currency rounding (#524) * Handle currency in beautifyNumber and remove currency rounding in currency * Sneak in console log removal * Fix some locale issues --- scripts/dashboard/WalletBalance.vue | 9 +---- scripts/masternode/Masternode.vue | 1 - scripts/misc.js | 37 +++++++++++++------- tests/unit/misc.spec.js | 53 +++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 tests/unit/misc.spec.js diff --git a/scripts/dashboard/WalletBalance.vue b/scripts/dashboard/WalletBalance.vue index 788a2330a..68992a43e 100644 --- a/scripts/dashboard/WalletBalance.vue +++ b/scripts/dashboard/WalletBalance.vue @@ -117,14 +117,7 @@ const balanceValue = computed(() => { const nCoins = (publicMode.value ? balance : shieldBalance).value / COIN; const { nValue, cLocale } = optimiseCurrencyLocale(nCoins * price.value); - cLocale.minimumFractionDigits = 0; - cLocale.maximumFractionDigits = 0; - - return `${nValue.toLocaleString('en-gb', cLocale)}${beautifyNumber( - nValue.toFixed(2), - '13px', - false - )}`; + return `${beautifyNumber(nValue, '13px', cLocale)}`; }); const ticker = computed(() => cChainParams.current.TICKER); diff --git a/scripts/masternode/Masternode.vue b/scripts/masternode/Masternode.vue index 8a9949d2d..bef68b815 100644 --- a/scripts/masternode/Masternode.vue +++ b/scripts/masternode/Masternode.vue @@ -91,7 +91,6 @@ async function destroyMasternode() { * @param {import('../transaction.js').UTXO} utxo - Masternode utxo. Must be of exactly `cChainParams.current.collateralInSats` of value */ function importMasternode(privateKey, ip, utxo) { - console.log(privateKey, ip, utxo); const address = parseIpAddress(ip); if (!address) { createAlert('warning', ALERTS.MN_BAD_IP, 5000); diff --git a/scripts/misc.js b/scripts/misc.js index f5697d05e..7a25feb3b 100644 --- a/scripts/misc.js +++ b/scripts/misc.js @@ -310,29 +310,42 @@ export function sanitizeHTML(text) { /** * "Beautifies" a number with HTML, by displaying decimals in a lower opacity - * @param {string} strNumber - The number in String form to beautify + * @param {string} strNumber - The number in String form to beautify. This can contain a currency too. * @param {string?} strDecFontSize - The optional font size to display decimals in + * @param {Intl.NumberFormattingOptions} locale - Locale options to format with * @returns {string} - A HTML string with beautified number handling */ -export function beautifyNumber( - strNumber, - strDecFontSize = '', - showFirstNumber = true -) { - if (typeof strNumber === 'number') strNumber = strNumber.toString(); +export function beautifyNumber(strNumber, strDecFontSize = '', locale) { + if (typeof strNumber === 'number') + strNumber = strNumber.toLocaleString('en-gb', locale).replace(',', ''); // Only run this for numbers with decimals if (!strNumber.includes('.')) - return parseInt(strNumber).toLocaleString('en-GB'); + return parseInt(strNumber).toLocaleString('en-GB', locale); // Split the number in to Full and Decimal parts - const arrNumParts = strNumber.split('.'); + let arrNumParts = strNumber.split('.'); + + for (let i = 0; i < arrNumParts[0].length; i++) { + if (parseInt(arrNumParts[0][i])) { + // We have reached the end of the currency part + const currency = arrNumParts[0].slice(0, i); + let number = parseInt(arrNumParts[0].slice(i)).toLocaleString( + 'en-gb', + { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + } + ); + + arrNumParts[0] = [...currency, ...number].join(''); + break; + } + } // Return a HTML that renders the decimal in a lower opacity const strFontSize = strDecFontSize ? 'font-size: ' + strDecFontSize : ''; - return `${ - showFirstNumber ? parseInt(arrNumParts[0]).toLocaleString('en-GB') : '' - }<span style="opacity: 0.55; ${strFontSize}">.${arrNumParts[1]}</span>`; + return `${arrNumParts[0]}<span style="opacity: 0.55; ${strFontSize}">.${arrNumParts[1]}</span>`; } /** diff --git a/tests/unit/misc.spec.js b/tests/unit/misc.spec.js new file mode 100644 index 000000000..e8a77af01 --- /dev/null +++ b/tests/unit/misc.spec.js @@ -0,0 +1,53 @@ +import { describe, it, expect } from 'vitest'; +import { beautifyNumber } from '../../scripts/misc.js'; + +describe('beautifyNumber', () => { + it('should format a number without decimals correctly', () => { + expect(beautifyNumber(12345)).toBe('12,345'); + expect(beautifyNumber('12345')).toBe('12,345'); + }); + + it('should format a number with decimals and include HTML for the decimals', () => { + expect(beautifyNumber('12345.67')).toBe( + '12,345<span style="opacity: 0.55; ">.' + '67</span>' + ); + expect(beautifyNumber(12345.67)).toBe( + '12,345<span style="opacity: 0.55; ">.' + '67</span>' + ); + }); + + it('should handle numbers with a custom font size for the decimals', () => { + expect(beautifyNumber('12345.67', '14px')).toBe( + '12,345<span style="opacity: 0.55; font-size: 14px">.' + '67</span>' + ); + }); + + it('should handle numbers with leading 0 correctly', () => { + expect(beautifyNumber('0.67', '')).toBe( + '0<span style="opacity: 0.55; ">.' + '67</span>' + ); + }); + + it('should handle currency symbols correctly', () => { + expect(beautifyNumber('USD 0.67', '')).toBe( + 'USD 0<span style="opacity: 0.55; ">.' + '67</span>' + ); + expect(beautifyNumber('$1340139.67', '')).toBe( + '$1,340,139<span style="opacity: 0.55; ">.' + '67</span>' + ); + }); + + it('should handle edge cases gracefully', () => { + // Empty string input + expect(beautifyNumber('')).toBe('NaN'); + + // Zero as input + expect(beautifyNumber('0')).toBe('0'); + expect(beautifyNumber(0)).toBe('0'); + + // Negative number input + expect(beautifyNumber('-12345.67')).toBe( + '-12,345<span style="opacity: 0.55; ">.' + '67</span>' + ); + }); +});