diff --git a/src/components/desktop/TrendsChart.vue b/src/components/desktop/TrendsChart.vue index 05582a8b..f1fc6ea8 100644 --- a/src/components/desktop/TrendsChart.vue +++ b/src/components/desktop/TrendsChart.vue @@ -12,8 +12,8 @@ import { useUserStore } from '@/stores/user.js'; import { DateRangeScene } from '@/core/datetime.ts'; import { ThemeType } from '@/core/theme.ts'; +import { TrendChartType, ChartDateAggregationType } from '@/core/statistics.ts'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts'; -import statisticsConstants from '@/consts/statistics.js'; import { isArray, isNumber @@ -26,7 +26,7 @@ import { import { sortStatisticsItems, getAllDateRanges -} from '@/lib/statistics.js'; +} from '@/lib/statistics.ts'; export default { props: [ @@ -94,11 +94,11 @@ export default { for (let i = 0; i < this.allDateRanges.length; i++) { const dateRange = this.allDateRanges[i]; - if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + if (this.dateAggregationType === ChartDateAggregationType.Year.type) { allDisplayDateRanges.push(this.$locale.formatUnixTimeToShortYear(this.userStore, dateRange.minUnixTime)); - } else if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (this.dateAggregationType === ChartDateAggregationType.Quarter.type) { allDisplayDateRanges.push(this.$locale.formatYearQuarter(dateRange.year, dateRange.quarter)); - } else { // if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (this.dateAggregationType === ChartDateAggregationType.Month.type) { allDisplayDateRanges.push(this.$locale.formatUnixTimeToShortYearMonth(this.userStore, dateRange.minUnixTime)); } } @@ -122,11 +122,11 @@ export default { const dataItem = item.items[j]; let dateRangeKey = ''; - if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + if (this.dateAggregationType === ChartDateAggregationType.Year.type) { dateRangeKey = dataItem.year; - } else if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (this.dateAggregationType === ChartDateAggregationType.Quarter.type) { dateRangeKey = `${dataItem.year}-${Math.floor((dataItem.month - 1) / 3) + 1}`; - } else { // if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (this.dateAggregationType === ChartDateAggregationType.Month.type) { dateRangeKey = `${dataItem.year}-${dataItem.month}`; } @@ -140,11 +140,11 @@ export default { const dateRange = this.allDateRanges[j]; let dateRangeKey = ''; - if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + if (this.dateAggregationType === ChartDateAggregationType.Year.type) { dateRangeKey = dateRange.year; - } else if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (this.dateAggregationType === ChartDateAggregationType.Quarter.type) { dateRangeKey = `${dateRange.year}-${dateRange.quarter}`; - } else { // if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (this.dateAggregationType === ChartDateAggregationType.Month.type) { dateRangeKey = `${dateRange.year}-${dateRange.month + 1}`; } @@ -177,9 +177,9 @@ export default { data: allAmounts }; - if (this.type === statisticsConstants.allTrendChartTypes.Area) { + if (this.type === TrendChartType.Area.type) { finalItem.areaStyle = {}; - } else if (this.type === statisticsConstants.allTrendChartTypes.Column) { + } else if (this.type === TrendChartType.Column.type) { finalItem.type = 'bar'; } diff --git a/src/components/mobile/TrendsBarChart.vue b/src/components/mobile/TrendsBarChart.vue index 78491a4c..53a3eb47 100644 --- a/src/components/mobile/TrendsBarChart.vue +++ b/src/components/mobile/TrendsBarChart.vue @@ -94,8 +94,8 @@ import { useSettingsStore } from '@/stores/setting.js'; import { useUserStore } from '@/stores/user.js'; import { DateRangeScene } from '@/core/datetime.ts'; +import { ChartDateAggregationType } from '@/core/statistics.ts'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts'; -import statisticsConstants from '@/consts/statistics.js'; import { isNumber } from '@/lib/common.ts'; import { getYearMonthFirstUnixTime, @@ -105,7 +105,7 @@ import { import { sortStatisticsItems, getAllDateRanges -} from '@/lib/statistics.js'; +} from '@/lib/statistics.ts'; export default { props: [ @@ -170,11 +170,11 @@ export default { const dataItem = item.items[j]; let dateRangeKey = ''; - if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + if (this.dateAggregationType === ChartDateAggregationType.Year.type) { dateRangeKey = dataItem.year; - } else if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (this.dateAggregationType === ChartDateAggregationType.Quarter.type) { dateRangeKey = `${dataItem.year}-${Math.floor((dataItem.month - 1) / 3) + 1}`; - } else { // if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (this.dateAggregationType === ChartDateAggregationType.Month.type) { dateRangeKey = `${dataItem.year}-${dataItem.month}`; } @@ -200,21 +200,21 @@ export default { const dateRange = this.allDateRanges[i]; let dateRangeKey = ''; - if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + if (this.dateAggregationType === ChartDateAggregationType.Year.type) { dateRangeKey = dateRange.year; - } else if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (this.dateAggregationType === ChartDateAggregationType.Quarter.type) { dateRangeKey = `${dateRange.year}-${dateRange.quarter}`; - } else { // if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (this.dateAggregationType === ChartDateAggregationType.Month.type) { dateRangeKey = `${dateRange.year}-${dateRange.month + 1}`; } let displayDateRange = ''; - if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + if (this.dateAggregationType === ChartDateAggregationType.Year.type) { displayDateRange = this.$locale.formatUnixTimeToShortYear(this.userStore, dateRange.minUnixTime); - } else if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (this.dateAggregationType === ChartDateAggregationType.Quarter.type) { displayDateRange = this.$locale.formatYearQuarter(dateRange.year, dateRange.quarter); - } else { // if (this.dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (this.dateAggregationType === ChartDateAggregationType.Month.type) { displayDateRange = this.$locale.formatUnixTimeToShortYearMonth(this.userStore, dateRange.minUnixTime); } diff --git a/src/consts/statistics.js b/src/consts/statistics.js deleted file mode 100644 index 1452f343..00000000 --- a/src/consts/statistics.js +++ /dev/null @@ -1,214 +0,0 @@ -import { DateRange } from '@/core/datetime.ts'; - -const allAnalysisTypes = { - CategoricalAnalysis: 0, - TrendAnalysis: 1 -}; - -const allCategoricalChartTypes = { - Pie: 0, - Bar: 1 -}; - -const allCategoricalChartTypesArray = [ - { - name: 'Pie Chart', - type: allCategoricalChartTypes.Pie - }, - { - name: 'Bar Chart', - type: allCategoricalChartTypes.Bar - } -]; - -const defaultCategoricalChartType = allCategoricalChartTypes.Pie; - -const allTrendChartTypes = { - Area: 0, - Column: 1 -}; - -const allTrendChartTypesArray = [ - { - name: 'Area Chart', - type: allTrendChartTypes.Area - }, - { - name: 'Column Chart', - type: allTrendChartTypes.Column - } -]; - -const defaultTrendChartType = allTrendChartTypes.Column; - -const allChartDataTypes = { - ExpenseByAccount: { - type: 0, - name: 'Expense By Account', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true, - [allAnalysisTypes.TrendAnalysis]: true, - } - }, - ExpenseByPrimaryCategory: { - type: 1, - name: 'Expense By Primary Category', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true, - [allAnalysisTypes.TrendAnalysis]: true, - } - }, - ExpenseBySecondaryCategory: { - type: 2, - name: 'Expense By Secondary Category', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true, - [allAnalysisTypes.TrendAnalysis]: true, - } - }, - IncomeByAccount: { - type: 3, - name: 'Income By Account', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true, - [allAnalysisTypes.TrendAnalysis]: true, - } - }, - IncomeByPrimaryCategory: { - type: 4, - name: 'Income By Primary Category', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true, - [allAnalysisTypes.TrendAnalysis]: true, - } - }, - IncomeBySecondaryCategory: { - type: 5, - name: 'Income By Secondary Category', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true, - [allAnalysisTypes.TrendAnalysis]: true, - } - }, - AccountTotalAssets: { - type: 6, - name: 'Account Total Assets', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true - } - }, - AccountTotalLiabilities: { - type: 7, - name: 'Account Total Liabilities', - availableAnalysisTypes: { - [allAnalysisTypes.CategoricalAnalysis]: true - } - }, - TotalExpense: { - type: 8, - name: 'Total Expense', - availableAnalysisTypes: { - [allAnalysisTypes.TrendAnalysis]: true - } - }, - TotalIncome: { - type: 9, - name: 'Total Income', - availableAnalysisTypes: { - [allAnalysisTypes.TrendAnalysis]: true - } - }, - TotalBalance: { - type: 10, - name: 'Total Balance', - availableAnalysisTypes: { - [allAnalysisTypes.TrendAnalysis]: true - } - } -}; - -const allChartDataTypesMap = { - [allChartDataTypes.ExpenseByAccount.type]: allChartDataTypes.ExpenseByAccount, - [allChartDataTypes.ExpenseByPrimaryCategory.type]: allChartDataTypes.ExpenseByPrimaryCategory, - [allChartDataTypes.ExpenseBySecondaryCategory.type]: allChartDataTypes.ExpenseBySecondaryCategory, - [allChartDataTypes.IncomeByAccount.type]: allChartDataTypes.IncomeByAccount, - [allChartDataTypes.IncomeByPrimaryCategory.type]: allChartDataTypes.IncomeByPrimaryCategory, - [allChartDataTypes.IncomeBySecondaryCategory.type]: allChartDataTypes.IncomeBySecondaryCategory, - [allChartDataTypes.AccountTotalAssets.type]: allChartDataTypes.AccountTotalAssets, - [allChartDataTypes.AccountTotalLiabilities.type]: allChartDataTypes.AccountTotalLiabilities, - [allChartDataTypes.TotalExpense.type]: allChartDataTypes.TotalExpense, - [allChartDataTypes.TotalIncome.type]: allChartDataTypes.TotalIncome, - [allChartDataTypes.TotalBalance.type]: allChartDataTypes.TotalBalance -}; - -const defaultChartDataType = allChartDataTypes.ExpenseByPrimaryCategory.type; - -const allSortingTypes = { - Amount: { - type: 0, - name: 'Amount', - fullName: 'Sort by Amount' - }, - DisplayOrder: { - type: 1, - name: 'Display Order', - fullName: 'Sort by Display Order' - }, - Name: { - type: 2, - name: 'Name', - fullName: 'Sort by Name' - } -}; - -const allSortingTypesArray = [ - allSortingTypes.Amount, - allSortingTypes.DisplayOrder, - allSortingTypes.Name -] - -const defaultSortingType = allSortingTypes.Amount.type; - -const allDateAggregationTypes = { - Month: { - type: 0, - name: 'Aggregate by Month' - }, - Quarter: { - type: 1, - name: 'Aggregate by Quarter' - }, - Year: { - type: 2, - name: 'Aggregate by Year' - } -}; - -const allDateAggregationTypesArray = [ - allDateAggregationTypes.Month, - allDateAggregationTypes.Quarter, - allDateAggregationTypes.Year -] - -const defaultDateAggregationType = allDateAggregationTypes.Month.type; - -export default { - allAnalysisTypes: allAnalysisTypes, - allCategoricalChartTypes: allCategoricalChartTypes, - allCategoricalChartTypesArray: allCategoricalChartTypesArray, - defaultCategoricalChartType: defaultCategoricalChartType, - allTrendChartTypes: allTrendChartTypes, - allTrendChartTypesArray: allTrendChartTypesArray, - defaultTrendChartType: defaultTrendChartType, - allChartDataTypes: allChartDataTypes, - allChartDataTypesMap: allChartDataTypesMap, - defaultChartDataType: defaultChartDataType, - defaultCategoricalChartDataRangeType: DateRange.ThisMonth.type, - defaultTrendChartDataRangeType: DateRange.ThisYear.type, - allSortingTypes: allSortingTypes, - allSortingTypesArray: allSortingTypesArray, - defaultSortingType: defaultSortingType, - allDateAggregationTypes: allDateAggregationTypes, - allDateAggregationTypesArray: allDateAggregationTypesArray, - defaultDateAggregationType: defaultDateAggregationType, -}; diff --git a/src/core/statistics.ts b/src/core/statistics.ts new file mode 100644 index 00000000..e4ddcd47 --- /dev/null +++ b/src/core/statistics.ts @@ -0,0 +1,215 @@ +import type { TypeAndName } from './base.ts'; +import { DateRange } from '@/core/datetime.ts'; + +export enum StatisticsAnalysisType { + CategoricalAnalysis = 0, + TrendAnalysis = 1 +} + +type CategoricalChartTypeName = 'Pie' | 'Bar'; + +export class CategoricalChartType implements TypeAndName { + private static readonly allInstances: CategoricalChartType[] = []; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly Pie = new CategoricalChartType(0, 'Pie', 'Pie Chart'); + public static readonly Bar = new CategoricalChartType(1, 'Bar', 'Bar Chart'); + + public static readonly Default = CategoricalChartType.Pie; + + public readonly type: number; + public readonly typeName: CategoricalChartTypeName; + public readonly name: string; + + private constructor(type: number, typeName: CategoricalChartTypeName, name: string) { + this.type = type; + this.typeName = typeName; + this.name = name; + + CategoricalChartType.allInstances.push(this); + CategoricalChartType.allInstancesByTypeName[typeName] = this; + } + + public static values(): CategoricalChartType[] { + return CategoricalChartType.allInstances; + } + + public static all(): Record { + return CategoricalChartType.allInstancesByTypeName; + } +} + +type TrendChartTypeName = 'Area' | 'Column'; + +export class TrendChartType implements TypeAndName { + private static readonly allInstances: TrendChartType[] = []; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly Area = new TrendChartType(0, 'Area', 'Area Chart'); + public static readonly Column = new TrendChartType(1, 'Column', 'Column Chart'); + + public static readonly Default = TrendChartType.Column; + + public readonly type: number; + public readonly typeName: TrendChartTypeName; + public readonly name: string; + + private constructor(type: number, typeName: TrendChartTypeName, name: string) { + this.type = type; + this.typeName = typeName; + this.name = name; + + TrendChartType.allInstances.push(this); + TrendChartType.allInstancesByTypeName[typeName] = this; + } + + public static values(): TrendChartType[] { + return TrendChartType.allInstances; + } + + public static all(): Record { + return TrendChartType.allInstancesByTypeName; + } +} + +type ChartDataTypeName = 'ExpenseByAccount' | 'ExpenseByPrimaryCategory' | 'ExpenseBySecondaryCategory' | 'IncomeByAccount' | 'IncomeByPrimaryCategory' | 'IncomeBySecondaryCategory' | 'AccountTotalAssets' | 'AccountTotalLiabilities' | 'TotalExpense' | 'TotalIncome' | 'TotalBalance'; + +export class ChartDataType implements TypeAndName { + private static readonly allInstances: ChartDataType[] = []; + private static readonly allInstancesByType: Record = {}; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly ExpenseByAccount = new ChartDataType(0, 'ExpenseByAccount', 'Expense By Account', StatisticsAnalysisType.CategoricalAnalysis, StatisticsAnalysisType.TrendAnalysis); + public static readonly ExpenseByPrimaryCategory = new ChartDataType(1, 'ExpenseByPrimaryCategory', 'Expense By Primary Category', StatisticsAnalysisType.CategoricalAnalysis, StatisticsAnalysisType.TrendAnalysis); + public static readonly ExpenseBySecondaryCategory = new ChartDataType(2, 'ExpenseBySecondaryCategory', 'Expense By Secondary Category', StatisticsAnalysisType.CategoricalAnalysis, StatisticsAnalysisType.TrendAnalysis); + public static readonly IncomeByAccount = new ChartDataType(3, 'IncomeByAccount', 'Income By Account', StatisticsAnalysisType.CategoricalAnalysis, StatisticsAnalysisType.TrendAnalysis); + public static readonly IncomeByPrimaryCategory = new ChartDataType(4, 'IncomeByPrimaryCategory', 'Income By Primary Category', StatisticsAnalysisType.CategoricalAnalysis, StatisticsAnalysisType.TrendAnalysis); + public static readonly IncomeBySecondaryCategory = new ChartDataType(5, 'IncomeBySecondaryCategory', 'Income By Secondary Category', StatisticsAnalysisType.CategoricalAnalysis, StatisticsAnalysisType.TrendAnalysis); + public static readonly AccountTotalAssets = new ChartDataType(6, 'AccountTotalAssets', 'Account Total Assets', StatisticsAnalysisType.CategoricalAnalysis); + public static readonly AccountTotalLiabilities = new ChartDataType(7, 'AccountTotalLiabilities', 'Account Total Liabilities', StatisticsAnalysisType.CategoricalAnalysis); + public static readonly TotalExpense = new ChartDataType(8, 'TotalExpense', 'Total Expense', StatisticsAnalysisType.TrendAnalysis); + public static readonly TotalIncome = new ChartDataType(9, 'TotalIncome', 'Total Income', StatisticsAnalysisType.TrendAnalysis); + public static readonly TotalBalance = new ChartDataType(10, 'TotalBalance', 'Total Balance', StatisticsAnalysisType.TrendAnalysis); + + public static readonly Default = ChartDataType.ExpenseByPrimaryCategory; + + public readonly type: number; + public readonly typeName: ChartDataTypeName; + public readonly name: string; + private readonly availableAnalysisTypes: Record; + + private constructor(type: number, typeName: ChartDataTypeName, name: string, ...availableAnalysisTypes: StatisticsAnalysisType[]) { + this.type = type; + this.typeName = typeName; + this.name = name; + this.availableAnalysisTypes = {}; + + if (availableAnalysisTypes) { + for (const analysisType of availableAnalysisTypes) { + this.availableAnalysisTypes[analysisType] = true; + } + } + + ChartDataType.allInstances.push(this); + ChartDataType.allInstancesByType[type] = this; + ChartDataType.allInstancesByTypeName[typeName] = this; + } + + public isAvailableAnalysisType(analysisType: StatisticsAnalysisType): boolean { + return this.availableAnalysisTypes[analysisType] || false; + } + + public static values(analysisType: StatisticsAnalysisType | undefined): ChartDataType[] { + if (analysisType === undefined) { + return ChartDataType.allInstances; + } + + const ret: ChartDataType[] = []; + + for (const chartDataType of ChartDataType.allInstances) { + if (chartDataType.isAvailableAnalysisType(analysisType)) { + ret.push(chartDataType); + } + } + + return ret; + } + + public static all(): Record { + return ChartDataType.allInstancesByTypeName; + } + + public static valueOf(type: number): ChartDataType { + return ChartDataType.allInstancesByType[type]; + } + + public static isAvailableForAnalysisType(type: number, analysisType: StatisticsAnalysisType): boolean { + const chartDataType = ChartDataType.allInstancesByType[type]; + return chartDataType?.isAvailableAnalysisType(analysisType) || false; + } +} + +export class ChartSortingType implements TypeAndName { + private static readonly allInstances: ChartSortingType[] = []; + private static readonly allInstancesByType: Record = {}; + + public static readonly Amount = new ChartSortingType(0, 'Amount', 'Sort by Amount'); + public static readonly DisplayOrder = new ChartSortingType(1, 'Display Order', 'Sort by Display Order'); + public static readonly Name = new ChartSortingType(2, 'Name', 'Sort by Name'); + + public static readonly Default = ChartSortingType.Amount; + + public readonly type: number; + public readonly name: string; + public readonly fullName: string; + + private constructor(type: number, name: string, fullName: string) { + this.type = type; + this.name = name; + this.fullName = fullName; + + ChartSortingType.allInstances.push(this); + ChartSortingType.allInstancesByType[type] = this; + } + + public static values(): ChartSortingType[] { + return ChartSortingType.allInstances; + } + + public static valueOf(type: number): ChartSortingType { + return ChartSortingType.allInstancesByType[type]; + } +} + +export class ChartDateAggregationType implements TypeAndName { + private static readonly allInstances: ChartDateAggregationType[] = []; + private static readonly allInstancesByType: Record = {}; + + public static readonly Month = new ChartDateAggregationType(0, 'Aggregate by Month'); + public static readonly Quarter = new ChartDateAggregationType(1, 'Aggregate by Quarter'); + public static readonly Year = new ChartDateAggregationType(2, 'Aggregate by Year'); + + public static readonly Default = ChartDateAggregationType.Month; + + public readonly type: number; + public readonly name: string; + + private constructor(type: number, name: string) { + this.type = type; + this.name = name; + + ChartDateAggregationType.allInstances.push(this); + ChartDateAggregationType.allInstancesByType[type] = this; + } + + public static values(): ChartDateAggregationType[] { + return ChartDateAggregationType.allInstances; + } + + public static valueOf(type: number): ChartDateAggregationType { + return ChartDateAggregationType.allInstancesByType[type]; + } +} + +export const DEFAULT_CATEGORICAL_CHART_DATA_RANGE: DateRange = DateRange.ThisMonth; +export const DEFAULT_TREND_CHART_DATA_RANGE: DateRange = DateRange.ThisYear; diff --git a/src/lib/i18n.js b/src/lib/i18n.js index b26c58fd..e6a00d36 100644 --- a/src/lib/i18n.js +++ b/src/lib/i18n.js @@ -12,16 +12,15 @@ import { AccountType, AccountCategory } from '@/core/account.ts'; import { CategoryType } from '@/core/category.ts'; import { TransactionEditScopeType, TransactionTagFilterType } from '@/core/transaction.ts'; import { ScheduledTemplateFrequencyType } from '@/core/template.ts'; +import { CategoricalChartType, TrendChartType, ChartDataType, ChartSortingType, ChartDateAggregationType } from '@/core/statistics.ts'; 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'; import { DEFAULT_EXPENSE_CATEGORIES, DEFAULT_INCOME_CATEGORIES, DEFAULT_TRANSFER_CATEGORIES } from '@/consts/category.ts'; -import statisticsConstants from '@/consts/statistics.js'; import { KnownErrorCode, SPECIFIED_API_NOT_FOUND_ERRORS, PARAMETERIZED_ERRORS } from '@/consts/api.ts'; import { - isDefined, isString, isNumber, isBoolean, @@ -1109,96 +1108,23 @@ function getAllAccountTypes(translateFn) { } function getAllCategoricalChartTypes(translateFn) { - const allChartTypes = []; - - for (let i = 0; i < statisticsConstants.allCategoricalChartTypesArray.length; i++) { - const chartType = statisticsConstants.allCategoricalChartTypesArray[i]; - - allChartTypes.push({ - type: chartType.type, - displayName: translateFn(chartType.name) - }); - } - - return allChartTypes; + return getLocalizedDisplayNameAndType(CategoricalChartType.values(), translateFn); } function getAllTrendChartTypes(translateFn) { - const allChartTypes = []; - - for (let i = 0; i < statisticsConstants.allTrendChartTypesArray.length; i++) { - const chartType = statisticsConstants.allTrendChartTypesArray[i]; - - allChartTypes.push({ - type: chartType.type, - displayName: translateFn(chartType.name) - }); - } - - return allChartTypes; + return getLocalizedDisplayNameAndType(TrendChartType.values(), translateFn); } function getAllStatisticsChartDataTypes(translateFn, analysisType) { - const allChartDataTypes = []; - - for (const dataTypeField in statisticsConstants.allChartDataTypes) { - if (!Object.prototype.hasOwnProperty.call(statisticsConstants.allChartDataTypes, dataTypeField)) { - continue; - } - - const chartDataType = statisticsConstants.allChartDataTypes[dataTypeField]; - - if (isDefined(analysisType) && !chartDataType.availableAnalysisTypes[analysisType]) { - continue; - } - - allChartDataTypes.push({ - type: chartDataType.type, - displayName: translateFn(chartDataType.name), - availableAnalysisTypes: chartDataType.availableAnalysisTypes - }); - } - - return allChartDataTypes; + return getLocalizedDisplayNameAndType(ChartDataType.values(analysisType), translateFn); } function getAllStatisticsSortingTypes(translateFn) { - const allSortingTypes = []; - - for (const sortingTypeField in statisticsConstants.allSortingTypes) { - if (!Object.prototype.hasOwnProperty.call(statisticsConstants.allSortingTypes, sortingTypeField)) { - continue; - } - - const sortingType = statisticsConstants.allSortingTypes[sortingTypeField]; - - allSortingTypes.push({ - type: sortingType.type, - displayName: translateFn(sortingType.name), - displayFullName: translateFn(sortingType.fullName) - }); - } - - return allSortingTypes; + return getLocalizedDisplayNameAndType(ChartSortingType.values(), translateFn); } function getAllStatisticsDateAggregationTypes(translateFn) { - const aggregationTypes = []; - - for (const aggregationTypeField in statisticsConstants.allDateAggregationTypes) { - if (!Object.prototype.hasOwnProperty.call(statisticsConstants.allDateAggregationTypes, aggregationTypeField)) { - continue; - } - - const aggregationType = statisticsConstants.allDateAggregationTypes[aggregationTypeField]; - - aggregationTypes.push({ - type: aggregationType.type, - displayName: translateFn(aggregationType.name) - }); - } - - return aggregationTypes; + return getLocalizedDisplayNameAndType(ChartDateAggregationType.values(), translateFn); } function getAllTransactionEditScopeTypes(translateFn) { diff --git a/src/lib/settings.js b/src/lib/settings.js index 374b185e..ba67d077 100644 --- a/src/lib/settings.js +++ b/src/lib/settings.js @@ -1,6 +1,13 @@ import { TimezoneTypeForStatistics } from '@/core/timezone.ts'; import { CurrencySortingType } from '@/core/currency.ts'; -import statisticsConstants from '@/consts/statistics.js'; +import { + CategoricalChartType, + TrendChartType, + ChartDataType, + ChartSortingType, + DEFAULT_CATEGORICAL_CHART_DATA_RANGE, + DEFAULT_TREND_CHART_DATA_RANGE +} from '@/core/statistics.ts'; const settingsLocalStorageKey = 'ebk_app_settings'; @@ -22,15 +29,15 @@ const defaultSettings = { showAccountBalance: true, currencySortByInExchangeRatesPage: CurrencySortingType.Default.type, statistics: { - defaultChartDataType: statisticsConstants.defaultChartDataType, + defaultChartDataType: ChartDataType.Default.type, defaultTimezoneType: TimezoneTypeForStatistics.Default.type, defaultAccountFilter: {}, defaultTransactionCategoryFilter: {}, - defaultSortingType: statisticsConstants.defaultSortingType, - defaultCategoricalChartType: statisticsConstants.defaultCategoricalChartType, - defaultCategoricalChartDataRangeType: statisticsConstants.defaultCategoricalChartDataRangeType, - defaultTrendChartType: statisticsConstants.defaultTrendChartType, - defaultTrendChartDataRangeType: statisticsConstants.defaultTrendChartDataRangeType, + defaultSortingType: ChartSortingType.Default.type, + defaultCategoricalChartType: CategoricalChartType.Default.type, + defaultCategoricalChartDataRangeType: DEFAULT_CATEGORICAL_CHART_DATA_RANGE.type, + defaultTrendChartType: TrendChartType.Default.type, + defaultTrendChartDataRangeType: DEFAULT_TREND_CHART_DATA_RANGE, }, animate: true }; diff --git a/src/lib/statistics.js b/src/lib/statistics.ts similarity index 67% rename from src/lib/statistics.js rename to src/lib/statistics.ts index b9264219..9562474f 100644 --- a/src/lib/statistics.js +++ b/src/lib/statistics.ts @@ -1,4 +1,5 @@ -import statisticsConstants from '@/consts/statistics.js'; +import type { YearMonth, YearUnixTime, YearQuarterUnixTime, YearMonthUnixTime } from '@/core/datetime.ts'; +import { ChartSortingType, ChartDateAggregationType } from '@/core/statistics.ts'; import { getAllMonthsStartAndEndUnixTimes, @@ -6,26 +7,8 @@ import { getAllYearsStartAndEndUnixTimes } from '@/lib/datetime.ts'; -export function isChartDataTypeAvailableForAnalysisType(chartDataType, analysisType) { - for (const dataTypeField in statisticsConstants.allChartDataTypes) { - if (!Object.prototype.hasOwnProperty.call(statisticsConstants.allChartDataTypes, dataTypeField)) { - continue; - } - - const dataTypeItem = statisticsConstants.allChartDataTypes[dataTypeField]; - - if (dataTypeItem.type !== chartDataType) { - continue; - } - - return !!dataTypeItem.availableAnalysisTypes[analysisType]; - } - - return false; -} - -export function sortStatisticsItems(items, sortingType) { - if (sortingType === statisticsConstants.allSortingTypes.DisplayOrder.type) { +export function sortStatisticsItems(items: { name: string, totalAmount: number, displayOrders: number[] }[], sortingType: number): void { + if (sortingType === ChartSortingType.DisplayOrder.type) { items.sort(function (data1, data2) { for (let i = 0; i < Math.min(data1.displayOrders.length, data2.displayOrders.length); i++) { if (data1.displayOrders[i] !== data2.displayOrders[i]) { @@ -38,7 +21,7 @@ export function sortStatisticsItems(items, sortingType) { sensitivity: 'base' }); }); - } else if (sortingType === statisticsConstants.allSortingTypes.Name.type) { + } else if (sortingType === ChartSortingType.Name.type) { items.sort(function (data1, data2) { return data1.name.localeCompare(data2.name, undefined, { // asc numeric: true, @@ -59,7 +42,7 @@ export function sortStatisticsItems(items, sortingType) { } } -export function getAllDateRanges(items, startYearMonth, endYearMonth, dateAggregationType) { +export function getAllDateRanges(items: { items: YearMonth[] }[], startYearMonth: YearMonth | string, endYearMonth: YearMonth | string, dateAggregationType: number): YearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] { if ((!startYearMonth || !endYearMonth) && items && items.length) { let minYear = Number.MAX_SAFE_INTEGER, minMonth = Number.MAX_SAFE_INTEGER, maxYear = 0, maxMonth = 0; @@ -88,11 +71,12 @@ export function getAllDateRanges(items, startYearMonth, endYearMonth, dateAggreg if (!startYearMonth || !endYearMonth) { return []; } - if (dateAggregationType === statisticsConstants.allDateAggregationTypes.Year.type) { + + if (dateAggregationType === ChartDateAggregationType.Year.type) { return getAllYearsStartAndEndUnixTimes(startYearMonth, endYearMonth); - } else if (dateAggregationType === statisticsConstants.allDateAggregationTypes.Quarter.type) { + } else if (dateAggregationType === ChartDateAggregationType.Quarter.type) { return getAllQuartersStartAndEndUnixTimes(startYearMonth, endYearMonth); - } else { // if (dateAggregationType === statisticsConstants.allDateAggregationTypes.Month.type) { + } else { // if (dateAggregationType === ChartDateAggregationType.Month.type) { return getAllMonthsStartAndEndUnixTimes(startYearMonth, endYearMonth); } } diff --git a/src/stores/statistics.js b/src/stores/statistics.js index 71a514e1..bd617348 100644 --- a/src/stores/statistics.js +++ b/src/stores/statistics.js @@ -9,7 +9,16 @@ import { useExchangeRatesStore } from './exchangeRates.js'; import { DateRangeScene, DateRange } from '@/core/datetime'; import { CategoryType } from '@/core/category.ts'; import { TransactionTagFilterType } from '@/core/transaction.ts'; -import statisticsConstants from '@/consts/statistics.js'; +import { + StatisticsAnalysisType, + CategoricalChartType, + TrendChartType, + ChartDataType, + ChartSortingType, + ChartDateAggregationType, + DEFAULT_CATEGORICAL_CHART_DATA_RANGE, + DEFAULT_TREND_CHART_DATA_RANGE +} from '@/core/statistics.ts'; import { DEFAULT_ACCOUNT_ICON, DEFAULT_CATEGORY_ICON } from '@/consts/icon.ts'; import { DEFAULT_ACCOUNT_COLOR, DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts'; import services from '@/lib/services.js'; @@ -37,7 +46,7 @@ import { } from '@/lib/category.js'; import { sortStatisticsItems -} from '@/lib/statistics.js'; +} from '@/lib/statistics.ts'; function assembleAccountAndCategoryInfo(userStore, accountsStore, transactionCategoriesStore, exchangeRatesStore, items) { const finalItems = []; @@ -101,21 +110,21 @@ function getCategoryTotalAmountItems(items, transactionStatisticsFilter) { continue; } - if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByAccount.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByPrimaryCategory.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseBySecondaryCategory.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalExpense.type) { + if (transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByAccount.type || + transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type || + transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type || + transactionStatisticsFilter.chartDataType === ChartDataType.TotalExpense.type) { if (item.category.type !== CategoryType.Expense) { continue; } - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByAccount.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByPrimaryCategory.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeBySecondaryCategory.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalIncome.type) { + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByAccount.type || + transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByPrimaryCategory.type || + transactionStatisticsFilter.chartDataType === ChartDataType.IncomeBySecondaryCategory.type || + transactionStatisticsFilter.chartDataType === ChartDataType.TotalIncome.type) { if (item.category.type !== CategoryType.Income) { continue; } - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalBalance.type) { + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.TotalBalance.type) { // Do Nothing } else { continue; @@ -129,8 +138,8 @@ function getCategoryTotalAmountItems(items, transactionStatisticsFilter) { continue; } - if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByAccount.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByAccount.type) { + if (transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByAccount.type || + transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByAccount.type) { if (isNumber(item.amountInDefaultCurrency)) { let data = allDataItems[item.account.id]; @@ -157,8 +166,8 @@ function getCategoryTotalAmountItems(items, transactionStatisticsFilter) { allDataItems[item.account.id] = data; } - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByPrimaryCategory.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByPrimaryCategory.type) { + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type || + transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByPrimaryCategory.type) { if (isNumber(item.amountInDefaultCurrency)) { let data = allDataItems[item.primaryCategory.id]; @@ -185,8 +194,8 @@ function getCategoryTotalAmountItems(items, transactionStatisticsFilter) { allDataItems[item.primaryCategory.id] = data; } - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseBySecondaryCategory.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeBySecondaryCategory.type) { + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type || + transactionStatisticsFilter.chartDataType === ChartDataType.IncomeBySecondaryCategory.type) { if (isNumber(item.amountInDefaultCurrency)) { let data = allDataItems[item.category.id]; @@ -213,14 +222,14 @@ function getCategoryTotalAmountItems(items, transactionStatisticsFilter) { allDataItems[item.category.id] = data; } - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalExpense.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalIncome.type || - transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalBalance.type) { + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.TotalExpense.type || + transactionStatisticsFilter.chartDataType === ChartDataType.TotalIncome.type || + transactionStatisticsFilter.chartDataType === ChartDataType.TotalBalance.type) { if (isNumber(item.amountInDefaultCurrency)) { let data = allDataItems['total']; let amount = item.amountInDefaultCurrency; - if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalBalance.type && + if (transactionStatisticsFilter.chartDataType === ChartDataType.TotalBalance.type && item.category.type === CategoryType.Expense) { amount = -amount; } @@ -230,12 +239,12 @@ function getCategoryTotalAmountItems(items, transactionStatisticsFilter) { } else { let name = ''; - if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalExpense.type) { - name = statisticsConstants.allChartDataTypes.TotalExpense.name; - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalIncome.type) { - name = statisticsConstants.allChartDataTypes.TotalIncome.name; - } else if (transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalBalance.type) { - name = statisticsConstants.allChartDataTypes.TotalBalance.name; + if (transactionStatisticsFilter.chartDataType === ChartDataType.TotalExpense.type) { + name = ChartDataType.TotalExpense.name; + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.TotalIncome.type) { + name = ChartDataType.TotalIncome.name; + } else if (transactionStatisticsFilter.chartDataType === ChartDataType.TotalBalance.type) { + name = ChartDataType.TotalBalance.name; } data = { @@ -275,13 +284,13 @@ function sortCategoryTotalAmountItems(items, transactionStatisticsFilter) { export const useStatisticsStore = defineStore('statistics', { state: () => ({ transactionStatisticsFilter: { - chartDataType: statisticsConstants.defaultChartDataType, - categoricalChartType: statisticsConstants.defaultCategoricalChartType, - categoricalChartDateType: statisticsConstants.defaultCategoricalChartDataRangeType, + chartDataType: ChartDataType.Default.type, + categoricalChartType: CategoricalChartType.Default.type, + categoricalChartDateType: DEFAULT_CATEGORICAL_CHART_DATA_RANGE.type, categoricalChartStartTime: 0, categoricalChartEndTime: 0, - trendChartType: statisticsConstants.defaultTrendChartType, - trendChartDateType: statisticsConstants.defaultTrendChartDataRangeType, + trendChartType: TrendChartType.Default.type, + trendChartDateType: DEFAULT_TREND_CHART_DATA_RANGE.type, trendChartStartYearMonth: '', trendChartEndYearMonth: '', filterAccountIds: {}, @@ -295,15 +304,15 @@ export const useStatisticsStore = defineStore('statistics', { }), getters: { categoricalAnalysisChartDataCategory(state) { - if (state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByAccount.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByAccount.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalAssets.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalLiabilities.type) { + if (state.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByAccount.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByAccount.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalAssets.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalLiabilities.type) { return 'account'; - } else if (state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByPrimaryCategory.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseBySecondaryCategory.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByPrimaryCategory.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeBySecondaryCategory.type) { + } else if (state.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByPrimaryCategory.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeBySecondaryCategory.type) { return 'category'; } else { return ''; @@ -351,11 +360,11 @@ export const useStatisticsStore = defineStore('statistics', { for (let i = 0; i < accountsStore.allPlainAccounts.length; i++) { const account = accountsStore.allPlainAccounts[i]; - if (state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalAssets.type) { + if (state.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalAssets.type) { if (!account.isAsset) { continue; } - } else if (state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalLiabilities.type) { + } else if (state.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalLiabilities.type) { if (!account.isLiability) { continue; } @@ -417,15 +426,15 @@ export const useStatisticsStore = defineStore('statistics', { totalAmount: 0 }; - if (state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByAccount.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByPrimaryCategory.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseBySecondaryCategory.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByAccount.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByPrimaryCategory.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeBySecondaryCategory.type) { + if (state.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByAccount.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByAccount.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByPrimaryCategory.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeBySecondaryCategory.type) { combinedData = state.transactionCategoryTotalAmountAnalysisData; - } else if (state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalAssets.type || - state.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalLiabilities.type) { + } else if (state.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalAssets.type || + state.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalLiabilities.type) { combinedData = state.accountTotalAmountAnalysisData; } @@ -553,13 +562,13 @@ export const useStatisticsStore = defineStore('statistics', { this.transactionStatisticsStateInvalid = invalidState; }, resetTransactionStatistics() { - this.transactionStatisticsFilter.chartDataType = statisticsConstants.defaultChartDataType; - this.transactionStatisticsFilter.categoricalChartType = statisticsConstants.defaultCategoricalChartType; - this.transactionStatisticsFilter.categoricalChartDateType = statisticsConstants.defaultCategoricalChartDataRangeType; + this.transactionStatisticsFilter.chartDataType = ChartDataType.Default.type; + this.transactionStatisticsFilter.categoricalChartType = CategoricalChartType.Default.type; + this.transactionStatisticsFilter.categoricalChartDateType = DEFAULT_CATEGORICAL_CHART_DATA_RANGE.type; this.transactionStatisticsFilter.categoricalChartStartTime = 0; this.transactionStatisticsFilter.categoricalChartEndTime = 0; - this.transactionStatisticsFilter.trendChartType = statisticsConstants.defaultTrendChartType; - this.transactionStatisticsFilter.trendChartDateType = statisticsConstants.defaultTrendChartDataRangeType; + this.transactionStatisticsFilter.trendChartType = TrendChartType.Default.type; + this.transactionStatisticsFilter.trendChartDateType = DEFAULT_TREND_CHART_DATA_RANGE.type; this.transactionStatisticsFilter.trendChartStartYearMonth = ''; this.transactionStatisticsFilter.trendChartEndYearMonth = ''; this.transactionStatisticsFilter.filterAccountIds = {}; @@ -580,10 +589,9 @@ export const useStatisticsStore = defineStore('statistics', { this.transactionStatisticsFilter.chartDataType = settingsStore.appSettings.statistics.defaultChartDataType; } - if (analysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis || analysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) { - if (!statisticsConstants.allChartDataTypesMap[this.transactionStatisticsFilter.chartDataType] || - !statisticsConstants.allChartDataTypesMap[this.transactionStatisticsFilter.chartDataType].availableAnalysisTypes[analysisType]) { - this.transactionStatisticsFilter.chartDataType = statisticsConstants.defaultChartDataType; + if (analysisType === StatisticsAnalysisType.CategoricalAnalysis || analysisType === StatisticsAnalysisType.TrendAnalysis) { + if (!ChartDataType.isAvailableForAnalysisType(this.transactionStatisticsFilter.chartDataType, analysisType)) { + this.transactionStatisticsFilter.chartDataType = ChartDataType.Default.type; } } @@ -593,8 +601,8 @@ export const useStatisticsStore = defineStore('statistics', { this.transactionStatisticsFilter.categoricalChartType = settingsStore.appSettings.statistics.defaultCategoricalChartType; } - if (this.transactionStatisticsFilter.categoricalChartType !== statisticsConstants.allCategoricalChartTypes.Pie && this.transactionStatisticsFilter.categoricalChartType !== statisticsConstants.allCategoricalChartTypes.Bar) { - this.transactionStatisticsFilter.categoricalChartType = statisticsConstants.defaultCategoricalChartType; + if (this.transactionStatisticsFilter.categoricalChartType !== CategoricalChartType.Pie.type && this.transactionStatisticsFilter.categoricalChartType !== CategoricalChartType.Bar.type) { + this.transactionStatisticsFilter.categoricalChartType = CategoricalChartType.Default.type; } if (filter && isInteger(filter.categoricalChartDateType)) { @@ -606,7 +614,7 @@ export const useStatisticsStore = defineStore('statistics', { let categoricalChartDateTypeValid = true; if (!DateRange.isAvailableForScene(this.transactionStatisticsFilter.categoricalChartDateType, DateRangeScene.Normal)) { - this.transactionStatisticsFilter.categoricalChartDateType = statisticsConstants.defaultCategoricalChartDataRangeType; + this.transactionStatisticsFilter.categoricalChartDateType = DEFAULT_CATEGORICAL_CHART_DATA_RANGE.type; categoricalChartDateTypeValid = false; } @@ -635,8 +643,8 @@ export const useStatisticsStore = defineStore('statistics', { this.transactionStatisticsFilter.trendChartType = settingsStore.appSettings.statistics.defaultTrendChartType; } - if (this.transactionStatisticsFilter.trendChartType !== statisticsConstants.allTrendChartTypes.Area && this.transactionStatisticsFilter.trendChartType !== statisticsConstants.allTrendChartTypes.Column) { - this.transactionStatisticsFilter.trendChartType = statisticsConstants.defaultTrendChartType; + if (this.transactionStatisticsFilter.trendChartType !== TrendChartType.Area.type && this.transactionStatisticsFilter.trendChartType !== TrendChartType.Column.type) { + this.transactionStatisticsFilter.trendChartType = TrendChartType.Default.type; } if (filter && isInteger(filter.trendChartDateType)) { @@ -648,7 +656,7 @@ export const useStatisticsStore = defineStore('statistics', { let trendChartDateTypeValid = true; if (!DateRange.isAvailableForScene(this.transactionStatisticsFilter.trendChartDateType, DateRangeScene.TrendAnalysis)) { - this.transactionStatisticsFilter.trendChartDateType = statisticsConstants.defaultTrendChartDataRangeType; + this.transactionStatisticsFilter.trendChartDateType = DEFAULT_TREND_CHART_DATA_RANGE.type; trendChartDateTypeValid = false; } @@ -701,8 +709,8 @@ export const useStatisticsStore = defineStore('statistics', { this.transactionStatisticsFilter.sortingType = settingsStore.appSettings.statistics.defaultSortingType; } - if (this.transactionStatisticsFilter.sortingType < statisticsConstants.allSortingTypes.Amount.type || this.transactionStatisticsFilter.sortingType > statisticsConstants.allSortingTypes.Name.type) { - this.transactionStatisticsFilter.sortingType = statisticsConstants.defaultSortingType; + if (this.transactionStatisticsFilter.sortingType < ChartSortingType.Amount.type || this.transactionStatisticsFilter.sortingType > ChartSortingType.Name.type) { + this.transactionStatisticsFilter.sortingType = ChartSortingType.Default.type; } }, updateTransactionStatisticsFilter(filter) { @@ -786,7 +794,7 @@ export const useStatisticsStore = defineStore('statistics', { querys.push('analysisType=' + analysisType); querys.push('chartDataType=' + this.transactionStatisticsFilter.chartDataType); - if (analysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) { + if (analysisType === StatisticsAnalysisType.CategoricalAnalysis) { querys.push('chartType=' + this.transactionStatisticsFilter.categoricalChartType); querys.push('chartDateType=' + this.transactionStatisticsFilter.categoricalChartDateType); @@ -794,7 +802,7 @@ export const useStatisticsStore = defineStore('statistics', { querys.push('startTime=' + this.transactionStatisticsFilter.categoricalChartStartTime); querys.push('endTime=' + this.transactionStatisticsFilter.categoricalChartEndTime); } - } else if (analysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) { + } else if (analysisType === StatisticsAnalysisType.TrendAnalysis) { querys.push('chartType=' + this.transactionStatisticsFilter.trendChartType); querys.push('chartDateType=' + this.transactionStatisticsFilter.trendChartDateType); @@ -803,7 +811,7 @@ export const useStatisticsStore = defineStore('statistics', { querys.push('endTime=' + this.transactionStatisticsFilter.trendChartEndYearMonth); } - if (trendDateAggregationType !== statisticsConstants.allDateAggregationTypes.Month.type) { + if (trendDateAggregationType !== ChartDateAggregationType.Month.type) { querys.push('trendDateAggregationType=' + trendDateAggregationType); } } @@ -841,31 +849,31 @@ export const useStatisticsStore = defineStore('statistics', { const transactionCategoriesStore = useTransactionCategoriesStore(); const querys = []; - if (this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByAccount.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByPrimaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeBySecondaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalIncome.type) { + if (this.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByAccount.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByPrimaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeBySecondaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.TotalIncome.type) { querys.push('type=2'); - } else if (this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByAccount.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByPrimaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseBySecondaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.TotalExpense.type) { + } else if (this.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByAccount.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.TotalExpense.type) { querys.push('type=3'); } - if (itemId && (this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByAccount.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByAccount.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalAssets.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.AccountTotalLiabilities.type)) { + if (itemId && (this.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByAccount.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByAccount.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalAssets.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.AccountTotalLiabilities.type)) { querys.push('accountIds=' + itemId); if (!isObjectEmpty(this.transactionStatisticsFilter.filterCategoryIds)) { querys.push('categoryIds=' + getFinalCategoryIdsByFilteredCategoryIds(transactionCategoriesStore.allTransactionCategoriesMap, this.transactionStatisticsFilter.filterCategoryIds)); } - } else if (itemId && (this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeByPrimaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.IncomeBySecondaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseByPrimaryCategory.type - || this.transactionStatisticsFilter.chartDataType === statisticsConstants.allChartDataTypes.ExpenseBySecondaryCategory.type)) { + } else if (itemId && (this.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeByPrimaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.IncomeBySecondaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type + || this.transactionStatisticsFilter.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type)) { querys.push('categoryIds=' + itemId); if (!isObjectEmpty(this.transactionStatisticsFilter.filterAccountIds)) { @@ -889,16 +897,16 @@ export const useStatisticsStore = defineStore('statistics', { querys.push('tagFilterType=' + this.transactionStatisticsFilter.tagFilterType); } - if (analysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis - && this.transactionStatisticsFilter.chartDataType !== statisticsConstants.allChartDataTypes.AccountTotalAssets.type - && this.transactionStatisticsFilter.chartDataType !== statisticsConstants.allChartDataTypes.AccountTotalLiabilities.type) { + if (analysisType === StatisticsAnalysisType.CategoricalAnalysis + && this.transactionStatisticsFilter.chartDataType !== ChartDataType.AccountTotalAssets.type + && this.transactionStatisticsFilter.chartDataType !== ChartDataType.AccountTotalLiabilities.type) { querys.push('dateType=' + this.transactionStatisticsFilter.categoricalChartDateType); if (this.transactionStatisticsFilter.categoricalChartDateType === DateRange.Custom.type) { querys.push('minTime=' + this.transactionStatisticsFilter.categoricalChartStartTime); querys.push('maxTime=' + this.transactionStatisticsFilter.categoricalChartEndTime); } - } else if (analysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis && dateRange) { + } else if (analysisType === StatisticsAnalysisType.TrendAnalysis && dateRange) { querys.push('dateType=' + dateRange.type); querys.push('minTime=' + dateRange.minTime); querys.push('maxTime=' + dateRange.maxTime); diff --git a/src/views/desktop/app/settings/tabs/AppStatisticsSettingTab.vue b/src/views/desktop/app/settings/tabs/AppStatisticsSettingTab.vue index 3f74892e..fb182bd7 100644 --- a/src/views/desktop/app/settings/tabs/AppStatisticsSettingTab.vue +++ b/src/views/desktop/app/settings/tabs/AppStatisticsSettingTab.vue @@ -129,7 +129,7 @@ import { mapStores } from 'pinia'; import { useSettingsStore } from '@/stores/setting.js'; import { DateRangeScene } from '@/core/datetime.ts'; -import statisticsConstants from '@/consts/statistics.js'; +import { StatisticsAnalysisType } from '@/core/statistics.ts'; import AccountFilterSettingsCard from '@/views/desktop/common/cards/AccountFilterSettingsCard.vue'; import CategoryFilterSettingsCard from '@/views/desktop/common/cards/CategoryFilterSettingsCard.vue'; @@ -142,7 +142,7 @@ export default { computed: { ...mapStores(useSettingsStore), allChartDataTypes() { - return this.$locale.getAllStatisticsChartDataTypes(statisticsConstants.allAnalysisTypes.CategoricalAnalysis); + return this.$locale.getAllStatisticsChartDataTypes(StatisticsAnalysisType.CategoricalAnalysis); }, allTimezoneTypesUsedForStatistics() { return this.$locale.getAllTimezoneTypesUsedForStatistics(); diff --git a/src/views/desktop/statistics/TransactionPage.vue b/src/views/desktop/statistics/TransactionPage.vue index 3a28a592..d6139fd6 100644 --- a/src/views/desktop/statistics/TransactionPage.vue +++ b/src/views/desktop/statistics/TransactionPage.vue @@ -31,14 +31,14 @@ class="mt-2" density="compact" :disabled="loading" - :items="allSortingTypesArray" + :items="allSortingTypes" v-model="querySortingType" /> + v-for="dataType in allChartDataTypes" v-show="dataType.isAvailableAnalysisType(queryAnalysisType)"> {{ $t(dataType.name) }} {{ $t(dataType.name) }} @@ -97,7 +97,7 @@ @@ -155,7 +155,7 @@ {{ $t('No transaction data') }} - + +