use for-of statements to replace for and for-in

This commit is contained in:
MaysWind
2025-09-14 17:18:01 +08:00
parent 4700446ca0
commit 1a8ce7d58d
29 changed files with 455 additions and 579 deletions
@@ -151,14 +151,8 @@ function updateFrequencyValue(value: number, selected: boolean | null): void {
frequencyValue.value = sortNumbersArray(newFrequencyValues);
}
function isFrequencyValueSelected(value: number): boolean {
for (let i = 0; i < frequencyValue.value.length; i++) {
if (frequencyValue.value[i] === value) {
return true;
}
}
return false;
function isFrequencyValueSelected(currentValue: number): boolean {
return frequencyValue.value.indexOf(currentValue) >= 0;
}
function onMenuStateChanged(state: boolean): void {
@@ -56,6 +56,7 @@ import {
useAccountBalanceTrendsChartBase
} from '@/components/base/AccountBalanceTrendsChartBase.ts'
import { itemAndIndex } from '@/core/base.ts';
import type { ColorStyleValue } from '@/core/color.ts';
import { DEFAULT_CHART_COLORS } from '@/consts/color.ts';
@@ -88,15 +89,13 @@ const allVirtualListItems = computed<MobileAccountBalanceTrendsChartItem[]>(() =
const ret: MobileAccountBalanceTrendsChartItem[] = [];
let maxClosingBalance = 0;
for (let i = 0; i < allDataItems.value.length; i++) {
const dataItem = allDataItems.value[i];
for (const [dataItem, index] of itemAndIndex(allDataItems.value)) {
if (dataItem.closingBalance > maxClosingBalance) {
maxClosingBalance = dataItem.closingBalance;
}
const finalDataItem: MobileAccountBalanceTrendsChartItem = {
index: i,
index: index,
displayDate: dataItem.displayDate,
openingBalance: dataItem.openingBalance,
closingBalance: dataItem.closingBalance,
@@ -104,18 +103,18 @@ const allVirtualListItems = computed<MobileAccountBalanceTrendsChartItem[]>(() =
averageBalance: dataItem.averageBalance,
minimumBalance: dataItem.minimumBalance,
maximumBalance: dataItem.maximumBalance,
color: `#${DEFAULT_CHART_COLORS[0]}`,
color: `#${DEFAULT_CHART_COLORS[0] as string}`,
percent: 0.0
};
ret.push(finalDataItem);
}
for (let i = 0; i < ret.length; i++) {
if (maxClosingBalance > 0 && ret[i].closingBalance > 0) {
ret[i].percent = 100.0 * ret[i].closingBalance / maxClosingBalance;
for (const item of ret) {
if (maxClosingBalance > 0 && item.closingBalance > 0) {
item.percent = 100.0 * item.closingBalance / maxClosingBalance;
} else {
ret[i].percent = 0.0;
item.percent = 0.0;
}
}
@@ -72,6 +72,7 @@ import { type CommonScheduleFrequencySelectionProps, useScheduleFrequencySelecti
import { useUserStore } from '@/stores/user.ts';
import { itemAndIndex } from '@/core/base.ts';
import { type WeekDayValue } from '@/core/datetime.ts';
import { ScheduledTemplateFrequencyType } from '@/core/template.ts';
import { sortNumbersArray } from '@/lib/common.ts';
@@ -117,20 +118,20 @@ function changeFrequencyType(value: number): void {
}
function changeFrequencyValue(e: Event): void {
const value = parseInt((e.target as HTMLInputElement).value);
const currentValue = parseInt((e.target as HTMLInputElement).value);
if ((e.target as HTMLInputElement).checked) {
for (let i = 0; i < currentFrequencyValue.value.length; i++) {
if (currentFrequencyValue.value[i] === value) {
for (const value of currentFrequencyValue.value) {
if (value === currentValue) {
return;
}
}
currentFrequencyValue.value.push(value);
currentFrequencyValue.value.push(currentValue);
} else {
for (let i = 0; i < currentFrequencyValue.value.length; i++) {
if (currentFrequencyValue.value[i] === value) {
currentFrequencyValue.value.splice(i, 1);
for (const [value, index] of itemAndIndex(currentFrequencyValue.value)) {
if (value === currentValue) {
currentFrequencyValue.value.splice(index, 1);
break;
}
}
@@ -103,9 +103,7 @@ function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, unknown>): b
const lowerCaseFilterContent = filterContent.value?.toLowerCase() ?? '';
for (let i = 0; i < subItems.length; i++) {
const secondaryItem = subItems[i];
for (const secondaryItem of subItems) {
if (props.secondaryHiddenField && (secondaryItem as Record<string, unknown>)[props.secondaryHiddenField]) {
continue;
}
+46 -30
View File
@@ -1,4 +1,4 @@
import type { TypeAndName, TypeAndDisplayName } from './base.ts';
import { type TypeAndName, type TypeAndDisplayName, entries, keys } from './base.ts';
import { KnownAmountFormat } from './numeral.ts';
import { KnownDateTimeFormat } from './datetime.ts';
import { KnownDateTimezoneFormat } from './timezone.ts';
@@ -92,9 +92,9 @@ export class ImportTransactionDataMapping {
this.dataColumnMapping[columnType] = columnIndex;
}
for (const otherColumnType in this.dataColumnMapping) {
if (otherColumnType !== columnType.toString() && this.dataColumnMapping[otherColumnType] === columnIndex) {
delete this.dataColumnMapping[otherColumnType];
for (const otherColumnType of keys(this.dataColumnMapping)) {
if (otherColumnType !== columnType.toString() && this.dataColumnMapping[parseInt(otherColumnType)] === columnIndex) {
delete this.dataColumnMapping[parseInt(otherColumnType)];
}
}
}
@@ -119,16 +119,22 @@ export class ImportTransactionDataMapping {
const allTypeMap: Record<string, boolean> = {};
const allTypes: string[] = [];
const typeColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.TransactionType.type];
const typeColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.TransactionType.type] as number;
const startIndex = this.includeHeader ? 1 : 0;
for (let i = startIndex; i < fileData.length; i++) {
if (fileData[i].length <= typeColumnIndex) {
const items = fileData[i];
if (!items) {
continue;
}
const type = fileData[i][typeColumnIndex];
if (items.length <= typeColumnIndex) {
continue;
}
const type = items[typeColumnIndex];
if (type && !allTypeMap[type]) {
allTypes.push(type);
@@ -150,13 +156,7 @@ export class ImportTransactionDataMapping {
return result;
}
for (const name in this.transactionTypeMapping) {
if (!Object.prototype.hasOwnProperty.call(this.transactionTypeMapping, name)) {
continue;
}
const type = this.transactionTypeMapping[name];
for (const [name, type] of entries(this.transactionTypeMapping)) {
if (TransactionType.ModifyBalance <= type && type <= TransactionType.Transfer) {
result[name] = type;
}
@@ -171,16 +171,22 @@ export class ImportTransactionDataMapping {
}
const allDateTimes: string[] = [];
const dateTimeColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.TransactionTime.type];
const dateTimeColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.TransactionTime.type] as number;
const startIndex = this.includeHeader ? 1 : 0;
for (let i = startIndex; i < fileData.length; i++) {
if (fileData[i].length <= dateTimeColumnIndex) {
const items = fileData[i];
if (!items) {
continue;
}
const dateTime = fileData[i][dateTimeColumnIndex];
if (items.length <= dateTimeColumnIndex) {
continue;
}
const dateTime = items[dateTimeColumnIndex];
if (dateTime) {
allDateTimes.push(dateTime);
@@ -193,7 +199,7 @@ export class ImportTransactionDataMapping {
return undefined;
}
return detectedFormats[0].format;
return detectedFormats[0]!.format;
}
public parseFileAutoDetectedTimezoneFormat(fileData: string[][] | undefined): string | undefined {
@@ -202,16 +208,22 @@ export class ImportTransactionDataMapping {
}
const allTimezones: string[] = [];
const timezoneColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.TransactionTimezone.type];
const timezoneColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.TransactionTimezone.type] as number;
const startIndex = this.includeHeader ? 1 : 0;
for (let i = startIndex; i < fileData.length; i++) {
if (fileData[i].length <= timezoneColumnIndex) {
const items = fileData[i];
if (!items) {
continue;
}
const timezone = fileData[i][timezoneColumnIndex];
if (items.length <= timezoneColumnIndex) {
continue;
}
const timezone = items[timezoneColumnIndex];
if (timezone) {
allTimezones.push(timezone);
@@ -224,7 +236,7 @@ export class ImportTransactionDataMapping {
return undefined;
}
return detectedFormats[0].value;
return detectedFormats[0]!.value;
}
public parseFileAutoDetectedAmountFormat(fileData: string[][] | undefined): string | undefined {
@@ -233,16 +245,22 @@ export class ImportTransactionDataMapping {
}
const allAmounts: string[] = [];
const amountColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.Amount.type];
const amountColumnIndex = this.dataColumnMapping[ImportTransactionColumnType.Amount.type] as number;
const startIndex = this.includeHeader ? 1 : 0;
for (let i = startIndex; i < fileData.length; i++) {
if (fileData[i].length <= amountColumnIndex) {
const items = fileData[i];
if (!items) {
continue;
}
const amount = fileData[i][amountColumnIndex];
if (items.length <= amountColumnIndex) {
continue;
}
const amount = items[amountColumnIndex];
if (amount) {
allAmounts.push(amount);
@@ -255,7 +273,7 @@ export class ImportTransactionDataMapping {
return undefined;
}
return detectedFormats[0].type;
return detectedFormats[0]!.type;
}
public reset(): void {
@@ -382,8 +400,7 @@ export class ImportTransactionReplaceRules {
public toJson(): string {
const result: unknown[] = [];
for (let i = 0; i < this.rules.length; i++) {
const rule = this.rules[i];
for (const rule of this.rules) {
result.push(rule.toJsonObject());
}
@@ -407,8 +424,7 @@ export class ImportTransactionReplaceRules {
const result = new ImportTransactionReplaceRules([]);
for (let i = 0; i < root.length; i++) {
const rule = root[i];
for (const rule of root) {
const replaceRule = ImportTransactionReplaceRule.parse(rule);
if (replaceRule) {
@@ -3,6 +3,8 @@ import path from 'path';
import { describe, expect, test } from '@jest/globals';
import { DEFAULT_CONTENT } from '@/locales/calendar/chinese/index.ts';
import { itemAndIndex, entries } from '@/core/base.ts';
import type { ChineseCalendarLocaleData } from '@/core/calendar.ts';
import {
type ChineseYearMonthDayInfo,
@@ -90,12 +92,12 @@ describe('getChineseYearMonthAllDayInfos', () => {
allMonthChineseDays[`${currentYear}-${currentMonth}`] = currentMonthChineseDays;
allMonthSolarTermNames[`${currentYear}-${currentMonth}`] = currentMonthSolarTermNames;
for (const yearMonth in allMonthChineseDays) {
for (const [yearMonth, monthChineseDays] of entries(allMonthChineseDays)) {
test(`returns correct chinese all dates in month for ${yearMonth}`, () => {
const [yearStr, monthStr] = yearMonth.split('-');
const year = parseInt(yearStr as string);
const month = parseInt(monthStr as string);
const expectedChineseMonthOrDays = allMonthChineseDays[yearMonth] as string[];
const expectedChineseMonthOrDays = monthChineseDays;
const expectedSolarTermNames = allMonthSolarTermNames[yearMonth] as string[];
const actualChineseDates: ChineseYearMonthDayInfo[] | undefined = getChineseYearMonthAllDayInfos({
@@ -106,13 +108,12 @@ describe('getChineseYearMonthAllDayInfos', () => {
expect(actualChineseDates).toBeDefined();
if (actualChineseDates) {
for (let i = 0; i < actualChineseDates.length; i++) {
const actualChineseDate = actualChineseDates[i];
for (const [actualChineseDate, index] of itemAndIndex(actualChineseDates)) {
const chineseMonthOrDay: string | undefined = actualChineseDate?.day === 1 ? `${actualChineseDate?.month}${ordinalSuffix[actualChineseDate?.month - 1] ?? 'th'} Lunar Month`.toLowerCase() : actualChineseDate?.day.toString();
expect(actualChineseDate).toBeDefined();
expect(chineseMonthOrDay).toBe(expectedChineseMonthOrDays[i]);
expect(actualChineseDate?.solarTermName).toBe(expectedSolarTermNames[i]);
expect(chineseMonthOrDay).toBe(expectedChineseMonthOrDays[index]);
expect(actualChineseDate?.solarTermName).toBe(expectedSolarTermNames[index]);
}
}
});
+2 -2
View File
@@ -71,7 +71,7 @@ export function localizedPresetCategoriesToTransactionCategoryCreateWithSubCateg
return categories;
}
export function getSecondaryTransactionMapByName(allCategories: TransactionCategory[]): Record<string, TransactionCategory> {
export function getSecondaryTransactionMapByName(allCategories?: TransactionCategory[]): Record<string, TransactionCategory> {
const ret: Record<string, TransactionCategory> = {};
if (!allCategories) {
@@ -274,7 +274,7 @@ export function isSubCategoryIdAvailable(categories: TransactionCategory[], cate
return false;
}
export function getFirstAvailableCategoryId(categories: TransactionCategory[]): string {
export function getFirstAvailableCategoryId(categories?: TransactionCategory[]): string {
if (!categories || !categories.length) {
return '';
}
+11 -15
View File
@@ -431,8 +431,8 @@ export function countSplitItems(str: string | undefined | null, separator: strin
const items = str.split(separator);
let count = 0;
for (let i = 0; i < items.length; i++) {
if (items[i]) {
for (const item of items) {
if (item) {
count++;
}
}
@@ -483,9 +483,13 @@ export function selectInvert(filterItemIds: Record<string, boolean>, allItemsMap
}
export function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, Record<string, unknown>[]>, primarySubItemsField: string, secondaryValueField: string | undefined, secondaryHiddenField: string | undefined, secondaryValue: unknown): boolean {
for (let i = 0; i < primaryItem[primarySubItemsField].length; i++) {
const secondaryItem = primaryItem[primarySubItemsField][i];
const secondaryItems = primaryItem[primarySubItemsField];
if (!secondaryItems || secondaryItems.length < 1) {
return false;
}
for (const secondaryItem of secondaryItems) {
if (secondaryHiddenField && secondaryItem[secondaryHiddenField]) {
continue;
}
@@ -500,14 +504,12 @@ export function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, Recor
return false;
}
export function getPrimaryValueBySecondaryValue<T>(items: Record<string, Record<string, T>[]>[] | Record<string, Record<string, Record<string, T>[]>>, primarySubItemsField: string | undefined, primaryValueField: string | undefined, primaryHiddenField: string | undefined, secondaryValueField: string | undefined, secondaryHiddenField: string | undefined, secondaryValue: T): Record<string, T>[] | Record<string, Record<string, T>[]> | null {
export function getPrimaryValueBySecondaryValue<T>(items: Record<string, Record<string, T>[]>[] | Record<string, Record<string, Record<string, T>[]>>, primarySubItemsField: string | undefined, primaryValueField: string | undefined, primaryHiddenField: string | undefined, secondaryValueField: string | undefined, secondaryHiddenField: string | undefined, secondaryValue: T): Record<string, T>[] | Record<string, Record<string, T>[]> | null | undefined {
if (primarySubItemsField) {
if (isArray(items)) {
const arr = items as Record<string, Record<string, T>[]>[];
for (let i = 0; i < arr.length; i++) {
const primaryItem = arr[i];
for (const primaryItem of arr) {
if (primaryHiddenField && primaryItem[primaryHiddenField]) {
continue;
}
@@ -523,13 +525,7 @@ export function getPrimaryValueBySecondaryValue<T>(items: Record<string, Record<
} else {
const obj = items as Record<string, Record<string, Record<string, T>[]>>;
for (const field in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, field)) {
continue;
}
const primaryItem = obj[field];
for (const primaryItem of values(obj)) {
if (primaryHiddenField && primaryItem[primaryHiddenField]) {
continue;
}
+1 -3
View File
@@ -224,9 +224,7 @@ export class LeafletMapInstance implements MapInstance {
private getFinalUrlFormat(urlFormat: string, urlExtraParams: LeafletTileSourceExtraParam[], options: MapInstanceInitOptions) {
const params: string[] = [];
for (let i = 0; i < urlExtraParams.length; i++) {
const param = urlExtraParams[i];
for (const param of urlExtraParams) {
if (param.paramValueType === 'tomtom_key') {
params.push(param.paramName + '=' + getTomTomMapAPIKey());
} else if (param.paramValueType === 'tianditu_key') {
+6 -6
View File
@@ -221,7 +221,7 @@ export class Account implements AccountInfoResponse {
};
}
public getAccountOrSubAccountId(subAccountId: string): string | null {
public getAccountOrSubAccountId(subAccountId?: string): string | null {
if (this.type === AccountType.SingleAccount.type) {
return this.id;
} else if (this.type === AccountType.MultiSubAccounts.type && !subAccountId) {
@@ -243,7 +243,7 @@ export class Account implements AccountInfoResponse {
}
}
public isAccountOrSubAccountHidden(subAccountId: string): boolean {
public isAccountOrSubAccountHidden(subAccountId?: string): boolean {
if (this.type === AccountType.SingleAccount.type) {
return this.hidden;
} else if (this.type === AccountType.MultiSubAccounts.type && !subAccountId) {
@@ -265,7 +265,7 @@ export class Account implements AccountInfoResponse {
}
}
public getAccountOrSubAccountComment(subAccountId: string): string | null {
public getAccountOrSubAccountComment(subAccountId?: string): string | null {
if (this.type === AccountType.SingleAccount.type) {
return this.comment;
} else if (this.type === AccountType.MultiSubAccounts.type && !subAccountId) {
@@ -287,7 +287,7 @@ export class Account implements AccountInfoResponse {
}
}
public getAccountOrSubAccount(subAccountId: string): Account | null {
public getAccountOrSubAccount(subAccountId?: string): Account | null {
if (this.type === AccountType.SingleAccount.type) {
return this;
} else if (this.type === AccountType.MultiSubAccounts.type && !subAccountId) {
@@ -309,7 +309,7 @@ export class Account implements AccountInfoResponse {
}
}
public getSubAccount(subAccountId: string): Account | null {
public getSubAccount(subAccountId?: string): Account | null {
if (!this.subAccounts || !this.subAccounts.length) {
return null;
}
@@ -323,7 +323,7 @@ export class Account implements AccountInfoResponse {
return null;
}
public getSubAccountCurrencies(showHidden: boolean, subAccountId: string): string[] {
public getSubAccountCurrencies(showHidden: boolean, subAccountId?: string): string[] {
if (!this.subAccounts || !this.subAccounts.length) {
return [];
}
+3 -3
View File
@@ -140,15 +140,15 @@ export class Transaction implements TransactionInfoResponse {
}
}
public setCategory(category: TransactionCategory): void {
public setCategory(category?: TransactionCategory): void {
this._category = category;
}
public setSourceAccount(sourceAccount: Account): void {
public setSourceAccount(sourceAccount?: Account): void {
this._sourceAccount = sourceAccount;
}
public setDestinationAccount(destinationAccount: Account): void {
public setDestinationAccount(destinationAccount?: Account): void {
this._destinationAccount = destinationAccount;
}
+132 -180
View File
@@ -5,7 +5,7 @@ import { useSettingsStore } from './setting.ts';
import { useUserStore } from './user.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import type { BeforeResolveFunction } from '@/core/base.ts';
import { type BeforeResolveFunction, itemAndIndex, reversed, entries, values } from '@/core/base.ts';
import type { HiddenAmount, NumberWithSuffix } from '@/core/numeral.ts';
import { AccountType, AccountCategory } from '@/core/account.ts';
import { DISPLAY_HIDDEN_AMOUNT, INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numeral.ts';
@@ -36,15 +36,12 @@ export const useAccountsStore = defineStore('accounts', () => {
const allPlainAccounts = computed<Account[]>(() => {
const allAccountsList: Account[] = [];
for (let i = 0; i < allAccounts.value.length; i++) {
const account = allAccounts.value[i];
for (const account of allAccounts.value) {
if (account.type === AccountType.SingleAccount.type) {
allAccountsList.push(account);
} else if (account.type === AccountType.MultiSubAccounts.type) {
if (account.subAccounts) {
for (let j = 0; j < account.subAccounts.length; j++) {
const subAccount = account.subAccounts[j];
for (const subAccount of account.subAccounts) {
allAccountsList.push(subAccount);
}
}
@@ -57,17 +54,14 @@ export const useAccountsStore = defineStore('accounts', () => {
const allMixedPlainAccounts = computed<Account[]>(() => {
const allAccountsList: Account[] = [];
for (let i = 0; i < allAccounts.value.length; i++) {
const account = allAccounts.value[i];
for (const account of allAccounts.value) {
if (account.type === AccountType.SingleAccount.type) {
allAccountsList.push(account);
} else if (account.type === AccountType.MultiSubAccounts.type) {
allAccountsList.push(account);
if (account.subAccounts) {
for (let j = 0; j < account.subAccounts.length; j++) {
const subAccount = account.subAccounts[j];
for (const subAccount of account.subAccounts) {
allAccountsList.push(subAccount);
}
}
@@ -80,9 +74,7 @@ export const useAccountsStore = defineStore('accounts', () => {
const allVisiblePlainAccounts = computed<Account[]>(() => {
const allVisibleAccounts: Account[] = [];
for (let i = 0; i < allAccounts.value.length; i++) {
const account = allAccounts.value[i];
for (const account of allAccounts.value) {
if (account.hidden) {
continue;
}
@@ -91,8 +83,7 @@ export const useAccountsStore = defineStore('accounts', () => {
allVisibleAccounts.push(account);
} else if (account.type === AccountType.MultiSubAccounts.type) {
if (account.subAccounts) {
for (let j = 0; j < account.subAccounts.length; j++) {
const subAccount = account.subAccounts[j];
for (const subAccount of account.subAccounts) {
if (subAccount.hidden) {
continue;
@@ -110,12 +101,8 @@ export const useAccountsStore = defineStore('accounts', () => {
const allAvailableAccountsCount = computed<number>(() => {
let allAccountCount = 0;
for (const category in allCategorizedAccountsMap.value) {
if (!Object.prototype.hasOwnProperty.call(allCategorizedAccountsMap.value, category)) {
continue;
}
allAccountCount += allCategorizedAccountsMap.value[category].accounts.length;
for (const categorizedAccounts of values(allCategorizedAccountsMap.value)) {
allAccountCount += categorizedAccounts.accounts.length;
}
return allAccountCount;
@@ -124,15 +111,11 @@ export const useAccountsStore = defineStore('accounts', () => {
const allVisibleAccountsCount = computed<number>(() => {
let shownAccountCount = 0;
for (const category in allCategorizedAccountsMap.value) {
if (!Object.prototype.hasOwnProperty.call(allCategorizedAccountsMap.value, category)) {
continue;
}
for (const categorizedAccounts of values(allCategorizedAccountsMap.value)) {
const accountList = categorizedAccounts.accounts;
const accountList = allCategorizedAccountsMap.value[category].accounts;
for (let i = 0; i < accountList.length; i++) {
if (!accountList[i].hidden) {
for (const account of accountList) {
if (!account.hidden) {
shownAccountCount++;
}
}
@@ -145,13 +128,11 @@ export const useAccountsStore = defineStore('accounts', () => {
allAccounts.value = accounts;
allAccountsMap.value = {};
for (let i = 0; i < accounts.length; i++) {
const account = accounts[i];
for (const account of accounts) {
allAccountsMap.value[account.id] = account;
if (account.subAccounts) {
for (let j = 0; j < account.subAccounts.length; j++) {
const subAccount = account.subAccounts[j];
for (const subAccount of account.subAccounts) {
allAccountsMap.value[subAccount.id] = subAccount;
}
}
@@ -160,51 +141,49 @@ export const useAccountsStore = defineStore('accounts', () => {
allCategorizedAccountsMap.value = getCategorizedAccountsMap(accounts);
}
function addAccountToAccountList(account: Account): void {
const newAccountCategory = AccountCategory.valueOf(account.category);
function addAccountToAccountList(currentAccount: Account): void {
const newAccountCategory = AccountCategory.valueOf(currentAccount.category);
let insertIndexToAllList = allAccounts.value.length;
if (newAccountCategory) {
for (let i = 0; i < allAccounts.value.length; i++) {
const accountCategory = AccountCategory.valueOf(allAccounts.value[i].category);
for (const [account, index] of itemAndIndex(allAccounts.value)) {
const accountCategory = AccountCategory.valueOf(account.category);
if (accountCategory && accountCategory.displayOrder > newAccountCategory.displayOrder) {
insertIndexToAllList = i;
insertIndexToAllList = index;
break;
}
}
}
allAccounts.value.splice(insertIndexToAllList, 0, account);
allAccounts.value.splice(insertIndexToAllList, 0, currentAccount);
allAccountsMap.value[account.id] = account;
allAccountsMap.value[currentAccount.id] = currentAccount;
if (account.subAccounts) {
for (let i = 0; i < account.subAccounts.length; i++) {
const subAccount = account.subAccounts[i];
if (currentAccount.subAccounts) {
for (const subAccount of currentAccount.subAccounts) {
allAccountsMap.value[subAccount.id] = subAccount;
}
}
if (allCategorizedAccountsMap.value[account.category]) {
const accountList = allCategorizedAccountsMap.value[account.category].accounts;
accountList.push(account);
if (allCategorizedAccountsMap.value[currentAccount.category]) {
const accountList = allCategorizedAccountsMap.value[currentAccount.category]!.accounts;
accountList.push(currentAccount);
} else {
allCategorizedAccountsMap.value = getCategorizedAccountsMap(allAccounts.value);
}
}
function updateAccountToAccountList(oldAccount: Account, newAccount: Account): void {
for (let i = 0; i < allAccounts.value.length; i++) {
if (allAccounts.value[i].id === newAccount.id) {
allAccounts.value.splice(i, 1, newAccount);
for (const [account, index] of itemAndIndex(allAccounts.value)) {
if (account.id === newAccount.id) {
allAccounts.value.splice(index, 1, newAccount);
break;
}
}
if (oldAccount.subAccounts) {
for (let i = 0; i < oldAccount.subAccounts.length; i++) {
const subAccount = oldAccount.subAccounts[i];
for (const subAccount of oldAccount.subAccounts) {
if (allAccountsMap.value[subAccount.id]) {
delete allAccountsMap.value[subAccount.id];
}
@@ -214,18 +193,17 @@ export const useAccountsStore = defineStore('accounts', () => {
allAccountsMap.value[newAccount.id] = newAccount;
if (newAccount.subAccounts) {
for (let i = 0; i < newAccount.subAccounts.length; i++) {
const subAccount = newAccount.subAccounts[i];
for (const subAccount of newAccount.subAccounts) {
allAccountsMap.value[subAccount.id] = subAccount;
}
}
if (allCategorizedAccountsMap.value[newAccount.category]) {
const accountList = allCategorizedAccountsMap.value[newAccount.category].accounts;
const accountList = allCategorizedAccountsMap.value[newAccount.category]!.accounts;
for (let i = 0; i < accountList.length; i++) {
if (accountList[i].id === newAccount.id) {
accountList.splice(i, 1, newAccount);
for (const [account, index] of itemAndIndex(accountList)) {
if (account.id === newAccount.id) {
accountList.splice(index, 1, newAccount);
break;
}
}
@@ -237,12 +215,12 @@ export const useAccountsStore = defineStore('accounts', () => {
let toAccount = null;
if (allCategorizedAccountsMap.value[account.category]) {
const accountList = allCategorizedAccountsMap.value[account.category].accounts;
const accountList = allCategorizedAccountsMap.value[account.category]!.accounts;
if (updateListOrder) {
fromAccount = accountList[from];
toAccount = accountList[to];
accountList.splice(to, 0, accountList.splice(from, 1)[0]);
accountList.splice(to, 0, accountList.splice(from, 1)[0] as Account);
} else {
fromAccount = accountList[to];
@@ -258,94 +236,93 @@ export const useAccountsStore = defineStore('accounts', () => {
let globalFromIndex = -1;
let globalToIndex = -1;
for (let i = 0; i < allAccounts.value.length; i++) {
if (allAccounts.value[i].id === fromAccount.id) {
globalFromIndex = i;
} else if (allAccounts.value[i].id === toAccount.id) {
globalToIndex = i;
for (const [account, index] of itemAndIndex(allAccounts.value)) {
if (account.id === fromAccount.id) {
globalFromIndex = index;
} else if (account.id === toAccount.id) {
globalToIndex = index;
}
}
if (globalFromIndex >= 0 && globalToIndex >= 0) {
allAccounts.value.splice(globalToIndex, 0, allAccounts.value.splice(globalFromIndex, 1)[0]);
allAccounts.value.splice(globalToIndex, 0, allAccounts.value.splice(globalFromIndex, 1)[0] as Account);
}
}
}
function updateAccountVisibilityInAccountList({ account, hidden }: { account: Account, hidden: boolean }): void {
if (allAccountsMap.value[account.id]) {
allAccountsMap.value[account.id].visible = !hidden;
allAccountsMap.value[account.id]!.visible = !hidden;
}
}
function removeAccountFromAccountList(account: Account): void {
for (let i = 0; i < allAccounts.value.length; i++) {
if (allAccounts.value[i].id === account.id) {
allAccounts.value.splice(i, 1);
function removeAccountFromAccountList(currentAccount: Account): void {
for (const [account, index] of itemAndIndex(allAccounts.value)) {
if (account.id === currentAccount.id) {
allAccounts.value.splice(index, 1);
break;
}
}
if (allAccountsMap.value[account.id] && allAccountsMap.value[account.id].subAccounts) {
const subAccounts = allAccountsMap.value[account.id].subAccounts as Account[];
if (allAccountsMap.value[currentAccount.id] && allAccountsMap.value[currentAccount.id]!.subAccounts) {
const subAccounts = allAccountsMap.value[currentAccount.id]!.subAccounts as Account[];
for (let i = 0; i < subAccounts.length; i++) {
const subAccount = subAccounts[i];
for (const subAccount of subAccounts) {
if (allAccountsMap.value[subAccount.id]) {
delete allAccountsMap.value[subAccount.id];
}
}
}
if (allAccountsMap.value[account.id]) {
delete allAccountsMap.value[account.id];
if (allAccountsMap.value[currentAccount.id]) {
delete allAccountsMap.value[currentAccount.id];
}
if (allCategorizedAccountsMap.value[account.category]) {
const accountList = allCategorizedAccountsMap.value[account.category].accounts;
if (allCategorizedAccountsMap.value[currentAccount.category]) {
const accountList = allCategorizedAccountsMap.value[currentAccount.category]!.accounts;
for (let i = 0; i < accountList.length; i++) {
if (accountList[i].id === account.id) {
accountList.splice(i, 1);
for (const [account, index] of itemAndIndex(accountList)) {
if (account.id === currentAccount.id) {
accountList.splice(index, 1);
break;
}
}
}
}
function removeSubAccountFromAccountList(subAccount: Account): void {
for (let i = 0; i < allAccounts.value.length; i++) {
if (allAccounts.value[i].type !== AccountType.MultiSubAccounts.type || !allAccounts.value[i].subAccounts) {
function removeSubAccountFromAccountList(currentSubAccount: Account): void {
for (const account of allAccounts.value) {
if (account.type !== AccountType.MultiSubAccounts.type || !account.subAccounts) {
continue;
}
const subAccounts = allAccounts.value[i].subAccounts as Account[];
const subAccounts = account.subAccounts as Account[];
for (let j = 0; j < subAccounts.length; j++) {
if (subAccounts[j].id === subAccount.id) {
subAccounts.splice(j, 1);
for (const [subAccount, index] of itemAndIndex(subAccounts)) {
if (subAccount.id === currentSubAccount.id) {
subAccounts.splice(index, 1);
break;
}
}
}
if (allAccountsMap.value[subAccount.id]) {
delete allAccountsMap.value[subAccount.id];
if (allAccountsMap.value[currentSubAccount.id]) {
delete allAccountsMap.value[currentSubAccount.id];
}
if (allCategorizedAccountsMap.value[subAccount.category]) {
const accountList = allCategorizedAccountsMap.value[subAccount.category].accounts;
if (allCategorizedAccountsMap.value[currentSubAccount.category]) {
const accountList = allCategorizedAccountsMap.value[currentSubAccount.category]!.accounts;
for (let i = 0; i < accountList.length; i++) {
if (accountList[i].type !== AccountType.MultiSubAccounts.type || !accountList[i].subAccounts) {
for (const account of accountList) {
if (account.type !== AccountType.MultiSubAccounts.type || !account.subAccounts) {
continue;
}
const subAccounts = accountList[i].subAccounts as Account[];
const subAccounts = account.subAccounts as Account[];
for (let j = 0; j < subAccounts.length; j++) {
if (subAccounts[j].id === subAccount.id) {
subAccounts.splice(j, 1);
for (const [subAccount, index] of itemAndIndex(subAccounts)) {
if (subAccount.id === currentSubAccount.id) {
subAccounts.splice(index, 1);
break;
}
}
@@ -370,24 +347,16 @@ export const useAccountsStore = defineStore('accounts', () => {
subAccounts: {}
};
for (const category in allCategorizedAccountsMap.value) {
if (!Object.prototype.hasOwnProperty.call(allCategorizedAccountsMap.value, category)) {
for (const [category, categorizedAccounts] of entries(allCategorizedAccountsMap.value)) {
if (!categorizedAccounts || !categorizedAccounts.accounts) {
continue;
}
if (!allCategorizedAccountsMap.value[category] || !allCategorizedAccountsMap.value[category].accounts) {
continue;
}
const accounts = allCategorizedAccountsMap.value[category].accounts;
for (let i = 0; i < accounts.length; i++) {
const account = accounts[i];
const accounts = categorizedAccounts.accounts;
for (const account of accounts) {
if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) {
for (let j = 0; j < account.subAccounts.length; j++) {
const subAccount = account.subAccounts[j];
for (const subAccount of account.subAccounts) {
if (showHidden || !subAccount.hidden) {
ret.subAccounts[account.id] = subAccount.id;
break;
@@ -396,7 +365,7 @@ export const useAccountsStore = defineStore('accounts', () => {
}
if (showHidden || !account.hidden) {
ret.accounts[category] = account.id;
ret.accounts[parseInt(category)] = account.id;
break;
}
}
@@ -411,24 +380,16 @@ export const useAccountsStore = defineStore('accounts', () => {
subAccounts: {}
};
for (const category in allCategorizedAccountsMap.value) {
if (!Object.prototype.hasOwnProperty.call(allCategorizedAccountsMap.value, category)) {
for (const [category, categorizedAccounts] of entries(allCategorizedAccountsMap.value)) {
if (!categorizedAccounts || !categorizedAccounts.accounts) {
continue;
}
if (!allCategorizedAccountsMap.value[category] || !allCategorizedAccountsMap.value[category].accounts) {
continue;
}
const accounts = allCategorizedAccountsMap.value[category].accounts;
for (let i = accounts.length - 1; i >= 0; i--) {
const account = accounts[i];
const accounts = categorizedAccounts.accounts;
for (const account of reversed(accounts)) {
if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) {
for (let j = account.subAccounts.length - 1; j >= 0; j--) {
const subAccount = account.subAccounts[j];
for (const subAccount of reversed(account.subAccounts)) {
if (showHidden || !subAccount.hidden) {
ret.subAccounts[account.id] = subAccount.id;
break;
@@ -437,7 +398,7 @@ export const useAccountsStore = defineStore('accounts', () => {
}
if (showHidden || !account.hidden) {
ret.accounts[category] = account.id;
ret.accounts[parseInt(category)] = account.id;
break;
}
}
@@ -454,9 +415,8 @@ export const useAccountsStore = defineStore('accounts', () => {
const accountIds = accountId.split(',');
let mainAccount = null;
for (let i = 0; i < accountIds.length; i++) {
const id = accountIds[i];
let account = allAccountsMap.value[id];
for (const accountId of accountIds) {
let account = allAccountsMap.value[accountId];
if (!account) {
return null;
@@ -466,7 +426,11 @@ export const useAccountsStore = defineStore('accounts', () => {
account = allAccountsMap.value[account.parentId];
}
if (mainAccount !== null) {
if (!account) {
return null;
}
if (mainAccount) {
if (mainAccount.id !== account.id) {
return null;
} else {
@@ -499,11 +463,11 @@ export const useAccountsStore = defineStore('accounts', () => {
let netAssets = 0;
let hasUnCalculatedAmount = false;
for (let i = 0; i < accountsBalance.length; i++) {
if (accountsBalance[i].currency === userStore.currentUserDefaultCurrency) {
netAssets += accountsBalance[i].balance;
for (const accountBalance of accountsBalance) {
if (accountBalance.currency === userStore.currentUserDefaultCurrency) {
netAssets += accountBalance.balance;
} else {
const balance = exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, userStore.currentUserDefaultCurrency);
const balance = exchangeRatesStore.getExchangedAmount(accountBalance.balance, accountBalance.currency, userStore.currentUserDefaultCurrency);
if (!isNumber(balance)) {
hasUnCalculatedAmount = true;
@@ -535,11 +499,11 @@ export const useAccountsStore = defineStore('accounts', () => {
let totalAssets = 0;
let hasUnCalculatedAmount = false;
for (let i = 0; i < accountsBalance.length; i++) {
if (accountsBalance[i].currency === userStore.currentUserDefaultCurrency) {
totalAssets += accountsBalance[i].balance;
for (const accountBalance of accountsBalance) {
if (accountBalance.currency === userStore.currentUserDefaultCurrency) {
totalAssets += accountBalance.balance;
} else {
const balance = exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, userStore.currentUserDefaultCurrency);
const balance = exchangeRatesStore.getExchangedAmount(accountBalance.balance, accountBalance.currency, userStore.currentUserDefaultCurrency);
if (!isNumber(balance)) {
hasUnCalculatedAmount = true;
@@ -571,11 +535,11 @@ export const useAccountsStore = defineStore('accounts', () => {
let totalLiabilities = 0;
let hasUnCalculatedAmount = false;
for (let i = 0; i < accountsBalance.length; i++) {
if (accountsBalance[i].currency === userStore.currentUserDefaultCurrency) {
totalLiabilities -= accountsBalance[i].balance;
for (const accountBalance of accountsBalance) {
if (accountBalance.currency === userStore.currentUserDefaultCurrency) {
totalLiabilities -= accountBalance.balance;
} else {
const balance = exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, userStore.currentUserDefaultCurrency);
const balance = exchangeRatesStore.getExchangedAmount(accountBalance.balance, accountBalance.currency, userStore.currentUserDefaultCurrency);
if (!isNumber(balance)) {
hasUnCalculatedAmount = true;
@@ -605,26 +569,26 @@ export const useAccountsStore = defineStore('accounts', () => {
let totalBalance = 0;
let hasUnCalculatedAmount = false;
for (let i = 0; i < accountsBalance.length; i++) {
if (accountsBalance[i].currency === userStore.currentUserDefaultCurrency) {
if (accountsBalance[i].isAsset) {
totalBalance += accountsBalance[i].balance;
} else if (accountsBalance[i].isLiability) {
totalBalance -= accountsBalance[i].balance;
for (const accountBalance of accountsBalance) {
if (accountBalance.currency === userStore.currentUserDefaultCurrency) {
if (accountBalance.isAsset) {
totalBalance += accountBalance.balance;
} else if (accountBalance.isLiability) {
totalBalance -= accountBalance.balance;
} else {
totalBalance += accountsBalance[i].balance;
totalBalance += accountBalance.balance;
}
} else {
const balance = exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, userStore.currentUserDefaultCurrency);
const balance = exchangeRatesStore.getExchangedAmount(accountBalance.balance, accountBalance.currency, userStore.currentUserDefaultCurrency);
if (!isNumber(balance)) {
hasUnCalculatedAmount = true;
continue;
}
if (accountsBalance[i].isAsset) {
if (accountBalance.isAsset) {
totalBalance += Math.trunc(balance);
} else if (accountsBalance[i].isLiability) {
} else if (accountBalance.isLiability) {
totalBalance -= Math.trunc(balance);
} else {
totalBalance += Math.trunc(balance);
@@ -678,9 +642,7 @@ export const useAccountsStore = defineStore('accounts', () => {
const allSubAccountCurrencies: string[] = [];
let totalBalance = 0;
for (let i = 0; i < account.subAccounts.length; i++) {
const subAccount = account.subAccounts[i];
for (const subAccount of account.subAccounts) {
if (!showHidden && subAccount.hidden) {
continue;
}
@@ -699,14 +661,12 @@ export const useAccountsStore = defineStore('accounts', () => {
}
if (allSubAccountCurrencies.length === 1) {
resultCurrency = allSubAccountCurrencies[0];
resultCurrency = allSubAccountCurrencies[0] as string;
}
let hasUnCalculatedAmount = false;
for (let i = 0; i < account.subAccounts.length; i++) {
const subAccount = account.subAccounts[i];
for (const subAccount of account.subAccounts) {
if (!showHidden && subAccount.hidden) {
continue;
}
@@ -762,17 +722,15 @@ export const useAccountsStore = defineStore('accounts', () => {
}
function hasAccount(accountCategory: AccountCategory, visibleOnly: boolean): boolean {
if (!allCategorizedAccountsMap.value[accountCategory.type] ||
!allCategorizedAccountsMap.value[accountCategory.type].accounts ||
!allCategorizedAccountsMap.value[accountCategory.type].accounts.length) {
const categorizedAccounts = allCategorizedAccountsMap.value[accountCategory.type];
if (!categorizedAccounts || !categorizedAccounts.accounts || !categorizedAccounts.accounts.length) {
return false;
}
let shownCount = 0;
for (let i = 0; i < allCategorizedAccountsMap.value[accountCategory.type].accounts.length; i++) {
const account = allCategorizedAccountsMap.value[accountCategory.type].accounts[i];
for (const account of categorizedAccounts.accounts) {
if (!visibleOnly || !account.hidden) {
shownCount++;
}
@@ -786,8 +744,8 @@ export const useAccountsStore = defineStore('accounts', () => {
return false;
}
for (let i = 0; i < account.subAccounts.length; i++) {
if (showHidden || !account.subAccounts[i].hidden) {
for (const subAccount of account.subAccounts) {
if (showHidden || !subAccount.hidden) {
return true;
}
}
@@ -934,8 +892,8 @@ export const useAccountsStore = defineStore('accounts', () => {
return new Promise((resolve, reject) => {
if (!account ||
!allCategorizedAccountsMap.value[account.category] ||
!allCategorizedAccountsMap.value[account.category].accounts ||
!allCategorizedAccountsMap.value[account.category].accounts[to]) {
!allCategorizedAccountsMap.value[account.category]!.accounts ||
!allCategorizedAccountsMap.value[account.category]!.accounts[to]) {
reject({ message: 'Unable to move account' });
return;
}
@@ -953,17 +911,11 @@ export const useAccountsStore = defineStore('accounts', () => {
function updateAccountDisplayOrders(): Promise<boolean> {
const newDisplayOrders: AccountNewDisplayOrderRequest[] = [];
for (const category in allCategorizedAccountsMap.value) {
if (!Object.prototype.hasOwnProperty.call(allCategorizedAccountsMap.value, category)) {
continue;
}
const accountList = allCategorizedAccountsMap.value[category].accounts;
for (let i = 0; i < accountList.length; i++) {
for (const categorizedAccounts of values(allCategorizedAccountsMap.value)) {
for (const [account, index] of itemAndIndex(categorizedAccounts.accounts)) {
newDisplayOrders.push({
id: accountList[i].id,
displayOrder: i + 1
id: account.id,
displayOrder: index + 1
});
}
}
+9 -30
View File
@@ -7,6 +7,7 @@ import { useAccountsStore } from './account.ts';
import { useTransactionCategoriesStore } from './transactionCategory.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import { entries, values } from '@/core/base.ts';
import { type TextualYearMonth, type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import { CategoryType } from '@/core/category.ts';
@@ -228,9 +229,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
let totalAmount = 0;
let totalNonNegativeAmount = 0;
for (let i = 0; i < accountsStore.allPlainAccounts.length; i++) {
const account = accountsStore.allPlainAccounts[i];
for (const account of accountsStore.allPlainAccounts) {
if (transactionStatisticsFilter.value.chartDataType === ChartDataType.AccountTotalAssets.type) {
if (!account.isAsset) {
continue;
@@ -312,12 +311,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
const allStatisticsItems: TransactionCategoricalAnalysisDataItem[] = [];
if (combinedData && combinedData.items) {
for (const id in combinedData.items) {
if (!Object.prototype.hasOwnProperty.call(combinedData.items, id)) {
continue;
}
const dataItem = combinedData.items[id];
for (const dataItem of values(combinedData.items)) {
let percent = 0;
if (dataItem.totalAmount > 0) {
@@ -361,8 +355,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
const finalTrendsData: TransactionStatisticTrendsResponseItemWithInfo[] = [];
if (trendsData && trendsData.length) {
for (let i = 0; i < trendsData.length; i++) {
const trendItem = trendsData[i];
for (const trendItem of trendsData) {
const finalTrendItem: TransactionStatisticTrendsResponseItemWithInfo = {
year: trendItem.year,
month: trendItem.month,
@@ -387,16 +380,10 @@ export const useStatisticsStore = defineStore('statistics', () => {
const combinedDataMap: Record<string, WritableTransactionTrendsAnalysisDataItem> = {};
for (let i = 0; i < transactionCategoryTrendsDataWithCategoryAndAccountInfo.value.length; i++) {
const trendItem = transactionCategoryTrendsDataWithCategoryAndAccountInfo.value[i];
for (const trendItem of transactionCategoryTrendsDataWithCategoryAndAccountInfo.value) {
const totalAmountItems = getCategoryTotalAmountItems(trendItem.items, transactionStatisticsFilter.value);
for (const id in totalAmountItems.items) {
if (!Object.prototype.hasOwnProperty.call(totalAmountItems.items, id)) {
continue;
}
const item = totalAmountItems.items[id];
for (const [id, item] of entries(totalAmountItems.items)) {
let combinedData = combinedDataMap[id];
if (!combinedData) {
@@ -426,12 +413,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
const totalAmountsTrends: TransactionTrendsAnalysisDataItem[] = [];
for (const id in combinedDataMap) {
if (!Object.prototype.hasOwnProperty.call(combinedDataMap, id)) {
continue;
}
const trendData = combinedDataMap[id];
for (const trendData of values(combinedDataMap)) {
totalAmountsTrends.push(trendData);
}
@@ -448,8 +430,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
const finalItems: TransactionStatisticResponseItemWithInfo[] = [];
const defaultCurrency = userStore.currentUserDefaultCurrency;
for (let i = 0; i < items.length; i++) {
const dataItem = items[i];
for (const dataItem of items) {
const item: TransactionStatisticResponseItemWithInfo = {
categoryId: dataItem.categoryId,
accountId: dataItem.accountId,
@@ -500,9 +481,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
let totalAmount = 0;
let totalNonNegativeAmount = 0;
for (let i = 0; i < items.length; i++) {
const item = items[i];
for (const item of items) {
if (!item.primaryAccount || !item.account || !item.primaryCategory || !item.category) {
continue;
}
+42 -58
View File
@@ -9,7 +9,7 @@ import { useOverviewStore } from './overview.ts';
import { useStatisticsStore } from './statistics.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import type { BeforeResolveFunction } from '@/core/base.ts';
import { type BeforeResolveFunction, itemAndIndex, entries, keys } from '@/core/base.ts';
import { type TextualYearMonth, DateRange } from '@/core/datetime.ts';
import { CategoryType } from '@/core/category.ts';
import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts';
@@ -165,8 +165,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
let currentMonthListIndex = -1;
let currentMonthList: TransactionMonthList | null = null;
for (let i = 0; i < transactionPageWrapper.items.length; i++) {
const item = transactionPageWrapper.items[i];
for (const [item, index] of itemAndIndex(transactionPageWrapper.items)) {
fillTransactionObject(item, currentUtcOffset);
const transactionTime = parseDateTimeFromUnixTime(item.time, item.utcOffset, currentUtcOffset);
@@ -174,8 +173,8 @@ export const useTransactionsStore = defineStore('transactions', () => {
const transactionMonth = transactionTime.getGregorianCalendarMonth();
const transactionYearDashMonth = transactionTime.getGregorianCalendarYearDashMonth();
if (i === 0 && transactions.value.length > 0) {
const lastMonthList = transactions.value[transactions.value.length - 1];
if (index === 0 && transactions.value.length > 0) {
const lastMonthList = transactions.value[transactions.value.length - 1] as TransactionMonthList;
if (lastMonthList.totalAmount.incompleteExpense || lastMonthList.totalAmount.incompleteIncome) {
// calculate the total amount of last month which has incomplete total amount before starting to process a new request
@@ -186,7 +185,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
if (currentMonthList && currentMonthList.year === transactionYear && currentMonthList.month === transactionMonth) {
currentMonthList.items.push(Object.freeze(item));
if (i === transactionPageWrapper.items.length - 1) {
if (index === transactionPageWrapper.items.length - 1) {
// calculate the total amount of current month when processing the last transaction item of this request
calculateMonthTotalAmount(currentMonthList, defaultCurrency, transactionsFilter.value.accountIds, true);
}
@@ -194,9 +193,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
for (let j = currentMonthListIndex + 1; j < transactions.value.length; j++) {
if (transactions.value[j].year === transactionYear && transactions.value[j].month === transactionMonth) {
if (transactions.value[j]!.year === transactionYear && transactions.value[j]!.month === transactionMonth) {
currentMonthListIndex = j;
currentMonthList = transactions.value[j];
currentMonthList = transactions.value[j] as TransactionMonthList;
break;
}
}
@@ -223,7 +222,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
transactions.value.push(monthList);
currentMonthListIndex = transactions.value.length - 1;
currentMonthList = transactions.value[transactions.value.length - 1];
currentMonthList = transactions.value[transactions.value.length - 1] as TransactionMonthList;
}
currentMonthList.items.push(Object.freeze(item));
@@ -235,50 +234,48 @@ export const useTransactionsStore = defineStore('transactions', () => {
if (nextTimeSequenceId) {
transactionsNextTimeId.value = nextTimeSequenceId;
} else {
calculateMonthTotalAmount(transactions.value[transactions.value.length - 1], defaultCurrency, transactionsFilter.value.accountIds, false);
calculateMonthTotalAmount(transactions.value[transactions.value.length - 1] as TransactionMonthList, defaultCurrency, transactionsFilter.value.accountIds, false);
transactionsNextTimeId.value = -1;
}
}
function updateTransactionInTransactionList({ transaction, defaultCurrency }: { transaction: Transaction, defaultCurrency: string }): void {
function updateTransactionInTransactionList({ currentTransaction, defaultCurrency }: { currentTransaction: Transaction, defaultCurrency: string }): void {
const currentUtcOffset = getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone);
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentUtcOffset);
const transactionTime = parseDateTimeFromUnixTime(currentTransaction.time, currentTransaction.utcOffset, currentUtcOffset);
const transactionYear = transactionTime.getGregorianCalendarYear();
const transactionMonth = transactionTime.getGregorianCalendarMonth();
for (let i = 0; i < transactions.value.length; i++) {
const transactionMonthList = transactions.value[i];
for (const [transactionMonthList, monthIndex] of itemAndIndex(transactions.value)) {
if (!transactionMonthList.items) {
continue;
}
for (let j = 0; j < transactionMonthList.items.length; j++) {
if (transactionMonthList.items[j].id === transaction.id) {
fillTransactionObject(transaction, currentUtcOffset);
for (const [transaction, transactionIndex] of itemAndIndex(transactionMonthList.items)) {
if (transaction.id === currentTransaction.id) {
fillTransactionObject(currentTransaction, currentUtcOffset);
if (transactionYear !== transactionMonthList.year ||
transactionMonth !== transactionMonthList.month ||
transaction.gregorianCalendarDayOfMonth !== transactionMonthList.items[j].gregorianCalendarDayOfMonth) {
currentTransaction.gregorianCalendarDayOfMonth !== transaction.gregorianCalendarDayOfMonth) {
transactionListStateInvalid.value = true;
return;
}
if ((transactionsFilter.value.categoryIds && !allFilterCategoryIds.value[transaction.categoryId]) ||
(transactionsFilter.value.accountIds && !allFilterAccountIds.value[transaction.sourceAccountId] && !allFilterAccountIds.value[transaction.destinationAccountId] &&
(!transaction.sourceAccount || !allFilterAccountIds.value[transaction.sourceAccount.parentId]) &&
(!transaction.destinationAccount || !allFilterAccountIds.value[transaction.destinationAccount.parentId])
if ((transactionsFilter.value.categoryIds && !allFilterCategoryIds.value[currentTransaction.categoryId]) ||
(transactionsFilter.value.accountIds && !allFilterAccountIds.value[currentTransaction.sourceAccountId] && !allFilterAccountIds.value[currentTransaction.destinationAccountId] &&
(!currentTransaction.sourceAccount || !allFilterAccountIds.value[currentTransaction.sourceAccount.parentId]) &&
(!currentTransaction.destinationAccount || !allFilterAccountIds.value[currentTransaction.destinationAccount.parentId])
)
) {
transactionMonthList.items.splice(j, 1);
transactionMonthList.items.splice(transactionIndex, 1);
} else {
transactionMonthList.items.splice(j, 1, transaction);
transactionMonthList.items.splice(transactionIndex, 1, currentTransaction);
}
if (transactionMonthList.items.length < 1) {
transactions.value.splice(i, 1);
transactions.value.splice(monthIndex, 1);
} else {
calculateMonthTotalAmount(transactionMonthList, defaultCurrency, transactionsFilter.value.accountIds, i >= transactions.value.length - 1 && transactionsNextTimeId.value > 0);
calculateMonthTotalAmount(transactionMonthList, defaultCurrency, transactionsFilter.value.accountIds, monthIndex >= transactions.value.length - 1 && transactionsNextTimeId.value > 0);
}
return;
@@ -287,26 +284,24 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
}
function removeTransactionFromTransactionList({ transaction, defaultCurrency }: { transaction: TransactionInfoResponse, defaultCurrency: string }): void {
for (let i = 0; i <transactions.value.length; i++) {
const transactionMonthList = transactions.value[i];
function removeTransactionFromTransactionList({ currentTransaction, defaultCurrency }: { currentTransaction: TransactionInfoResponse, defaultCurrency: string }): void {
for (const [transactionMonthList, monthIndex] of itemAndIndex(transactions.value)) {
if (!transactionMonthList.items ||
transactionMonthList.items[0].time < transaction.time ||
transactionMonthList.items[transactionMonthList.items.length - 1].time > transaction.time) {
transactionMonthList.items[0]!.time < currentTransaction.time ||
transactionMonthList.items[transactionMonthList.items.length - 1]!.time > currentTransaction.time) {
continue;
}
for (let j = 0; j < transactionMonthList.items.length; j++) {
if (transactionMonthList.items[j].id === transaction.id) {
transactionMonthList.items.splice(j, 1);
for (const [transaction, transactionIndex] of itemAndIndex(transactionMonthList.items)) {
if (transaction.id === currentTransaction.id) {
transactionMonthList.items.splice(transactionIndex, 1);
}
}
if (transactionMonthList.items.length < 1) {
transactions.value.splice(i, 1);
transactions.value.splice(monthIndex, 1);
} else {
calculateMonthTotalAmount(transactionMonthList, defaultCurrency, transactionsFilter.value.accountIds, i >= transactions.value.length - 1 && transactionsNextTimeId.value > 0);
calculateMonthTotalAmount(transactionMonthList, defaultCurrency, transactionsFilter.value.accountIds, monthIndex >= transactions.value.length - 1 && transactionsNextTimeId.value > 0);
}
}
}
@@ -328,16 +323,15 @@ export const useTransactionsStore = defineStore('transactions', () => {
if (accountIds && accountIds !== '0') {
const allAccountIdsArray = accountIds.split(',');
for (let i = 0; i < allAccountIdsArray.length; i++) {
if (allAccountIdsArray[i]) {
allAccountIdsMap[allAccountIdsArray[i]] = true;
for (const accountId of allAccountIdsArray) {
if (accountId) {
allAccountIdsMap[accountId] = true;
totalAccountIdsCount++;
}
}
}
for (let i = 0; i < transactionMonthList.items.length; i++) {
const transaction = transactionMonthList.items[i];
for (const transaction of transactionMonthList.items) {
const transactionDay = isNumber(transaction.gregorianCalendarDayOfMonth) ? transaction.gregorianCalendarDayOfMonth.toString() : '0';
let dailyTotalAmount = dailyTotalAmounts[transactionDay];
@@ -413,21 +407,11 @@ export const useTransactionsStore = defineStore('transactions', () => {
transactionMonthList.totalAmount.income = Math.trunc(totalIncome);
transactionMonthList.totalAmount.incompleteIncome = incomplete || hasUnCalculatedTotalIncome;
for (const day in transactionMonthList.dailyTotalAmounts) {
if (!Object.prototype.hasOwnProperty.call(transactionMonthList.dailyTotalAmounts, day)) {
continue;
}
for (const day of keys(transactionMonthList.dailyTotalAmounts)) {
delete transactionMonthList.dailyTotalAmounts[day];
}
for (const day in dailyTotalAmounts) {
if (!Object.prototype.hasOwnProperty.call(dailyTotalAmounts, day)) {
continue;
}
const dailyTotalAmount = dailyTotalAmounts[day];
for (const [day, dailyTotalAmount] of entries(dailyTotalAmounts)) {
transactionMonthList.dailyTotalAmounts[day] = {
expense: Math.trunc(dailyTotalAmount.expense),
incompleteExpense: incomplete || dailyTotalAmount.incompleteExpense,
@@ -1076,7 +1060,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
} else {
updateTransactionInTransactionList({
transaction: transaction,
currentTransaction: transaction,
defaultCurrency: defaultCurrency
});
}
@@ -1131,13 +1115,13 @@ export const useTransactionsStore = defineStore('transactions', () => {
if (beforeResolve) {
beforeResolve(() => {
removeTransactionFromTransactionList({
transaction: transaction,
currentTransaction: transaction,
defaultCurrency: defaultCurrency
});
});
} else {
removeTransactionFromTransactionList({
transaction: transaction,
currentTransaction: transaction,
defaultCurrency: defaultCurrency
});
}
+38 -46
View File
@@ -3,6 +3,7 @@ import { defineStore } from 'pinia';
import type { BeforeResolveFunction } from '@/core/base.ts';
import { itemAndIndex, values } from '@/core/base.ts';
import { CategoryType } from '@/core/category.ts';
import {
@@ -53,23 +54,15 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
allTransactionCategories.value = allCategories;
allTransactionCategoriesMap.value = {};
for (const categoryType in allCategories) {
if (!Object.prototype.hasOwnProperty.call(allCategories, categoryType)) {
continue;
}
const categories = allCategories[categoryType];
for (let i = 0; i < categories.length; i++) {
const category = categories[i];
for (const categories of values(allCategories)) {
for (const category of categories) {
allTransactionCategoriesMap.value[category.id] = category;
if (!category.subCategories) {
continue;
}
for (let j = 0; j < category.subCategories.length; j++) {
const subCategory = category.subCategories[j];
for (const subCategory of category.subCategories) {
allTransactionCategoriesMap.value[subCategory.id] = subCategory;
}
}
@@ -82,7 +75,7 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
if (!category.parentId || category.parentId === '0') {
categoryList = allTransactionCategories.value[category.type];
} else if (allTransactionCategoriesMap.value[category.parentId]) {
categoryList = allTransactionCategoriesMap.value[category.parentId].subCategories;
categoryList = allTransactionCategoriesMap.value[category.parentId]!.subCategories;
}
if (categoryList) {
@@ -92,33 +85,33 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
allTransactionCategoriesMap.value[category.id] = category;
}
function updateCategoryInTransactionCategoryList(category: TransactionCategory, oldCategory: TransactionCategory): boolean {
if (oldCategory && category.parentId !== oldCategory.parentId) {
function updateCategoryInTransactionCategoryList(currentCategory: TransactionCategory, oldCategory?: TransactionCategory): boolean {
if (oldCategory && currentCategory.parentId !== oldCategory.parentId) {
return false;
}
let categoryList: TransactionCategory[] | undefined = undefined;
if (!category.parentId || category.parentId === '0') {
categoryList = allTransactionCategories.value[category.type];
} else if (allTransactionCategoriesMap.value[category.parentId]) {
categoryList = allTransactionCategoriesMap.value[category.parentId].subCategories;
if (!currentCategory.parentId || currentCategory.parentId === '0') {
categoryList = allTransactionCategories.value[currentCategory.type];
} else if (allTransactionCategoriesMap.value[currentCategory.parentId]) {
categoryList = allTransactionCategoriesMap.value[currentCategory.parentId]!.subCategories;
}
if (categoryList) {
for (let i = 0; i < categoryList.length; i++) {
if (categoryList[i].id === category.id) {
if (!category.parentId || category.parentId === '0') {
category.subCategories = categoryList[i].subCategories;
for (const [category, index] of itemAndIndex(categoryList)) {
if (category.id === currentCategory.id) {
if (!currentCategory.parentId || currentCategory.parentId === '0') {
currentCategory.subCategories = category.subCategories;
}
categoryList.splice(i, 1, category);
categoryList.splice(index, 1, currentCategory);
break;
}
}
}
allTransactionCategoriesMap.value[category.id] = category;
allTransactionCategoriesMap.value[currentCategory.id] = currentCategory;
return true;
}
@@ -128,44 +121,43 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
if (!category.parentId || category.parentId === '0') {
categoryList = allTransactionCategories.value[category.type];
} else if (allTransactionCategoriesMap.value[category.parentId]) {
categoryList = allTransactionCategoriesMap.value[category.parentId].subCategories;
categoryList = allTransactionCategoriesMap.value[category.parentId]!.subCategories;
}
if (categoryList) {
categoryList.splice(to, 0, categoryList.splice(from, 1)[0]);
categoryList.splice(to, 0, categoryList.splice(from, 1)[0] as TransactionCategory);
}
}
function updateCategoryVisibilityInTransactionCategoryList({ category, hidden }: { category: TransactionCategory, hidden: boolean }): void {
if (allTransactionCategoriesMap.value[category.id]) {
allTransactionCategoriesMap.value[category.id].visible = !hidden;
allTransactionCategoriesMap.value[category.id]!.visible = !hidden;
}
}
function removeCategoryFromTransactionCategoryList(category: TransactionCategory): void {
function removeCategoryFromTransactionCategoryList(currentCategory: TransactionCategory): void {
let categoryList: TransactionCategory[] | undefined = undefined;
if (!category.parentId || category.parentId === '0') {
categoryList = allTransactionCategories.value[category.type];
} else if (allTransactionCategoriesMap.value[category.parentId]) {
categoryList = allTransactionCategoriesMap.value[category.parentId].subCategories;
if (!currentCategory.parentId || currentCategory.parentId === '0') {
categoryList = allTransactionCategories.value[currentCategory.type];
} else if (allTransactionCategoriesMap.value[currentCategory.parentId]) {
categoryList = allTransactionCategoriesMap.value[currentCategory.parentId]!.subCategories;
}
if (categoryList) {
for (let i = 0; i < categoryList.length; i++) {
if (categoryList[i].id === category.id) {
categoryList.splice(i, 1);
for (const [category, index] of itemAndIndex(categoryList)) {
if (category.id === currentCategory.id) {
categoryList.splice(index, 1);
break;
}
}
}
if (allTransactionCategoriesMap.value[category.id] && allTransactionCategoriesMap.value[category.id].subCategories) {
const subCategoryList = allTransactionCategoriesMap.value[category.id].subCategories;
if (allTransactionCategoriesMap.value[currentCategory.id] && allTransactionCategoriesMap.value[currentCategory.id]!.subCategories) {
const subCategoryList = allTransactionCategoriesMap.value[currentCategory.id]!.subCategories;
if (subCategoryList) {
for (let i = 0; i < subCategoryList.length; i++) {
const subCategory = subCategoryList[i];
for (const subCategory of subCategoryList) {
if (allTransactionCategoriesMap.value[subCategory.id]) {
delete allTransactionCategoriesMap.value[subCategory.id];
}
@@ -173,8 +165,8 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
}
}
if (allTransactionCategoriesMap.value[category.id]) {
delete allTransactionCategoriesMap.value[category.id];
if (allTransactionCategoriesMap.value[currentCategory.id]) {
delete allTransactionCategoriesMap.value[currentCategory.id];
}
}
@@ -403,12 +395,12 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
if (!category.parentId || category.parentId === '0') {
if (!allTransactionCategories.value[category.type] ||
!allTransactionCategories.value[category.type][to]) {
!allTransactionCategories.value[category.type]![to]) {
reject({ message: 'Unable to move category' });
return;
}
} else {
const subCategoryList = allTransactionCategoriesMap.value[category.parentId].subCategories;
const subCategoryList = allTransactionCategoriesMap.value[category.parentId]?.subCategories;
if (!subCategoryList || !subCategoryList[to]) {
reject({ message: 'Unable to move category' });
@@ -438,10 +430,10 @@ export const useTransactionCategoriesStore = defineStore('transactionCategories'
}
if (categoryList) {
for (let i = 0; i < categoryList.length; i++) {
for (const [category, index] of itemAndIndex(categoryList)) {
newDisplayOrders.push({
id: categoryList[i].id,
displayOrder: i + 1
id: category.id,
displayOrder: index + 1
});
}
}
+28 -44
View File
@@ -1,7 +1,7 @@
import { ref, computed } from 'vue';
import { defineStore } from 'pinia';
import type { BeforeResolveFunction } from '@/core/base.ts';
import { type BeforeResolveFunction, itemAndIndex, entries } from '@/core/base.ts';
import { TransactionType } from '@/core/transaction.ts';
@@ -24,23 +24,16 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
const allVisibleTemplates = computed<Record<number, TransactionTemplate[]>>(() => {
const allVisibleTemplates: Record<number, TransactionTemplate[]> = {};
for (const templateType in allTransactionTemplates.value) {
if (!Object.prototype.hasOwnProperty.call(allTransactionTemplates.value, templateType)) {
continue;
}
const allTemplates = allTransactionTemplates.value[templateType];
for (const [templateType, allTemplates] of entries(allTransactionTemplates.value)) {
const visibleTemplates: TransactionTemplate[] = [];
for (let i = 0; i < allTemplates.length; i++) {
const template = allTemplates[i];
for (const template of allTemplates) {
if (!template.hidden) {
visibleTemplates.push(template);
}
}
allVisibleTemplates[templateType] = visibleTemplates;
allVisibleTemplates[parseInt(templateType)] = visibleTemplates;
}
return allVisibleTemplates;
@@ -49,12 +42,8 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
const allAvailableTemplatesCount = computed<Record<number, number>>(() => {
const allAvailableTemplateCounts: Record<number, number> = {};
for (const templateType in allTransactionTemplates.value) {
if (!Object.prototype.hasOwnProperty.call(allTransactionTemplates.value, templateType)) {
continue;
}
allAvailableTemplateCounts[templateType] = allTransactionTemplates.value[templateType].length;
for (const [templateType, allTemplates] of entries(allTransactionTemplates.value)) {
allAvailableTemplateCounts[parseInt(templateType)] = allTemplates.length;
}
return allAvailableTemplateCounts;
@@ -63,12 +52,8 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
const allVisibleTemplatesCount = computed<Record<number, number>>(() => {
const allVisibleTemplateCounts: Record<number, number> = {};
for (const templateType in allVisibleTemplates.value) {
if (!Object.prototype.hasOwnProperty.call(allVisibleTemplates.value, templateType)) {
continue;
}
allVisibleTemplateCounts[templateType] = allVisibleTemplates.value[templateType].length;
for (const [templateType, allTemplates] of entries(allVisibleTemplates.value)) {
allVisibleTemplateCounts[parseInt(templateType)] = allTemplates.length;
}
return allVisibleTemplateCounts;
@@ -78,8 +63,7 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
allTransactionTemplates.value[templateType] = templates;
allTransactionTemplatesMap.value[templateType] = {};
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
for (const template of templates) {
allTransactionTemplatesMap.value[templateType][template.id] = template;
}
}
@@ -102,9 +86,9 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
const templateMap = allTransactionTemplatesMap.value[templateType];
if (isArray(templates)) {
for (let i = 0; i < templates.length; i++) {
if (templates[i].id === template.id) {
templates.splice(i, 1, template);
for (const [template, index] of itemAndIndex(templates)) {
if (template.id === template.id) {
templates.splice(index, 1, template);
break;
}
}
@@ -119,7 +103,7 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
const templates = allTransactionTemplates.value[templateType];
if (isArray(templates)) {
templates.splice(to, 0, templates.splice(from, 1)[0]);
templates.splice(to, 0, templates.splice(from, 1)[0] as TransactionTemplate);
}
}
@@ -128,27 +112,27 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
if (isObject(templateMap)) {
if (templateMap[template.id]) {
templateMap[template.id].hidden = hidden;
templateMap[template.id]!.hidden = hidden;
}
}
}
function removeTemplateFromTransactionTemplateList(templateType: number, template: TransactionTemplate): void {
function removeTemplateFromTransactionTemplateList(templateType: number, currentTemplate: TransactionTemplate): void {
const templates = allTransactionTemplates.value[templateType];
const templateMap = allTransactionTemplatesMap.value[templateType];
if (isArray(templates)) {
for (let i = 0; i < templates.length; i++) {
if (templates[i].id === template.id) {
templates.splice(i, 1);
for (const [template, index] of itemAndIndex(templates)) {
if (template.id === currentTemplate.id) {
templates.splice(index, 1);
break;
}
}
}
if (isObject(templateMap)) {
if (templateMap[template.id]) {
delete templateMap[template.id];
if (templateMap[currentTemplate.id]) {
delete templateMap[currentTemplate.id];
}
}
}
@@ -298,21 +282,21 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
function changeTemplateDisplayOrder({ templateType, templateId, from, to }: { templateType: number, templateId: string, from: number, to: number }): Promise<void> {
return new Promise((resolve, reject) => {
let template: TransactionTemplate | null = null;
let currentTemplate: TransactionTemplate | null = null;
if (!isArray(allTransactionTemplates.value[templateType])) {
reject({ message: 'Unable to move template' });
return;
}
for (let i = 0; i < allTransactionTemplates.value[templateType].length; i++) {
if (allTransactionTemplates.value[templateType][i].id === templateId) {
template = allTransactionTemplates.value[templateType][i];
for (const template of allTransactionTemplates.value[templateType]) {
if (template.id === templateId) {
currentTemplate = template;
break;
}
}
if (!template || !allTransactionTemplates.value[templateType][to]) {
if (!currentTemplate || !allTransactionTemplates.value[templateType][to]) {
reject({ message: 'Unable to move template' });
return;
}
@@ -331,10 +315,10 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates',
const newDisplayOrders: TransactionTemplateNewDisplayOrderRequest[] = [];
if (isArray(allTransactionTemplates.value[templateType])) {
for (let i = 0; i < allTransactionTemplates.value[templateType].length; i++) {
for (const [template, index] of itemAndIndex(allTransactionTemplates.value[templateType])) {
newDisplayOrders.push({
id: allTransactionTemplates.value[templateType][i].id,
displayOrder: i + 1
id: template.id,
displayOrder: index + 1
});
}
}
@@ -175,8 +175,7 @@ export function useAppCloudSyncBase() {
if (settings && settings.length > 0) {
settingsStore.setApplicationSettingsFromCloudSettings(settings);
for (let i = 0; i < settings.length; i++) {
const setting = settings[i];
for (const setting of settings) {
if (setting && setting.settingKey) {
enabledApplicationCloudSettings.value[setting.settingKey] = true;
}
+12 -10
View File
@@ -150,8 +150,8 @@
handle=".drag-handle"
ghost-class="dragging-item"
:disabled="activeAccountCategoryVisibleAccountCount <= 1"
:list="allCategorizedAccountsMap[activeAccountCategory.type].accounts"
v-if="activeAccountCategory && allCategorizedAccountsMap[activeAccountCategory.type] && allCategorizedAccountsMap[activeAccountCategory.type].accounts && allCategorizedAccountsMap[activeAccountCategory.type].accounts.length"
:list="allCategorizedAccountsMap[activeAccountCategory.type]!.accounts"
v-if="activeAccountCategory && allCategorizedAccountsMap[activeAccountCategory.type] && allCategorizedAccountsMap[activeAccountCategory.type]!.accounts && allCategorizedAccountsMap[activeAccountCategory.type]!.accounts.length"
@change="onMove"
>
<template #item="{ element }">
@@ -376,20 +376,24 @@ const activeAccountCategory = computed<AccountCategory | undefined>(() => Accoun
const activeAccountCategoryTotalBalance = computed<string>(() => accountCategoryTotalBalance(activeAccountCategory.value));
const activeAccountCategoryVisibleAccountCount = computed<number>(() => {
if (!activeAccountCategory.value || !allCategorizedAccountsMap.value[activeAccountCategory.value.type] || !allCategorizedAccountsMap.value[activeAccountCategory.value.type].accounts) {
if (!activeAccountCategory.value) {
return 0;
}
const accounts = allCategorizedAccountsMap.value[activeAccountCategory.value.type].accounts;
const categorizedAccounts = allCategorizedAccountsMap.value[activeAccountCategory.value.type];
if (!categorizedAccounts || !categorizedAccounts.accounts || !categorizedAccounts.accounts.length) {
return 0;
}
if (showHidden.value) {
return accounts.length;
return categorizedAccounts.accounts.length;
}
let visibleCount = 0;
for (let i = 0; i < accounts.length; i++) {
if (!accounts[i].hidden) {
for (const account of categorizedAccounts.accounts) {
if (!account.hidden) {
visibleCount++;
}
}
@@ -407,9 +411,7 @@ function reload(force: boolean): void {
displayOrderModified.value = false;
if (allAccounts.value) {
for (let i = 0; i < allAccounts.value.length; i++) {
const account = allAccounts.value[i];
for (const account of allAccounts.value) {
if (account.type === AccountType.MultiSubAccounts.type && !activeSubAccount.value[account.id]) {
activeSubAccount.value[account.id] = '';
}
@@ -202,6 +202,7 @@ import { useAccountEditPageBaseBase } from '@/views/base/accounts/AccountEditPag
import { useUserStore } from '@/stores/user.ts';
import { useAccountsStore } from '@/stores/account.ts';
import { itemAndIndex } from '@/core/base.ts';
import { AccountType } from '@/core/account.ts';
import { ALL_ACCOUNT_ICONS } from '@/consts/icon.ts';
import { ALL_ACCOUNT_COLORS } from '@/consts/color.ts';
@@ -365,11 +366,11 @@ function save(): void {
});
}
function removeSubAccount(subAccount: Account): void {
function removeSubAccount(currentSubAccount: Account): void {
confirmDialog.value?.open('Are you sure you want to remove this sub-account?').then(() => {
for (let i = 0; i < subAccounts.value.length; i++) {
if (subAccounts.value[i] === subAccount) {
subAccounts.value.splice(i, 1);
for (const [subAccount, index] of itemAndIndex(subAccounts.value)) {
if (subAccount === currentSubAccount) {
subAccounts.value.splice(index, 1);
if (currentAccountIndex.value >= subAccounts.value.length) {
currentAccountIndex.value = subAccounts.value.length - 1;
@@ -162,15 +162,15 @@
<template #item.categoryId="{ item }">
<div class="d-flex align-center">
<ItemIcon size="24px" icon-type="category"
:icon-id="allCategoriesMap[item.categoryId].icon"
:color="allCategoriesMap[item.categoryId].color"
:icon-id="allCategoriesMap[item.categoryId]?.icon ?? ''"
:color="allCategoriesMap[item.categoryId]?.color ?? ''"
v-if="allCategoriesMap[item.categoryId] && allCategoriesMap[item.categoryId]?.color"></ItemIcon>
<v-icon size="24" :icon="mdiPencilBoxOutline" v-else-if="!allCategoriesMap[item.categoryId] || !allCategoriesMap[item.categoryId]?.color" />
<span class="ms-2" v-if="item.type === TransactionType.ModifyBalance">
{{ tt('Modify Balance') }}
</span>
<span class="ms-2" v-else-if="item.type !== TransactionType.ModifyBalance && allCategoriesMap[item.categoryId]">
{{ allCategoriesMap[item.categoryId].name }}
{{ allCategoriesMap[item.categoryId]?.name }}
</span>
</div>
</template>
@@ -181,9 +181,9 @@
</template>
<template #item.sourceAccountId="{ item }">
<div class="d-flex align-center">
<span v-if="item.sourceAccountId && allAccountsMap[item.sourceAccountId]">{{ allAccountsMap[item.sourceAccountId].name }}</span>
<span v-if="item.sourceAccountId && allAccountsMap[item.sourceAccountId]">{{ allAccountsMap[item.sourceAccountId]?.name }}</span>
<v-icon class="icon-with-direction mx-1" size="13" :icon="mdiArrowRight" v-if="item.type === TransactionType.Transfer"></v-icon>
<span v-if="item.type === TransactionType.Transfer && item.destinationAccountId && allAccountsMap[item.destinationAccountId]">{{ allAccountsMap[item.destinationAccountId].name }}</span>
<span v-if="item.type === TransactionType.Transfer && item.destinationAccountId && allAccountsMap[item.destinationAccountId]">{{ allAccountsMap[item.destinationAccountId]?.name }}</span>
</div>
</template>
<template #item.accountBalance="{ item }">
@@ -388,12 +388,7 @@ const totalPageCount = computed<number>(() => {
return 1;
}
let count = 0;
for (let i = 0; i < reconciliationStatements.value.transactions.length; i++) {
count++;
}
const count = reconciliationStatements.value.transactions.length;
return Math.ceil(count / countPerPage.value);
});
@@ -422,9 +417,7 @@ function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
const availableCountPerPage = [ 5, 10, 15, 20, 25, 30, 50 ];
for (let i = 0; i < availableCountPerPage.length; i++) {
const count = availableCountPerPage[i];
for (const count of availableCountPerPage) {
if (linesCount < count) {
break;
}
+2 -2
View File
@@ -259,7 +259,7 @@ const primaryCategories = computed<TransactionCategory[]>(() => {
return [];
}
return transactionCategoriesStore.allTransactionCategories[activeCategoryType.value];
return transactionCategoriesStore.allTransactionCategories[activeCategoryType.value] ?? [];
});
const secondaryCategories = computed<TransactionCategory[]>(() => {
@@ -267,7 +267,7 @@ const secondaryCategories = computed<TransactionCategory[]>(() => {
return [];
}
return transactionCategoriesStore.allTransactionCategoriesMap[primaryCategoryId.value].subCategories || [];
return transactionCategoriesStore.allTransactionCategoriesMap[primaryCategoryId.value]?.subCategories ?? [];
});
const hasSubCategories = computed<boolean>(() => {
@@ -78,9 +78,7 @@ const hasAnyData = computed<boolean>(() => {
return false;
}
for (let i = 0; i < props.data.length; i++) {
const item = props.data[i];
for (const item of props.data) {
if (item.incomeAmount > 0 || item.incomeAmount < 0 || item.expenseAmount > 0 || item.expenseAmount < 0) {
return true;
}
@@ -99,8 +97,7 @@ const chartOptions = computed<object>(() => {
const expenseIncomeAmountColor = getExpenseAndIncomeAmountColor(userStore.currentUserExpenseAmountColor, userStore.currentUserIncomeAmountColor, props.isDarkMode);
if (props.data) {
for (let i = 0; i < props.data.length; i++) {
const item = props.data[i];
for (const item of props.data) {
const monthShortName = formatUnixTimeToGregorianLikeShortMonth(item.monthStartTime);
monthNames.push(monthShortName);
@@ -145,10 +142,9 @@ const chartOptions = computed<object>(() => {
let incomeAmount: string | null = null;
let expenseAmount: string | null = null;
for (let i = 0; i < params.length; i++) {
const param = params[i];
for (const param of params) {
const dataIndex = param.dataIndex;
const data = props.data[dataIndex];
const data = props.data[dataIndex] as TransactionMonthlyIncomeAndExpenseData;
if (param.seriesId === 'seriesIncome') {
incomeAmount = getDisplayIncomeAmount(data);
@@ -160,7 +156,7 @@ const chartOptions = computed<object>(() => {
return `<table>` +
`<thead>` +
`<tr>` +
`<td colspan="2" class="text-start">${params[0].name}</td>` +
`<td colspan="2" class="text-start">${params[0]?.name}</td>` +
`</tr>` +
`</thead>` +
`<tbody>` +
+25 -28
View File
@@ -261,7 +261,7 @@
</v-list-item>
<v-list-group :key="category.id" v-for="category in categories">
<template #activator="{ props }" v-if="!category.hidden || query.categoryIds === category.id || (allCategories[query.categoryIds] && allCategories[query.categoryIds].parentId === category.id)">
<template #activator="{ props }" v-if="!category.hidden || query.categoryIds === category.id || (allCategories[query.categoryIds] && allCategories[query.categoryIds]!.parentId === category.id)">
<v-divider />
<v-list-item class="text-sm" density="compact"
:class="getCategoryListItemCheckedClass(category, queryAllFilterCategoryIds)"
@@ -402,12 +402,12 @@
</v-list-item>
<template :key="account.id"
v-for="account in allAccounts">
<v-divider v-if="(!account.hidden && (!allAccountsMap[account.parentId] || !allAccountsMap[account.parentId].hidden)) || query.accountIds === account.id" />
<v-divider v-if="(!account.hidden && (!allAccountsMap[account.parentId] || !allAccountsMap[account.parentId]!.hidden)) || query.accountIds === account.id" />
<v-list-item class="text-sm" density="compact"
:value="account.id"
:class="{ 'list-item-selected': query.accountIds === account.id, 'item-in-multiple-selection': queryAllFilterAccountIdsCount > 1 && queryAllFilterAccountIds[account.id] }"
:append-icon="(query.accountIds === account.id ? mdiCheck : undefined)"
v-if="(!account.hidden && (!allAccountsMap[account.parentId] || !allAccountsMap[account.parentId].hidden)) || query.accountIds === account.id">
v-if="(!account.hidden && (!allAccountsMap[account.parentId] || !allAccountsMap[account.parentId]!.hidden)) || query.accountIds === account.id">
<v-list-item-title class="cursor-pointer"
@click="changeAccountFilter(account.id)">
<div class="d-flex align-center">
@@ -527,7 +527,7 @@
:class="{ 'disabled': loading, 'has-bottom-border': idx < transactions.length - 1 }"
v-for="(transaction, idx) in transactions">
<tr class="transaction-list-row-date no-hover text-sm"
v-if="pageType === TransactionListPageType.List.type && (idx === 0 || (idx > 0 && (transaction.gregorianCalendarYearDashMonthDashDay !== transactions[idx - 1].gregorianCalendarYearDashMonthDashDay)))">
v-if="pageType === TransactionListPageType.List.type && (idx === 0 || (idx > 0 && (transaction.gregorianCalendarYearDashMonthDashDay !== transactions[idx - 1]!.gregorianCalendarYearDashMonthDashDay)))">
<td :colspan="showTagInTransactionListPage ? 6 : 5" class="font-weight-bold">
<div class="d-flex align-center">
<span>{{ getDisplayLongDate(transaction) }}</span>
@@ -579,7 +579,7 @@
</td>
<td class="transaction-table-column-tags" v-if="showTagInTransactionListPage">
<v-chip class="transaction-tag" size="small" :prepend-icon="mdiPound"
:text="allTransactionTags[tagId].name"
:text="allTransactionTags[tagId]?.name"
:key="tagId"
v-for="tagId in transaction.tagIds"/>
<v-chip class="transaction-tag" size="small"
@@ -669,7 +669,11 @@ import { useTransactionsStore } from '@/stores/transaction.ts';
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.ts';
import { useDesktopPageStore } from '@/stores/desktopPage.ts';
import type { NameNumeralValue, TypeAndDisplayName } from '@/core/base.ts';
import {
type NameNumeralValue,
type TypeAndDisplayName,
keys
} from '@/core/base.ts';
import {
type Year0BasedMonth,
type LocalizedRecentMonthDateRange,
@@ -884,8 +888,7 @@ const allPageCounts = computed<NameNumeralValue[]>(() => {
const pageCounts: NameNumeralValue[] = [];
const availableCountPerPage: number[] = [ 5, 10, 15, 20, 25, 30, 50 ];
for (let i = 0; i < availableCountPerPage.length; i++) {
const count = availableCountPerPage[i];
for (const count of availableCountPerPage) {
pageCounts.push({ value: count, name: numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(count.toString()) });
}
@@ -903,11 +906,11 @@ const allTransactionTagFilterTypes = computed<TransactionTemplateWithIcon[]>(()
const allTagFilterTypes: TypeAndDisplayName[] = getAllTransactionTagFilterTypes();
const allTagFilterTypesWithIcon: TransactionTemplateWithIcon[] = [];
for (let i = 0; i < allTagFilterTypes.length; i++) {
for (const tagFilterType of allTagFilterTypes) {
allTagFilterTypesWithIcon.push({
type: allTagFilterTypes[i].type,
displayName: allTagFilterTypes[i].displayName,
icon: tagFilterIconMap[allTagFilterTypes[i].type]
type: tagFilterType.type,
displayName: tagFilterType.displayName,
icon: tagFilterIconMap[tagFilterType.type] ?? ''
});
}
@@ -948,9 +951,7 @@ const transactions = computed<Transaction[]>(() => {
const transactions :Transaction[] = [];
for (let i = 0; i < transactionData.items.length; i++) {
const transaction = transactionData.items[i];
for (const transaction of transactionData.items) {
if (transaction.gregorianCalendarYearDashMonthDashDay === currentCalendarDate.value) {
transactions.push(transaction);
}
@@ -972,7 +973,7 @@ const recentDateRangeIndex = computed<number>({
value = 0;
}
changeDateFilter(recentMonthDateRanges.value[value]);
changeDateFilter(recentMonthDateRanges.value[value] as LocalizedRecentMonthDateRange);
}
});
@@ -1089,8 +1090,8 @@ function getCategoryListItemCheckedClass(category: TransactionCategory, queryCat
}
if (category.subCategories) {
for (let i = 0; i < category.subCategories.length; i++) {
if (queryCategoryIds && queryCategoryIds[category.subCategories[i].id]) {
for (const subCategory of category.subCategories) {
if (queryCategoryIds && queryCategoryIds[subCategory.id]) {
return {
'list-item-selected': true,
'has-children-item-selected': true
@@ -1382,7 +1383,7 @@ function changeCustomMonthDateFilter(yearMonth: Year0BasedMonth): void {
}
function shiftDateRange(startTime: number, endTime: number, scale: number): void {
if (recentMonthDateRanges.value[recentDateRangeIndex.value].dateType === DateRange.All.type) {
if (recentMonthDateRanges.value[recentDateRangeIndex.value]?.dateType === DateRange.All.type) {
return;
}
@@ -1421,11 +1422,7 @@ function changeTypeFilter(type: number): void {
if (type && query.value.categoryIds) {
newCategoryFilter = '';
for (const categoryId in queryAllFilterCategoryIds.value) {
if (!Object.prototype.hasOwnProperty.call(queryAllFilterCategoryIds.value, categoryId)) {
continue;
}
for (const categoryId of keys(queryAllFilterCategoryIds.value)) {
const category = allCategories.value[categoryId];
if (category && category.type === transactionTypeToCategoryType(type)) {
@@ -1680,13 +1677,13 @@ function scrollAmountMenuToSelectedItem(opened: boolean): void {
if (isString(query.value.amountFilter)) {
try {
const filterItems = query.value.amountFilter.split(':');
const amountCount = getAmountFilterParameterCount(filterItems[0]);
const amountCount = getAmountFilterParameterCount(filterItems[0] as string);
if (filterItems.length === 2 && amountCount === 1) {
amount1 = parseInt(filterItems[1]);
amount1 = parseInt(filterItems[1] as string);
} else if (filterItems.length === 3 && amountCount === 2) {
amount1 = parseInt(filterItems[1]);
amount2 = parseInt(filterItems[2]);
amount1 = parseInt(filterItems[1] as string);
amount2 = parseInt(filterItems[2] as string);
}
} catch (ex) {
logger.warn('cannot parse amount from filter value, original value is ' + query.value.amountFilter, ex);
@@ -93,11 +93,11 @@
<div class="d-flex align-center" v-if="editingTransaction !== item || item.type === TransactionType.ModifyBalance">
<span v-if="item.type === TransactionType.ModifyBalance">-</span>
<ItemIcon size="24px" icon-type="category"
:icon-id="allCategoriesMap[item.categoryId].icon"
:color="allCategoriesMap[item.categoryId].color"
:icon-id="allCategoriesMap[item.categoryId]?.icon ?? ''"
:color="allCategoriesMap[item.categoryId]?.color ?? ''"
v-if="item.type !== TransactionType.ModifyBalance && item.categoryId && item.categoryId !== '0' && allCategoriesMap[item.categoryId]"></ItemIcon>
<span class="ms-2" v-if="item.type !== TransactionType.ModifyBalance && item.categoryId && item.categoryId !== '0' && allCategoriesMap[item.categoryId]">
{{ allCategoriesMap[item.categoryId].name }}
{{ allCategoriesMap[item.categoryId]?.name }}
</span>
<div class="text-error font-italic" v-else-if="item.type !== TransactionType.ModifyBalance && (!item.categoryId || item.categoryId === '0' || !allCategoriesMap[item.categoryId])">
<v-icon class="me-1" :icon="mdiAlertOutline"/>
@@ -166,13 +166,13 @@
</template>
<template #item.actualSourceAccountName="{ item }">
<div class="d-flex align-center" v-if="editingTransaction !== item">
<span v-if="item.sourceAccountId && item.sourceAccountId !== '0' && allAccountsMap[item.sourceAccountId]">{{ allAccountsMap[item.sourceAccountId].name }}</span>
<span v-if="item.sourceAccountId && item.sourceAccountId !== '0' && allAccountsMap[item.sourceAccountId]">{{ allAccountsMap[item.sourceAccountId]?.name }}</span>
<div class="text-error font-italic" v-else>
<v-icon class="me-1" :icon="mdiAlertOutline"/>
<span>{{ item.originalSourceAccountName }}</span>
</div>
<v-icon class="icon-with-direction mx-1" size="13" :icon="mdiArrowRight" v-if="item.type === TransactionType.Transfer"></v-icon>
<span v-if="item.type === TransactionType.Transfer && item.destinationAccountId && item.destinationAccountId !== '0' && allAccountsMap[item.destinationAccountId]">{{allAccountsMap[item.destinationAccountId].name }}</span>
<span v-if="item.type === TransactionType.Transfer && item.destinationAccountId && item.destinationAccountId !== '0' && allAccountsMap[item.destinationAccountId]">{{allAccountsMap[item.destinationAccountId]?.name }}</span>
<div class="text-error font-italic" v-else-if="item.type === TransactionType.Transfer && (!item.destinationAccountId || item.destinationAccountId === '0' || !allAccountsMap[item.destinationAccountId])">
<v-icon class="me-1" :icon="mdiAlertOutline"/>
<span>{{ item.originalDestinationAccountName }}</span>
@@ -252,7 +252,7 @@
<v-chip :class="{ 'font-italic': !isTagValid(editingTags, index) }"
:prepend-icon="isTagValid(editingTags, index) ? mdiPound : mdiAlertOutline"
:color="isTagValid(editingTags, index) ? 'default' : 'error'"
:text="isTagValid(editingTags, index) ? allTagsMap[editingTags[index]].name : item.originalTagNames[index]"
:text="isTagValid(editingTags, index) ? allTagsMap[editingTags[index] as string]?.name : item.originalTagNames[index]"
v-bind="props"/>
</template>
@@ -1153,7 +1153,7 @@ function getTransactionDisplayAmount(transaction: ImportTransaction): string {
let currency = transaction.originalSourceAccountCurrency || defaultCurrency.value;
if (transaction.sourceAccountId && transaction.sourceAccountId !== '0' && allAccountsMap.value[transaction.sourceAccountId]) {
currency = allAccountsMap.value[transaction.sourceAccountId].currency;
currency = allAccountsMap.value[transaction.sourceAccountId]!.currency;
}
return getDisplayCurrency(transaction.sourceAmount, currency);
@@ -1167,7 +1167,7 @@ function getTransactionDisplayDestinationAmount(transaction: ImportTransaction):
let currency = transaction.originalDestinationAccountCurrency || defaultCurrency.value;
if (transaction.destinationAccountId && transaction.destinationAccountId !== '0' && allAccountsMap.value[transaction.destinationAccountId]) {
currency = allAccountsMap.value[transaction.destinationAccountId].currency;
currency = allAccountsMap.value[transaction.destinationAccountId]!.currency;
}
return getDisplayCurrency(transaction.destinationAmount, currency);
@@ -1425,15 +1425,15 @@ function updateTransactionData(transaction: ImportTransaction): void {
transaction.valid = transaction.isTransactionValid();
if (transaction.categoryId && allCategoriesMap.value[transaction.categoryId]) {
transaction.actualCategoryName = allCategoriesMap.value[transaction.categoryId].name;
transaction.actualCategoryName = allCategoriesMap.value[transaction.categoryId]!.name;
}
if (transaction.sourceAccountId && allAccountsMap.value[transaction.sourceAccountId]) {
transaction.actualSourceAccountName = allAccountsMap.value[transaction.sourceAccountId].name;
transaction.actualSourceAccountName = allAccountsMap.value[transaction.sourceAccountId]!.name;
}
if (transaction.destinationAccountId && allAccountsMap.value[transaction.destinationAccountId]) {
transaction.actualDestinationAccountName = allAccountsMap.value[transaction.destinationAccountId].name;
transaction.actualDestinationAccountName = allAccountsMap.value[transaction.destinationAccountId]!.name;
}
}
@@ -358,15 +358,16 @@ const parsedFileLinesHeaders = computed<object[]>(() => {
}
}
const headers: object[] = [];
const firstLine: string[] = props.parsedFileData && props.parsedFileData.length > 0 ? (props.parsedFileData[0] as string[]) : [];
const headers: object[] = [];
headers.push({ key: 'index', value: 'index', title: '#', sortable: true, nowrap: true });
for (let i = 0; i < maxColumnCount; i++) {
let title = `#${i + 1}`;
if (parsedFileDataColumnMapping.value.includeHeader && props.parsedFileData && props.parsedFileData[0][i]) {
title = props.parsedFileData[0][i] as string;
if (parsedFileDataColumnMapping.value.includeHeader && firstLine && firstLine[i]) {
title = firstLine[i] as string;
}
headers.push({ key: i.toString(), value: `column${i + 1}`, title: title, sortable: true, nowrap: true });
+20 -19
View File
@@ -370,7 +370,7 @@
<template #default>
<div class="grid grid-cols-2">
<div class="list-item-subitem no-chevron">
<a class="item-link" href="#" @click="subAccountContexts[idx].showIconSelectionSheet = true">
<a class="item-link" href="#" @click="subAccountContexts[idx]!.showIconSelectionSheet = true">
<div class="item-content">
<div class="item-inner">
<div class="item-header">
@@ -387,12 +387,12 @@
<icon-selection-sheet :all-icon-infos="ALL_ACCOUNT_ICONS"
:color="subAccount.color"
v-model:show="subAccountContexts[idx].showIconSelectionSheet"
v-model:show="subAccountContexts[idx]!.showIconSelectionSheet"
v-model="subAccount.icon"
></icon-selection-sheet>
</div>
<div class="list-item-subitem no-chevron">
<a class="item-link" href="#" @click="subAccountContexts[idx].showColorSelectionSheet = true">
<a class="item-link" href="#" @click="subAccountContexts[idx]!.showColorSelectionSheet = true">
<div class="item-content">
<div class="item-inner">
<div class="item-header">
@@ -408,7 +408,7 @@
</a>
<color-selection-sheet :all-color-infos="ALL_ACCOUNT_COLORS"
v-model:show="subAccountContexts[idx].showColorSelectionSheet"
v-model:show="subAccountContexts[idx]!.showColorSelectionSheet"
v-model="subAccount.color"
></color-selection-sheet>
</div>
@@ -422,7 +422,7 @@
:class="{ 'disabled': editAccountId && !isNewAccount(subAccount) }"
:header="tt('Currency')"
:no-chevron="!!editAccountId && !isNewAccount(subAccount)"
@click="subAccountContexts[idx].showCurrencyPopup = true"
@click="subAccountContexts[idx]!.showCurrencyPopup = true"
>
<template #title>
<div class="no-padding no-margin">
@@ -438,7 +438,7 @@
:filter-placeholder="tt('Currency')"
:filter-no-items-text="tt('No results')"
:items="allCurrencies"
v-model:show="subAccountContexts[idx].showCurrencyPopup"
v-model:show="subAccountContexts[idx]!.showCurrencyPopup"
v-model="subAccount.currency">
</list-item-selection-popup>
</f7-list-item>
@@ -449,13 +449,13 @@
:class="{ 'disabled': editAccountId && !isNewAccount(subAccount) }"
:header="account.isLiability ? tt('Sub-account Outstanding Balance') : tt('Sub-account Balance')"
:title="formatAccountDisplayBalance(subAccount)"
@click="subAccountContexts[idx].showBalanceSheet = true"
@click="subAccountContexts[idx]!.showBalanceSheet = true"
>
<number-pad-sheet :min-value="TRANSACTION_MIN_AMOUNT"
:max-value="TRANSACTION_MAX_AMOUNT"
:currency="subAccount.currency"
:flip-negative="account.isLiability"
v-model:show="subAccountContexts[idx].showBalanceSheet"
v-model:show="subAccountContexts[idx]!.showBalanceSheet"
v-model="subAccount.balance"
></number-pad-sheet>
</f7-list-item>
@@ -467,15 +467,15 @@
v-if="!editAccountId || isNewAccount(subAccount)"
>
<template #header>
<div class="account-edit-balancetime-header" @click="showDateTimeDialog(subAccountContexts[idx], 'time')">{{ tt('Sub-account Balance Time') }}</div>
<div class="account-edit-balancetime-header" @click="showDateTimeDialog(subAccountContexts[idx] as AccountContext, 'time')">{{ tt('Sub-account Balance Time') }}</div>
</template>
<template #title>
<div class="account-edit-balancetime-title">
<div @click="showDateTimeDialog(subAccountContexts[idx], 'date')">{{ formatAccountBalanceDate(subAccount) }}</div>&nbsp;<div class="account-edit-balancetime-time" @click="showDateTimeDialog(subAccountContexts[idx], 'time')">{{ formatAccountBalanceTime(subAccount) }}</div>
<div @click="showDateTimeDialog(subAccountContexts[idx] as AccountContext, 'date')">{{ formatAccountBalanceDate(subAccount) }}</div>&nbsp;<div class="account-edit-balancetime-time" @click="showDateTimeDialog(subAccountContexts[idx] as AccountContext, 'time')">{{ formatAccountBalanceTime(subAccount) }}</div>
</div>
</template>
<date-time-selection-sheet :init-mode="subAccountContexts[idx].balanceDateTimeSheetMode"
v-model:show="subAccountContexts[idx].showBalanceDateTimeSheet"
<date-time-selection-sheet :init-mode="subAccountContexts[idx]!.balanceDateTimeSheetMode"
v-model:show="subAccountContexts[idx]!.showBalanceDateTimeSheet"
v-model="subAccount.balanceTime">
</date-time-selection-sheet>
</f7-list-item>
@@ -526,6 +526,7 @@ import { useAccountEditPageBaseBase } from '@/views/base/accounts/AccountEditPag
import { useAccountsStore } from '@/stores/account.ts';
import { itemAndIndex } from '@/core/base.ts';
import type { LocalizedCurrencyInfo } from '@/core/currency.ts';
import { AccountType } from '@/core/account.ts';
import { ALL_ACCOUNT_ICONS } from '@/consts/icon.ts';
@@ -709,14 +710,14 @@ function addSubAccountAndContext(): void {
}
}
function removeSubAccount(subAccount: Account | null, confirm: boolean): void {
if (!subAccount) {
function removeSubAccount(currentSubAccount: Account | null, confirm: boolean): void {
if (!currentSubAccount) {
showAlert('An error occurred');
return;
}
if (!confirm) {
subAccountToDelete.value = subAccount;
subAccountToDelete.value = currentSubAccount;
showDeleteActionSheet.value = true;
return;
}
@@ -724,10 +725,10 @@ function removeSubAccount(subAccount: Account | null, confirm: boolean): void {
showDeleteActionSheet.value = false;
subAccountToDelete.value = null;
for (let i = 0; i < subAccounts.value.length; i++) {
if (subAccounts.value[i] === subAccount) {
subAccounts.value.splice(i, 1);
subAccountContexts.value.splice(i, 1);
for (const [subAccount, index] of itemAndIndex(subAccounts.value)) {
if (subAccount === currentSubAccount) {
subAccounts.value.splice(index, 1);
subAccountContexts.value.splice(index, 1);
}
}
}
+2 -2
View File
@@ -140,13 +140,13 @@ const categories = computed<TransactionCategory[]>(() => {
return [];
}
return transactionCategoriesStore.allTransactionCategories[categoryType.value];
return transactionCategoriesStore.allTransactionCategories[categoryType.value] ?? [];
} else if (primaryCategoryId.value && primaryCategoryId.value !== '' && primaryCategoryId.value !== '0') {
if (!transactionCategoriesStore.allTransactionCategoriesMap || !transactionCategoriesStore.allTransactionCategoriesMap[primaryCategoryId.value]) {
return [];
}
return transactionCategoriesStore.allTransactionCategoriesMap[primaryCategoryId.value].subCategories || [];
return transactionCategoriesStore.allTransactionCategoriesMap[primaryCategoryId.value]?.subCategories ?? [];
} else {
return [];
}
+4 -4
View File
@@ -684,9 +684,9 @@ const transactionPictures = computed<Record<string, string | undefined>[]>(() =>
return thumbs;
}
for (let i = 0; i < transaction.value.pictures.length; i++) {
for (const picture of transaction.value.pictures) {
thumbs.push({
url: getTransactionPictureUrl(transaction.value.pictures[i])
url: getTransactionPictureUrl(picture)
});
}
@@ -700,8 +700,8 @@ const transactionThumbs = computed<(string | undefined)[]>(() => {
return thumbs;
}
for (let i = 0; i < transaction.value.pictures.length; i++) {
thumbs.push(getTransactionPictureUrl(transaction.value.pictures[i]));
for (const picture of transaction.value.pictures) {
thumbs.push(getTransactionPictureUrl(picture));
}
return thumbs;
+13 -21
View File
@@ -200,7 +200,7 @@
v-for="(transaction, idx) in transactionMonthList.items"
>
<template #media>
<div class="display-flex flex-direction-column transaction-date" :style="getTransactionDateStyle(transaction, idx > 0 ? transactionMonthList.items[idx - 1] : null)">
<div class="display-flex flex-direction-column transaction-date" :style="getTransactionDateStyle(transaction, idx > 0 ? transactionMonthList.items[idx - 1] : undefined)">
<span class="transaction-day full-line flex-direction-column">
{{ getCalendarDisplayDayOfMonthFromUnixTime(transaction.time) }}
</span>
@@ -252,7 +252,7 @@
<div class="item-footer">
<div class="transaction-tags" v-if="showTagInTransactionListPage && transaction.tagIds && transaction.tagIds.length">
<f7-chip media-text-color="var(--f7-chip-text-color)" class="transaction-tag"
:text="allTransactionTags[tagId].name"
:text="allTransactionTags[tagId]?.name"
:key="tagId"
v-for="tagId in transaction.tagIds">
<template #media>
@@ -373,7 +373,7 @@
:class="getCategoryListItemCheckedClass(category, queryAllFilterCategoryIds)"
:key="category.id"
v-for="category in categories"
v-show="!category.hidden || query.categoryIds === category.id || (allCategories[query.categoryIds] && allCategories[query.categoryIds].parentId === category.id)"
v-show="!category.hidden || query.categoryIds === category.id || (allCategories[query.categoryIds] && allCategories[query.categoryIds]?.parentId === category.id)"
>
<template #media>
<ItemIcon icon-type="category" :icon-id="category.icon" :color="category.color"></ItemIcon>
@@ -439,7 +439,7 @@
:class="{ 'list-item-selected': query.accountIds === account.id, 'item-in-multiple-selection': queryAllFilterAccountIdsCount > 1 && queryAllFilterAccountIds[account.id] }"
:key="account.id"
v-for="account in allAccounts"
v-show="(!account.hidden && (!allAccountsMap[account.parentId] || !allAccountsMap[account.parentId].hidden)) || query.accountIds === account.id"
v-show="(!account.hidden && (!allAccountsMap[account.parentId] || !allAccountsMap[account.parentId]!.hidden)) || query.accountIds === account.id"
@click="changeAccountFilter(account.id)"
>
<template #media>
@@ -597,7 +597,7 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type TransactionMonthList, useTransactionsStore } from '@/stores/transaction.ts';
import type { TypeAndDisplayName } from '@/core/base.ts';
import { type TypeAndDisplayName, keys } from '@/core/base.ts';
import { TextDirection } from '@/core/text.ts';
import {
type TextualYearMonth,
@@ -742,9 +742,7 @@ const transactions = computed<TransactionMonthList[]>(() => {
const transactions :Transaction[] = [];
for (let i = 0; i < transactionData.items.length; i++) {
const transaction = transactionData.items[i];
for (const transaction of transactionData.items) {
if (transaction.gregorianCalendarYearDashMonthDashDay === currentCalendarDate.value) {
transactions.push(transaction);
}
@@ -778,7 +776,7 @@ const noTransaction = computed<boolean>(() => {
if (pageType.value === TransactionListPageType.List.type) {
return transactionsStore.noTransaction;
} else if (pageType.value === TransactionListPageType.Calendar.type) {
return !transactions.value || !transactions.value.length || !transactions.value[0].items || !transactions.value[0].items.length;
return !transactions.value || !transactions.value.length || !transactions.value[0]!.items || !transactions.value[0]!.items.length;
} else {
return true;
}
@@ -832,8 +830,7 @@ function setTransactionMonthListHeights(reset: boolean): Promise<unknown> {
if (transactions.value && transactions.value.length) {
const heights: Record<string, number> = getElementActualHeights('.transaction-month-list');
for (let i = 0; i < transactions.value.length - 1; i++) {
const transactionMonthList = transactions.value[i];
for (const transactionMonthList of transactions.value) {
const yearDashMonth = transactionMonthList.yearDashMonth;
const domId = getTransactionMonthListDomId(yearDashMonth);
const height = heights[domId];
@@ -851,8 +848,7 @@ function setTransactionInvisibleYearMonthList(): void {
return;
}
for (let i = 0; i < transactions.value.length - 1; i++) {
const transactionMonthList = transactions.value[i];
for (const transactionMonthList of transactions.value) {
const yearDashMonth = transactionMonthList.yearDashMonth;
const titleDomId = getTransactionMonthTitleDomId(yearDashMonth);
@@ -875,7 +871,7 @@ function setTransactionInvisibleYearMonthList(): void {
}
}
function getTransactionDateStyle(transaction: Transaction, previousTransaction: Transaction | null): Record<string, string> {
function getTransactionDateStyle(transaction: Transaction, previousTransaction: Transaction | undefined): Record<string, string> {
if (!previousTransaction || transaction.gregorianCalendarDayOfMonth !== previousTransaction.gregorianCalendarDayOfMonth) {
return {};
}
@@ -893,8 +889,8 @@ function getCategoryListItemCheckedClass(category: TransactionCategory, queryCat
}
if (category.subCategories) {
for (let i = 0; i < category.subCategories.length; i++) {
if (queryCategoryIds && queryCategoryIds[category.subCategories[i].id]) {
for (const subCategory of category.subCategories) {
if (queryCategoryIds && queryCategoryIds[subCategory.id]) {
return {
'list-item-checked': true
};
@@ -1208,11 +1204,7 @@ function changeTypeFilter(type: number): void {
if (type && query.value.categoryIds) {
newCategoryFilter = '';
for (const categoryId in queryAllFilterCategoryIds.value) {
if (!Object.prototype.hasOwnProperty.call(queryAllFilterCategoryIds.value, categoryId)) {
continue;
}
for (const categoryId of keys(queryAllFilterCategoryIds.value)) {
const category = allCategories.value[categoryId];
if (category && category.type === transactionTypeToCategoryType(type)) {