From 27f8c90dae8e64a47a2a2f98b1544dd77f8abe4c Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sat, 4 Jan 2025 14:47:52 +0800 Subject: [PATCH] migrate numeral.js to ts --- src/components/desktop/PieChart.vue | 2 +- src/components/mobile/PieChart.vue | 2 +- src/consts/numeral.js | 168 ------------------ src/consts/numeral.ts | 2 + src/core/numeral.ts | 161 +++++++++++++++++ src/lib/i18n.js | 44 ++--- src/lib/{numeral.js => numeral.ts} | 114 ++++++------ src/stores/exchangeRates.js | 2 +- src/stores/transaction.js | 2 +- src/views/desktop/ExchangeRatesPage.vue | 2 +- .../desktop/statistics/TransactionPage.vue | 2 +- src/views/desktop/transactions/ListPage.vue | 6 +- src/views/mobile/ExchangeRatesPage.vue | 2 +- .../mobile/statistics/TransactionPage.vue | 2 +- .../mobile/transactions/AmountFilterPage.vue | 20 +-- src/views/mobile/transactions/ListPage.vue | 4 +- 16 files changed, 269 insertions(+), 266 deletions(-) delete mode 100644 src/consts/numeral.js create mode 100644 src/consts/numeral.ts create mode 100644 src/core/numeral.ts rename src/lib/{numeral.js => numeral.ts} (59%) diff --git a/src/components/desktop/PieChart.vue b/src/components/desktop/PieChart.vue index ccdc9b22..458943fb 100644 --- a/src/components/desktop/PieChart.vue +++ b/src/components/desktop/PieChart.vue @@ -12,7 +12,7 @@ import { useUserStore } from '@/stores/user.js'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts'; import { ThemeType } from '@/core/theme.ts'; -import { formatPercent } from '@/lib/numeral.js'; +import { formatPercent } from '@/lib/numeral.ts'; export default { props: [ diff --git a/src/components/mobile/PieChart.vue b/src/components/mobile/PieChart.vue index 72585863..04007bb8 100644 --- a/src/components/mobile/PieChart.vue +++ b/src/components/mobile/PieChart.vue @@ -82,7 +82,7 @@ import { useSettingsStore } from '@/stores/setting.js'; import { useUserStore } from '@/stores/user.js'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts'; -import { formatPercent } from '@/lib/numeral.js'; +import { formatPercent } from '@/lib/numeral.ts'; export default { props: [ diff --git a/src/consts/numeral.js b/src/consts/numeral.js deleted file mode 100644 index 3143af1f..00000000 --- a/src/consts/numeral.js +++ /dev/null @@ -1,168 +0,0 @@ -const allDecimalSeparator = { - Dot: { - type: 1, - name: 'Dot', - symbol: '.' - }, - Comma: { - type: 2, - name: 'Comma', - symbol: ',' - }, - Space: { - type: 3, - name: 'Space', - symbol: ' ' - } -}; - -const allDecimalSeparatorArray = [ - allDecimalSeparator.Dot, - allDecimalSeparator.Comma, - allDecimalSeparator.Space -]; - -const allDecimalSeparatorMap = { - [allDecimalSeparator.Dot.type]: allDecimalSeparator.Dot, - [allDecimalSeparator.Comma.type]: allDecimalSeparator.Comma, - [allDecimalSeparator.Space.type]: allDecimalSeparator.Space -}; - -const allDigitGroupingSymbol = { - Dot: { - type: 1, - name: 'Dot', - symbol: '.' - }, - Comma: { - type: 2, - name: 'Comma', - symbol: ',' - }, - Space: { - type: 3, - name: 'Space', - symbol: ' ' - }, - Apostrophe: { - type: 4, - name: 'Apostrophe', - symbol: '\'' - } -}; - -const allDigitGroupingSymbolArray = [ - allDigitGroupingSymbol.Dot, - allDigitGroupingSymbol.Comma, - allDigitGroupingSymbol.Space, - allDigitGroupingSymbol.Apostrophe -]; - -const allDigitGroupingSymbolMap = { - [allDigitGroupingSymbol.Dot.type]: allDigitGroupingSymbol.Dot, - [allDigitGroupingSymbol.Comma.type]: allDigitGroupingSymbol.Comma, - [allDigitGroupingSymbol.Space.type]: allDigitGroupingSymbol.Space, - [allDigitGroupingSymbol.Apostrophe.type]: allDigitGroupingSymbol.Apostrophe -}; - -const allDigitGroupingType = { - None: { - type: 1, - enabled: false, - name: 'None' - }, - ThousandsSeparator: { - type: 2, - enabled: true, - name: 'Thousands Separator' - } -}; - -const allDigitGroupingTypeArray = [ - allDigitGroupingType.None, - allDigitGroupingType.ThousandsSeparator -]; - -const allDigitGroupingTypeMap = { - [allDigitGroupingType.None.type]: allDigitGroupingType.None, - [allDigitGroupingType.ThousandsSeparator.type]: allDigitGroupingType.ThousandsSeparator -}; - -const allAmountFilterType = { - GreaterThan: { - type: 'gt', - name: 'Greater than', - paramCount: 1 - }, - LessThan:{ - type: 'lt', - name: 'Less than', - paramCount: 1 - }, - EqualTo:{ - type: 'eq', - name: 'Equal to', - paramCount: 1 - }, - NotEqualTo:{ - type: 'ne', - name: 'Not equal to', - paramCount: 1 - }, - Between:{ - type: 'bt', - name: 'Between', - paramCount: 2 - }, - NotBetween:{ - type: 'nb', - name: 'Not between', - paramCount: 2 - } -}; - -const allAmountFilterTypeArray = [ - allAmountFilterType.GreaterThan, - allAmountFilterType.LessThan, - allAmountFilterType.EqualTo, - allAmountFilterType.NotEqualTo, - allAmountFilterType.Between, - allAmountFilterType.NotBetween, -]; - -const allAmountFilterTypeMap = { - [allAmountFilterType.GreaterThan.type]: allAmountFilterType.GreaterThan, - [allAmountFilterType.LessThan.type]: allAmountFilterType.LessThan, - [allAmountFilterType.EqualTo.type]: allAmountFilterType.EqualTo, - [allAmountFilterType.NotEqualTo.type]: allAmountFilterType.NotEqualTo, - [allAmountFilterType.Between.type]: allAmountFilterType.Between, - [allAmountFilterType.NotBetween.type]: allAmountFilterType.NotBetween -}; - -const defaultDecimalSeparator = allDecimalSeparator.Dot; -const defaultDecimalNumberCount = 2; -const maxSupportedDecimalNumberCount = 2; -const defaultDigitGroupingSymbol = allDigitGroupingSymbol.Comma; -const defaultDigitGroupingType = allDigitGroupingType.ThousandsSeparator; -const defaultValue = 0; - -export default { - allDecimalSeparator: allDecimalSeparator, - allDecimalSeparatorArray: allDecimalSeparatorArray, - allDecimalSeparatorMap: allDecimalSeparatorMap, - allDigitGroupingSymbol: allDigitGroupingSymbol, - allDigitGroupingSymbolArray: allDigitGroupingSymbolArray, - allDigitGroupingSymbolMap: allDigitGroupingSymbolMap, - allDigitGroupingType: allDigitGroupingType, - allDigitGroupingTypeArray: allDigitGroupingTypeArray, - allDigitGroupingTypeMap: allDigitGroupingTypeMap, - allAmountFilterType: allAmountFilterType, - allAmountFilterTypeArray: allAmountFilterTypeArray, - allAmountFilterTypeMap: allAmountFilterTypeMap, - defaultDecimalSeparator: defaultDecimalSeparator, - defaultDecimalNumberCount: defaultDecimalNumberCount, - maxSupportedDecimalNumberCount: maxSupportedDecimalNumberCount, - defaultDigitGroupingSymbol: defaultDigitGroupingSymbol, - defaultDigitGroupingType: defaultDigitGroupingType, - defaultValue: defaultValue, -}; diff --git a/src/consts/numeral.ts b/src/consts/numeral.ts new file mode 100644 index 00000000..52585d93 --- /dev/null +++ b/src/consts/numeral.ts @@ -0,0 +1,2 @@ +export const DEFAULT_DECIMAL_NUMBER_COUNT: number = 2; +export const MAX_SUPPORTED_DECIMAL_NUMBER_COUNT: number = 2; diff --git a/src/core/numeral.ts b/src/core/numeral.ts new file mode 100644 index 00000000..6d2950a0 --- /dev/null +++ b/src/core/numeral.ts @@ -0,0 +1,161 @@ +import type { TypeAndName } from '@/core/base.ts'; + +export interface NumberFormatOptions { + digitGrouping?: number; + digitGroupingSymbol?: string; + decimalNumberCount?: number; + decimalSeparator?: string; + trimTailZero?: boolean; +} + +export class DecimalSeparator implements TypeAndName { + private static readonly allInstances: DecimalSeparator[] = []; + private static readonly allInstancesByType: Record = {}; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly LanguageDefaultType: number = 0; + public static readonly Dot = new DecimalSeparator(1, 'Dot', '.'); + public static readonly Comma = new DecimalSeparator(2, 'Comma', ','); + public static readonly Space = new DecimalSeparator(3, 'Space', ' '); + + public static readonly Default = DecimalSeparator.Dot; + + public readonly type: number; + public readonly name: string; + public readonly symbol: string; + + private constructor(type: number, name: string, symbol: string) { + this.type = type; + this.name = name; + this.symbol = symbol; + + DecimalSeparator.allInstances.push(this); + DecimalSeparator.allInstancesByType[type] = this; + DecimalSeparator.allInstancesByTypeName[name] = this; + } + + public static values(): DecimalSeparator[] { + return DecimalSeparator.allInstances; + } + + public static valueOf(type: number): DecimalSeparator { + return DecimalSeparator.allInstancesByType[type]; + } + + public static parse(typeName: string): DecimalSeparator { + return DecimalSeparator.allInstancesByTypeName[typeName]; + } +} + +export class DigitGroupingSymbol implements TypeAndName { + private static readonly allInstances: DigitGroupingSymbol[] = []; + private static readonly allInstancesByType: Record = {}; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly LanguageDefaultType: number = 0; + public static readonly Dot = new DigitGroupingSymbol(1, 'Dot', '.'); + public static readonly Comma = new DigitGroupingSymbol(2, 'Comma', ','); + public static readonly Space = new DigitGroupingSymbol(3, 'Space', ' '); + public static readonly Apostrophe = new DigitGroupingSymbol(4, 'Apostrophe', '\''); + + public static readonly Default = DigitGroupingSymbol.Comma; + + public readonly type: number; + public readonly name: string; + public readonly symbol: string; + + private constructor(type: number, name: string, symbol: string) { + this.type = type; + this.name = name; + this.symbol = symbol; + + DigitGroupingSymbol.allInstances.push(this); + DigitGroupingSymbol.allInstancesByType[type] = this; + DigitGroupingSymbol.allInstancesByTypeName[name] = this; + } + + public static values(): DigitGroupingSymbol[] { + return DigitGroupingSymbol.allInstances; + } + + public static valueOf(type: number): DigitGroupingSymbol { + return DigitGroupingSymbol.allInstancesByType[type]; + } + + public static parse(typeName: string): DigitGroupingSymbol { + return DigitGroupingSymbol.allInstancesByTypeName[typeName]; + } +} + +export class DigitGroupingType implements TypeAndName { + private static readonly allInstances: DigitGroupingType[] = []; + private static readonly allInstancesByType: Record = {}; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly LanguageDefaultType: number = 0; + public static readonly None = new DigitGroupingType(1, 'None', 'None', false); + public static readonly ThousandsSeparator = new DigitGroupingType(2, 'ThousandsSeparator', 'Thousands Separator', true); + + public static readonly Default = DigitGroupingType.ThousandsSeparator; + + public readonly type: number; + public readonly typeName: string; + public readonly name: string; + public readonly enabled: boolean; + + private constructor(type: number, typeName: string, name: string, enabled: boolean) { + this.type = type; + this.typeName = typeName; + this.name = name; + this.enabled = enabled; + + DigitGroupingType.allInstances.push(this); + DigitGroupingType.allInstancesByType[type] = this; + DigitGroupingType.allInstancesByTypeName[typeName] = this; + } + + public static values(): DigitGroupingType[] { + return DigitGroupingType.allInstances; + } + + public static valueOf(type: number): DigitGroupingType { + return DigitGroupingType.allInstancesByType[type]; + } + + public static parse(typeName: string): DigitGroupingType { + return DigitGroupingType.allInstancesByTypeName[typeName]; + } +} + +export class AmountFilterType { + private static readonly allInstances: AmountFilterType[] = []; + private static readonly allInstancesByType: Record = {}; + + public static readonly GreaterThan = new AmountFilterType('gt', 'Greater than', 1); + public static readonly LessThan = new AmountFilterType('lt', 'Less than', 1); + public static readonly EqualTo = new AmountFilterType('eq', 'Equal to', 1); + public static readonly NotEqualTo = new AmountFilterType('ne', 'Not equal to', 1); + public static readonly Between = new AmountFilterType('bt', 'Between', 2); + public static readonly NotBetween = new AmountFilterType('nb', 'Not between', 2); + + public readonly type: string; + public readonly name: string; + public readonly paramCount: number; + + private constructor(type: string, name: string, paramCount: number) { + this.type = type; + this.name = name; + this.paramCount = paramCount; + + AmountFilterType.allInstances.push(this); + AmountFilterType.allInstancesByType[type] = this; + } + + public static values(): AmountFilterType[] { + return AmountFilterType.allInstances; + } + + public static valueOf(type: string): AmountFilterType { + return AmountFilterType.allInstancesByType[type]; + } +} diff --git a/src/lib/i18n.js b/src/lib/i18n.js index 529b666f..67ccf40d 100644 --- a/src/lib/i18n.js +++ b/src/lib/i18n.js @@ -4,6 +4,7 @@ import { defaultLanguage, allLanguages } from '@/locales/index.ts'; import { Month, WeekDay, MeridiemIndicator, LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat, DateRangeScene, DateRange, LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE } from '@/core/datetime.ts'; import { TimezoneTypeForStatistics } from '@/core/timezone.ts'; +import { DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts'; import { CurrencyDisplayType, CurrencySortingType } from '@/core/currency.ts'; import { PresetAmountColor } from '@/core/color.ts'; import { AccountType, AccountCategory } from '@/core/account.ts'; @@ -11,7 +12,6 @@ import { CategoryType } from '@/core/category.ts'; import { TransactionEditScopeType, TransactionTagFilterType } from '@/core/transaction.ts'; import { ScheduledTemplateFrequencyType } from '@/core/template.ts'; -import numeralConstants from '@/consts/numeral.js'; import { UTC_TIMEZONE, ALL_TIMEZONES } from '@/consts/timezone.ts'; import { ALL_CURRENCIES } from '@/consts/currency.ts'; import { SUPPORTED_IMPORT_FILE_TYPES } from '@/consts/file.ts'; @@ -51,7 +51,7 @@ import { formatAmount, formatExchangeRateAmount, getAdaptiveDisplayAmountRate -} from './numeral.js'; +} from './numeral.ts'; import { getCurrencyFraction, @@ -802,16 +802,16 @@ function getAllTimezoneTypesUsedForStatistics(currentTimezone, translateFn) { function getAllDecimalSeparators(translateFn) { const defaultDecimalSeparatorTypeName = translateFn('default.decimalSeparator'); - return getNumeralSeparatorFormats(translateFn, numeralConstants.allDecimalSeparator, numeralConstants.allDecimalSeparatorArray, defaultDecimalSeparatorTypeName, numeralConstants.defaultDecimalSeparator); + return getNumeralSeparatorFormats(translateFn, DecimalSeparator.values(), DecimalSeparator.parse(defaultDecimalSeparatorTypeName), DecimalSeparator.Default, DecimalSeparator.LanguageDefaultType); } function getAllDigitGroupingSymbols(translateFn) { const defaultDigitGroupingSymbolTypeName = translateFn('default.digitGroupingSymbol'); - return getNumeralSeparatorFormats(translateFn, numeralConstants.allDigitGroupingSymbol, numeralConstants.allDigitGroupingSymbolArray, defaultDigitGroupingSymbolTypeName, numeralConstants.defaultDigitGroupingSymbol); + return getNumeralSeparatorFormats(translateFn, DigitGroupingSymbol.values(), DigitGroupingSymbol.parse(defaultDigitGroupingSymbolTypeName), DigitGroupingSymbol.Default, DigitGroupingSymbol.LanguageDefaultType); } -function getNumeralSeparatorFormats(translateFn, allSeparatorMap, allSeparatorArray, localeDefaultTypeName, systemDefaultType) { - let defaultSeparatorType = allSeparatorMap[localeDefaultTypeName]; +function getNumeralSeparatorFormats(translateFn, allSeparatorArray, localeDefaultType, systemDefaultType, languageDefaultValue) { + let defaultSeparatorType = localeDefaultType; if (!defaultSeparatorType) { defaultSeparatorType = systemDefaultType; @@ -820,7 +820,7 @@ function getNumeralSeparatorFormats(translateFn, allSeparatorMap, allSeparatorAr const ret = []; ret.push({ - type: numeralConstants.defaultValue, + type: languageDefaultValue, symbol: defaultSeparatorType.symbol, displayName: `${translateFn('Language Default')} (${defaultSeparatorType.symbol})` }); @@ -840,22 +840,24 @@ function getNumeralSeparatorFormats(translateFn, allSeparatorMap, allSeparatorAr function getAllDigitGroupingTypes(translateFn) { const defaultDigitGroupingTypeName = translateFn('default.digitGrouping'); - let defaultDigitGroupingType = numeralConstants.allDigitGroupingType[defaultDigitGroupingTypeName]; + let defaultDigitGroupingType = DigitGroupingType.parse(defaultDigitGroupingTypeName); if (!defaultDigitGroupingType) { - defaultDigitGroupingType = numeralConstants.defaultDigitGroupingType; + defaultDigitGroupingType = DigitGroupingType.Default; } const ret = []; ret.push({ - type: numeralConstants.defaultValue, + type: DigitGroupingType.LanguageDefaultType, enabled: defaultDigitGroupingType.enabled, displayName: `${translateFn('Language Default')} (${translateFn('numeral.' + defaultDigitGroupingType.name)})` }); - for (let i = 0; i < numeralConstants.allDigitGroupingTypeArray.length; i++) { - const type = numeralConstants.allDigitGroupingTypeArray[i]; + const allDigitGroupingTypes = DigitGroupingType.values(); + + for (let i = 0; i < allDigitGroupingTypes.length; i++) { + const type = allDigitGroupingTypes[i]; ret.push({ type: type.type, @@ -906,14 +908,14 @@ function getAllCurrencySortingTypes(translateFn) { } function getCurrentDecimalSeparator(translateFn, decimalSeparator) { - let decimalSeparatorType = numeralConstants.allDecimalSeparatorMap[decimalSeparator]; + let decimalSeparatorType = DecimalSeparator.valueOf(decimalSeparator); if (!decimalSeparatorType) { const defaultDecimalSeparatorTypeName = translateFn('default.decimalSeparator'); - decimalSeparatorType = numeralConstants.allDecimalSeparator[defaultDecimalSeparatorTypeName]; + decimalSeparatorType = DecimalSeparator.parse(defaultDecimalSeparatorTypeName); if (!decimalSeparatorType) { - decimalSeparatorType = numeralConstants.defaultDecimalSeparator; + decimalSeparatorType = DecimalSeparator.Default; } } @@ -921,14 +923,14 @@ function getCurrentDecimalSeparator(translateFn, decimalSeparator) { } function getCurrentDigitGroupingSymbol(translateFn, digitGroupingSymbol) { - let digitGroupingSymbolType = numeralConstants.allDigitGroupingSymbolMap[digitGroupingSymbol]; + let digitGroupingSymbolType = DigitGroupingSymbol.valueOf(digitGroupingSymbol); if (!digitGroupingSymbolType) { const defaultDigitGroupingSymbolTypeName = translateFn('default.digitGroupingSymbol'); - digitGroupingSymbolType = numeralConstants.allDigitGroupingSymbol[defaultDigitGroupingSymbolTypeName]; + digitGroupingSymbolType = DigitGroupingSymbol.parse(defaultDigitGroupingSymbolTypeName); if (!digitGroupingSymbolType) { - digitGroupingSymbolType = numeralConstants.defaultDigitGroupingSymbol; + digitGroupingSymbolType = DigitGroupingSymbol.Default; } } @@ -936,14 +938,14 @@ function getCurrentDigitGroupingSymbol(translateFn, digitGroupingSymbol) { } function getCurrentDigitGroupingType(translateFn, digitGrouping) { - let digitGroupingType = numeralConstants.allDigitGroupingTypeMap[digitGrouping]; + let digitGroupingType = DigitGroupingType.valueOf(digitGrouping); if (!digitGroupingType) { const defaultDigitGroupingTypeName = translateFn('default.digitGrouping'); - digitGroupingType = numeralConstants.allDigitGroupingType[defaultDigitGroupingTypeName]; + digitGroupingType = DigitGroupingType.parse(defaultDigitGroupingTypeName); if (!digitGroupingType) { - digitGroupingType = numeralConstants.defaultDigitGroupingType; + digitGroupingType = DigitGroupingType.Default; } } diff --git a/src/lib/numeral.js b/src/lib/numeral.ts similarity index 59% rename from src/lib/numeral.js rename to src/lib/numeral.ts index 977803bf..779171d4 100644 --- a/src/lib/numeral.js +++ b/src/lib/numeral.ts @@ -1,56 +1,61 @@ -import numeralConstants from '@/consts/numeral.js'; +import { type NumberFormatOptions, DecimalSeparator, DigitGroupingSymbol, DigitGroupingType} from '@/core/numeral.ts'; +import { DEFAULT_DECIMAL_NUMBER_COUNT, MAX_SUPPORTED_DECIMAL_NUMBER_COUNT } from '@/consts/numeral.ts'; import { isString, isNumber, removeAll } from './common.ts'; -export function appendDigitGroupingSymbol(value, options) { +export function appendDigitGroupingSymbol(value: number | string, options: NumberFormatOptions): string { + let textualValue = ''; + if (isNumber(value)) { - value = value.toString(); + textualValue = value.toString(); + } else { + textualValue = value as string; } - if (!isString(value)) { - return value; + if (!textualValue) { + return textualValue; } if (!options) { options = {}; } - if (!isNumber(options.digitGrouping) || options.digitGrouping === numeralConstants.allDigitGroupingType.None.type) { - return value; + if (!isNumber(options.digitGrouping) || options.digitGrouping === DigitGroupingType.None.type) { + return textualValue; } - if (value.length <= 3) { - return value; + if (textualValue.length <= 3) { + return textualValue; } - const negative = value.charAt(0) === '-'; + const negative = textualValue.charAt(0) === '-'; if (negative) { - value = value.substring(1); + textualValue = textualValue.substring(1); } - const digitGroupingSymbol = options.digitGroupingSymbol || numeralConstants.defaultDigitGroupingSymbol.symbol; - const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol; + const digitGroupingSymbol = options.digitGroupingSymbol || DigitGroupingSymbol.Default.symbol; + const decimalSeparator = options.decimalSeparator || DecimalSeparator.Default.symbol; let integerChars = []; let currentDecimalSeparator = ''; let decimals = ''; - for (let i = 0; i < value.length; i++) { - const ch = value.charAt(i); + for (let i = 0; i < textualValue.length; i++) { + const ch = textualValue.charAt(i); if ('0' <= ch && ch <= '9') { integerChars.push(ch); } else { currentDecimalSeparator = ch; - decimals = value.substring(i + 1); + decimals = textualValue.substring(i + 1); break; } } let newInteger = ''; - if (options.digitGrouping === numeralConstants.allDigitGroupingType.ThousandsSeparator.type) { + if (options.digitGrouping === DigitGroupingType.ThousandsSeparator.type) { for (let i = integerChars.length - 1, j = 0; i >= 0; i--, j++) { if (j % 3 === 0 && j > 0) { newInteger = digitGroupingSymbol + newInteger; @@ -71,9 +76,9 @@ export function appendDigitGroupingSymbol(value, options) { } } -export function parseAmount(str, options) { +export function parseAmount(str: string, options: NumberFormatOptions): number { if (!isString(str)) { - return str; + return 0; } if (!options) { @@ -96,8 +101,8 @@ export function parseAmount(str, options) { const sign = negative ? -1 : 1; - const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol; - const digitGroupingSymbol = options.digitGroupingSymbol || numeralConstants.defaultDigitGroupingSymbol.symbol; + const decimalSeparator = options.decimalSeparator || DecimalSeparator.Default.symbol; + const digitGroupingSymbol = options.digitGroupingSymbol || DigitGroupingSymbol.Default.symbol; if (str.indexOf(digitGroupingSymbol) >= 0) { str = removeAll(str, digitGroupingSymbol); @@ -126,42 +131,46 @@ export function parseAmount(str, options) { } } -export function formatAmount(value, options) { +export function formatAmount(value: number | string, options: NumberFormatOptions): string { + let textualValue = ''; + if (isNumber(value)) { - value = value.toString(); + textualValue = value.toString(); + } else { + textualValue = value as string; } - if (!isString(value)) { - return value; + if (!textualValue) { + return textualValue; } if (!options) { options = {}; } - const negative = value.charAt(0) === '-'; + const negative = textualValue.charAt(0) === '-'; if (negative) { - value = value.substring(1); + textualValue = textualValue.substring(1); } - const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol; + const decimalSeparator = options.decimalSeparator || DecimalSeparator.Default.symbol; let decimalNumberCount = options.decimalNumberCount; - if (!isNumber(decimalNumberCount) || decimalNumberCount > numeralConstants.maxSupportedDecimalNumberCount) { - decimalNumberCount = numeralConstants.defaultDecimalNumberCount; + if (!isNumber(decimalNumberCount) || (decimalNumberCount as number) > MAX_SUPPORTED_DECIMAL_NUMBER_COUNT) { + decimalNumberCount = DEFAULT_DECIMAL_NUMBER_COUNT; } let integer = '0'; let decimals = '00'; - if (value.length > 2) { - integer = value.substring(0, value.length - 2); - decimals = value.substring(value.length - 2); - } else if (value.length === 2) { - decimals = value; - } else if (value.length === 1) { - decimals = '0' + value; + if (textualValue.length > 2) { + integer = textualValue.substring(0, textualValue.length - 2); + decimals = textualValue.substring(textualValue.length - 2); + } else if (textualValue.length === 2) { + decimals = textualValue; + } else if (textualValue.length === 1) { + decimals = '0' + textualValue; } if (decimalNumberCount === 0) { @@ -187,19 +196,19 @@ export function formatAmount(value, options) { integer = appendDigitGroupingSymbol(integer, options); if (decimals !== '') { - value = `${integer}${decimalSeparator}${decimals}`; + textualValue = `${integer}${decimalSeparator}${decimals}`; } else { - value = integer; + textualValue = integer; } if (negative) { - value = `-${value}`; + textualValue = `-${textualValue}`; } - return value; + return textualValue; } -export function formatPercent(value, precision, lowPrecisionValue) { +export function formatPercent(value: number, precision: number, lowPrecisionValue: string): string { const ratio = Math.pow(10, precision); const normalizedValue = Math.floor(value * ratio); @@ -211,7 +220,7 @@ export function formatPercent(value, precision, lowPrecisionValue) { return result + '%'; } -export function getAmountWithDecimalNumberCount(amount, decimalNumberCount) { +export function getAmountWithDecimalNumberCount(amount: number, decimalNumberCount: number): number { if (decimalNumberCount === 0) { return Math.floor(amount / 100) * 100; } else if (decimalNumberCount === 1) { @@ -221,13 +230,13 @@ export function getAmountWithDecimalNumberCount(amount, decimalNumberCount) { return amount; } -export function formatExchangeRateAmount(exchangeRateAmount, options) { +export function formatExchangeRateAmount(exchangeRateAmount: number | string, options: NumberFormatOptions): string { if (!options) { options = {}; } const rateStr = exchangeRateAmount.toString(); - const decimalSeparator = numeralConstants.allDecimalSeparator.Dot.symbol; + const decimalSeparator = DecimalSeparator.Dot.symbol; if (rateStr.indexOf(decimalSeparator) < 0) { return appendDigitGroupingSymbol(rateStr, options); @@ -246,19 +255,16 @@ export function formatExchangeRateAmount(exchangeRateAmount, options) { } } -export function getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, options) { +export function getAdaptiveDisplayAmountRate(amount1: number, amount2: number, fromExchangeRate: { rate: string }, toExchangeRate: { rate: string }, options: NumberFormatOptions): string | null { if (!amount1 || !amount2 || amount1 === amount2) { if (!fromExchangeRate || !fromExchangeRate.rate || !toExchangeRate || !toExchangeRate.rate) { return null; } - amount1 = fromExchangeRate.rate; - amount2 = toExchangeRate.rate; + amount1 = parseFloat(fromExchangeRate.rate); + amount2 = parseFloat(toExchangeRate.rate); } - amount1 = parseFloat(amount1); - amount2 = parseFloat(amount2); - if (amount1 > amount2) { const rateStr = (amount1 / amount2).toString(); const displayRateStr = formatExchangeRateAmount(rateStr, options); @@ -270,7 +276,7 @@ export function getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, } } -export function getExchangedAmount(amount, fromRate, toRate) { +export function getExchangedAmount(amount: number, fromRate: string, toRate: string): number | null { const exchangeRate = parseFloat(toRate) / parseFloat(fromRate); if (!isNumber(exchangeRate)) { @@ -280,7 +286,7 @@ export function getExchangedAmount(amount, fromRate, toRate) { return amount * exchangeRate; } -export function getConvertedAmount(baseAmount, fromExchangeRate, toExchangeRate) { +export function getConvertedAmount(baseAmount: number | '', fromExchangeRate: { rate: string }, toExchangeRate: { rate: string }): number | '' | null { if (!fromExchangeRate || !toExchangeRate) { return ''; } @@ -289,5 +295,5 @@ export function getConvertedAmount(baseAmount, fromExchangeRate, toExchangeRate) return 0; } - return getExchangedAmount(baseAmount, fromExchangeRate.rate, toExchangeRate.rate); + return getExchangedAmount(baseAmount as number, fromExchangeRate.rate, toExchangeRate.rate); } diff --git a/src/stores/exchangeRates.js b/src/stores/exchangeRates.js index cd6cc919..29167883 100644 --- a/src/stores/exchangeRates.js +++ b/src/stores/exchangeRates.js @@ -4,7 +4,7 @@ import services from '@/lib/services.js'; import logger from '@/lib/logger.js'; import { isEquals } from '@/lib/common.ts'; import { getCurrentUnixTime, formatUnixTime } from '@/lib/datetime.ts'; -import { getExchangedAmount } from '@/lib/numeral.js'; +import { getExchangedAmount } from '@/lib/numeral.ts'; const exchangeRatesLocalStorageKey = 'ebk_app_exchange_rates'; diff --git a/src/stores/transaction.js b/src/stores/transaction.js index 2b1b7311..ca5fd2e2 100644 --- a/src/stores/transaction.js +++ b/src/stores/transaction.js @@ -33,7 +33,7 @@ import { getDay, getDayOfWeekName } from '@/lib/datetime.ts'; -import { getAmountWithDecimalNumberCount } from '@/lib/numeral.js'; +import { getAmountWithDecimalNumberCount } from '@/lib/numeral.ts'; import { getCurrencyFraction } from '@/lib/currency.ts'; import { getFirstAvailableCategoryId } from '@/lib/category.js'; diff --git a/src/views/desktop/ExchangeRatesPage.vue b/src/views/desktop/ExchangeRatesPage.vue index 9e0d2a9b..741b11e8 100644 --- a/src/views/desktop/ExchangeRatesPage.vue +++ b/src/views/desktop/ExchangeRatesPage.vue @@ -142,7 +142,7 @@ import { useUserStore } from '@/stores/user.js'; import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import logger from '@/lib/logger.js'; -import { getConvertedAmount } from '@/lib/numeral.js'; +import { getConvertedAmount } from '@/lib/numeral.ts'; import { mdiRefresh, diff --git a/src/views/desktop/statistics/TransactionPage.vue b/src/views/desktop/statistics/TransactionPage.vue index 4b9cdf9a..3a28a592 100644 --- a/src/views/desktop/statistics/TransactionPage.vue +++ b/src/views/desktop/statistics/TransactionPage.vue @@ -332,7 +332,7 @@ import { getNameByKeyValue, arrayItemToObjectField } from '@/lib/common.ts' -import { formatPercent } from '@/lib/numeral.js'; +import { formatPercent } from '@/lib/numeral.ts'; import { getYearAndMonthFromUnixTime, getYearMonthFirstUnixTime, diff --git a/src/views/desktop/transactions/ListPage.vue b/src/views/desktop/transactions/ListPage.vue index 8b4b770d..6f393c8d 100644 --- a/src/views/desktop/transactions/ListPage.vue +++ b/src/views/desktop/transactions/ListPage.vue @@ -596,10 +596,10 @@ import { useTransactionsStore } from '@/stores/transaction.js'; import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js'; import { DateRangeScene, DateRange } from '@/core/datetime.ts'; +import { AmountFilterType } from '@/core/numeral.ts'; import { AccountType } from '@/core/account.ts'; import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts'; import { TemplateType } from '@/core/template.ts'; -import numeralConstants from '@/consts/numeral.js'; import { isString, isNumber, getNameByKeyValue } from '@/lib/common.ts'; import logger from '@/lib/logger.js'; import { @@ -977,7 +977,7 @@ export default { } }, allAmountFilterTypes() { - return numeralConstants.allAmountFilterTypeArray; + return AmountFilterType.values(); }, allTransactionTypes() { return TransactionType; @@ -1674,7 +1674,7 @@ export default { return []; }, getAmountFilterParameterCount(filterType) { - const amountFilterType = numeralConstants.allAmountFilterTypeMap[filterType]; + const amountFilterType = AmountFilterType.valueOf(filterType); return amountFilterType ? amountFilterType.paramCount : 0; }, getFilterLinkUrl() { diff --git a/src/views/mobile/ExchangeRatesPage.vue b/src/views/mobile/ExchangeRatesPage.vue index c09b1cd8..076c595f 100644 --- a/src/views/mobile/ExchangeRatesPage.vue +++ b/src/views/mobile/ExchangeRatesPage.vue @@ -97,7 +97,7 @@ import { useUserStore } from '@/stores/user.js'; import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts'; -import { getConvertedAmount } from '@/lib/numeral.js'; +import { getConvertedAmount } from '@/lib/numeral.ts'; export default { data() { diff --git a/src/views/mobile/statistics/TransactionPage.vue b/src/views/mobile/statistics/TransactionPage.vue index 1a6fd489..33a295f1 100644 --- a/src/views/mobile/statistics/TransactionPage.vue +++ b/src/views/mobile/statistics/TransactionPage.vue @@ -334,7 +334,7 @@ import { useStatisticsStore } from '@/stores/statistics.js'; import { DateRangeScene, DateRange } from '@/core/datetime.ts'; import statisticsConstants from '@/consts/statistics.js'; import { getNameByKeyValue, limitText } from '@/lib/common.ts'; -import { formatPercent } from '@/lib/numeral.js'; +import { formatPercent } from '@/lib/numeral.ts'; import { getYearAndMonthFromUnixTime, getYearMonthFirstUnixTime, diff --git a/src/views/mobile/transactions/AmountFilterPage.vue b/src/views/mobile/transactions/AmountFilterPage.vue index 9cc99905..d3dfb1ca 100644 --- a/src/views/mobile/transactions/AmountFilterPage.vue +++ b/src/views/mobile/transactions/AmountFilterPage.vue @@ -57,7 +57,7 @@ import { useSettingsStore } from '@/stores/setting.js'; import { useUserStore } from '@/stores/user.js'; import { useTransactionsStore } from '@/stores/transaction.js'; -import numeralConstants from '@/consts/numeral.js'; +import { AmountFilterType } from '@/core/numeral.ts'; import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts'; import { isString } from '@/lib/common.ts'; import logger from '@/lib/logger.js'; @@ -79,7 +79,7 @@ export default { computed: { ...mapStores(useSettingsStore, useUserStore, useTransactionsStore), allAmountFilterTypes() { - return numeralConstants.allAmountFilterTypeArray; + return AmountFilterType.values(); }, allowedMinAmount() { return TRANSACTION_MIN_AMOUNT; @@ -91,24 +91,24 @@ export default { return this.getAmountFilterParameterCount(this.type); }, title() { - const amountFilterType = numeralConstants.allAmountFilterTypeMap[this.type]; + const amountFilterType = AmountFilterType.valueOf(this.type); return amountFilterType ? this.$t(amountFilterType.name) : this.$t('Amount'); }, amount1Header() { - if (this.type === numeralConstants.allAmountFilterType.GreaterThan.type - || this.type === numeralConstants.allAmountFilterType.Between.type - || this.type === numeralConstants.allAmountFilterType.NotBetween.type) { + if (this.type === AmountFilterType.GreaterThan.type + || this.type === AmountFilterType.Between.type + || this.type === AmountFilterType.NotBetween.type) { return this.$t('Minimum Amount'); - } else if (this.type === numeralConstants.allAmountFilterType.LessThan.type) { + } else if (this.type === AmountFilterType.LessThan.type) { return this.$t('Maximum Amount'); } else { return this.$t('Amount'); } }, amount2Header() { - if (this.type === numeralConstants.allAmountFilterType.Between.type) { + if (this.type === AmountFilterType.Between.type) { return this.$t('Maximum Amount'); - } else if (this.type === numeralConstants.allAmountFilterType.NotBetween.type) { + } else if (this.type === AmountFilterType.NotBetween.type) { return this.$t('Maximum Amount'); } else { return this.$t('Amount'); @@ -176,7 +176,7 @@ export default { return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, false); }, getAmountFilterParameterCount(filterType) { - const amountFilterType = numeralConstants.allAmountFilterTypeMap[filterType]; + const amountFilterType = AmountFilterType.valueOf(filterType); return amountFilterType ? amountFilterType.paramCount : 0; } } diff --git a/src/views/mobile/transactions/ListPage.vue b/src/views/mobile/transactions/ListPage.vue index 788e3c93..ed962f2e 100644 --- a/src/views/mobile/transactions/ListPage.vue +++ b/src/views/mobile/transactions/ListPage.vue @@ -529,9 +529,9 @@ import { useTransactionTagsStore } from '@/stores/transactionTag.js'; import { useTransactionsStore } from '@/stores/transaction.js'; import { DateRangeScene, DateRange } from '@/core/datetime.ts'; +import { AmountFilterType } from '@/core/numeral.ts'; import { AccountType } from '@/core/account.ts'; import { TransactionType } from '@/core/transaction.ts'; -import numeralConstants from '@/consts/numeral.js'; import { getNameByKeyValue } from '@/lib/common.ts'; import { getCurrentUnixTime, @@ -677,7 +677,7 @@ export default { return this.transactionsStore.hasMoreTransaction; }, allAmountFilterTypes() { - return numeralConstants.allAmountFilterTypeArray; + return AmountFilterType.values(); }, allTransactionTypes() { return TransactionType;