migrate transaction list page to composition API and typescript

This commit is contained in:
MaysWind
2025-02-09 15:07:06 +08:00
parent bb3a0c4444
commit 596787b998
12 changed files with 1875 additions and 2453 deletions
@@ -0,0 +1,312 @@
import { ref, computed } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useAccountsStore } from '@/stores/account.ts';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type TransactionListFilter, type TransactionMonthList, useTransactionsStore } from '@/stores/transaction.ts';
import { type LocalizedDateRange, DateRange, DateRangeScene } from '@/core/datetime.ts';
import { AccountType } from '@/core/account.ts';
import { TransactionType } from '@/core/transaction.ts';
import type { Account } from '@/models/account.ts';
import type { TransactionCategory } from '@/models/transaction_category.ts';
import type { TransactionTag } from '@/models/transaction_tag.ts';
import type { Transaction } from '@/models/transaction.ts';
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffset,
getTimezoneOffsetMinutes,
parseDateFromUnixTime,
getUnixTime,
getYearMonthFirstUnixTime
} from '@/lib/datetime.ts';
import {
getUnifiedSelectedAccountsCurrencyOrDefaultCurrency
} from '@/lib/account.ts';
import {
categoryTypeToTransactionType
} from '@/lib/category.ts';
export function useTransactionListPageBase() {
const {
tt,
getAllDateRanges,
formatUnixTimeToLongDateTime,
formatUnixTimeToLongDate,
formatUnixTimeToLongYearMonth,
formatUnixTimeToShortTime,
formatDateRange,
formatAmountWithCurrency
} = useI18n();
const settingsStore = useSettingsStore();
const userStore = useUserStore();
const accountsStore = useAccountsStore();
const transactionCategoriesStore = useTransactionCategoriesStore();
const transactionTagsStore = useTransactionTagsStore();
const transactionsStore = useTransactionsStore();
const loading = ref<boolean>(true);
const customMinDatetime = ref<number>(0);
const customMaxDatetime = ref<number>(0);
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const firstDayOfWeek = computed<number>(() => userStore.currentUserFirstDayOfWeek);
const defaultCurrency = computed<string>(() => getUnifiedSelectedAccountsCurrencyOrDefaultCurrency(allAccounts.value, queryAllFilterAccountIds.value, userStore.currentUserDefaultCurrency));
const showTotalAmountInTransactionListPage = computed<boolean>(() => settingsStore.appSettings.showTotalAmountInTransactionListPage);
const showTagInTransactionListPage = computed<boolean>(() => settingsStore.appSettings.showTagInTransactionListPage);
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.Normal, true, !!accountsStore.getAccountStatementDate(query.value.accountIds)));
const allAccounts = computed<Record<string, Account>>(() => accountsStore.allAccountsMap);
const allAvailableAccountsCount = computed<number>(() => accountsStore.allAvailableAccountsCount);
const allPrimaryCategories = computed<Record<number, TransactionCategory[]>>(() => {
const primaryCategories: Record<number, TransactionCategory[]> = {};
for (const categoryType in transactionCategoriesStore.allTransactionCategories) {
if (!Object.prototype.hasOwnProperty.call(transactionCategoriesStore.allTransactionCategories, categoryType)) {
continue;
}
if (query.value.type && categoryTypeToTransactionType(parseInt(categoryType)) !== query.value.type) {
continue;
}
primaryCategories[categoryType] = transactionCategoriesStore.allTransactionCategories[categoryType];
}
return primaryCategories;
});
const allCategories = computed<Record<string, TransactionCategory>>(() => transactionCategoriesStore.allTransactionCategoriesMap);
const allAvailableCategoriesCount = computed<number>(() => {
let totalCount = 0;
for (const categoryType in transactionCategoriesStore.allTransactionCategories) {
if (!Object.prototype.hasOwnProperty.call(transactionCategoriesStore.allTransactionCategories, categoryType)) {
continue;
}
if (query.value.type && categoryTypeToTransactionType(parseInt(categoryType)) !== query.value.type) {
continue;
}
if (transactionCategoriesStore.allTransactionCategories[categoryType]) {
totalCount += transactionCategoriesStore.allTransactionCategories[categoryType].length;
}
}
return totalCount;
});
const allTransactionTags = computed<Record<string, TransactionTag>>(() => transactionTagsStore.allTransactionTagsMap);
const allAvailableTagsCount = computed<number>(() => transactionTagsStore.allAvailableTagsCount);
const query = computed<TransactionListFilter>(() => transactionsStore.transactionsFilter);
const queryDateRangeName = computed<string>(() => {
if (query.value.dateType === DateRange.All.type) {
return tt('Date');
}
return formatDateRange(query.value.dateType, query.value.minTime, query.value.maxTime);
});
const queryMinTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.minTime));
const queryMaxTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.maxTime));
const queryAllFilterCategoryIds = computed<Record<string, boolean>>(() => transactionsStore.allFilterCategoryIds);
const queryAllFilterAccountIds = computed<Record<string, boolean>>(() => transactionsStore.allFilterAccountIds);
const queryAllFilterTagIds = computed<Record<string, boolean>>(() => transactionsStore.allFilterTagIds);
const queryAllFilterCategoryIdsCount = computed<number>(() => transactionsStore.allFilterCategoryIdsCount);
const queryAllFilterAccountIdsCount = computed<number>(() => transactionsStore.allFilterAccountIdsCount);
const queryAllFilterTagIdsCount = computed<number>(() => transactionsStore.allFilterTagIdsCount);
const queryAccountName = computed<string>(() => {
if (queryAllFilterAccountIdsCount.value > 1) {
return tt('Multiple Accounts');
}
return allAccounts.value[query.value.accountIds]?.name || tt('Account');
});
const queryCategoryName = computed<string>(() => {
if (queryAllFilterCategoryIdsCount.value > 1) {
return tt('Multiple Categories');
}
return allCategories.value[query.value.categoryIds]?.name || tt('Category');
});
const queryTagName = computed<string>(() => {
if (query.value.tagIds === 'none') {
return tt('Without Tags');
}
if (queryAllFilterTagIdsCount.value > 1) {
return tt('Multiple Tags');
}
return allTransactionTags.value[query.value.tagIds]?.name || tt('Tags');
});
const queryAmount = computed<string>(() => {
if (!query.value.amountFilter) {
return '';
}
const amountFilterItems = query.value.amountFilter.split(':');
if (amountFilterItems.length < 2) {
return '';
}
const displayAmount: string[] = [];
for (let i = 1; i < amountFilterItems.length; i++) {
displayAmount.push(formatAmountWithCurrency(amountFilterItems[i], false));
}
return displayAmount.join(' ~ ');
});
const canAddTransaction = computed<boolean>(() => {
if (query.value.accountIds && queryAllFilterAccountIdsCount.value === 1) {
const account = allAccounts.value[query.value.accountIds];
if (account && account.type === AccountType.MultiSubAccounts.type) {
return false;
}
}
return true;
});
function formatAmount(amount: number, hideAmount: boolean, currencyCode: string): string {
if (hideAmount) {
return formatAmountWithCurrency('***', currencyCode);
}
return formatAmountWithCurrency(amount, currencyCode);
}
function getDisplayTime(transaction: Transaction): string {
return formatUnixTimeToShortTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
}
function getDisplayLongDate(transaction: Transaction): string {
const transactionTime = getUnixTime(parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value));
return formatUnixTimeToLongDate(transactionTime);
}
function getDisplayLongYearMonth(transactionMonthList: TransactionMonthList): string {
return formatUnixTimeToLongYearMonth(getYearMonthFirstUnixTime(transactionMonthList.yearMonth));
}
function getDisplayTimezone(transaction: Transaction): string {
return `UTC${getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset)}`;
}
function getDisplayTimeInDefaultTimezone(transaction: Transaction): string {
return `${formatUnixTimeToLongDateTime(transaction.time)} (UTC${getTimezoneOffset(settingsStore.appSettings.timeZone)})`;
}
function getDisplayAmount(transaction: Transaction): string {
if (queryAllFilterAccountIdsCount.value < 1) {
if (transaction.sourceAccount) {
return formatAmount(transaction.sourceAmount, transaction.hideAmount, transaction.sourceAccount.currency);
}
} else if (queryAllFilterAccountIdsCount.value === 1) {
if (transaction.sourceAccount && (queryAllFilterAccountIds.value[transaction.sourceAccount.id] || queryAllFilterAccountIds.value[transaction.sourceAccount.parentId])) {
return formatAmount(transaction.sourceAmount, transaction.hideAmount, transaction.sourceAccount.currency);
} else if (transaction.destinationAccount && (queryAllFilterAccountIds.value[transaction.destinationAccount.id] || queryAllFilterAccountIds.value[transaction.destinationAccount.parentId])) {
return formatAmount(transaction.destinationAmount, transaction.hideAmount, transaction.destinationAccount.currency);
}
} else { // queryAllFilterAccountIdsCount.value > 1
if (transaction.sourceAccount && transaction.destinationAccount) {
if ((queryAllFilterAccountIds.value[transaction.sourceAccount.id] || queryAllFilterAccountIds.value[transaction.sourceAccount.parentId])
&& !queryAllFilterAccountIds.value[transaction.destinationAccount.id] && !queryAllFilterAccountIds.value[transaction.destinationAccount.parentId]) {
return formatAmount(transaction.sourceAmount, transaction.hideAmount, transaction.sourceAccount.currency);
} else if ((queryAllFilterAccountIds.value[transaction.destinationAccount.id] || queryAllFilterAccountIds.value[transaction.destinationAccount.parentId])
&& !queryAllFilterAccountIds.value[transaction.sourceAccount.id] && !queryAllFilterAccountIds.value[transaction.sourceAccount.parentId]) {
return formatAmount(transaction.destinationAmount, transaction.hideAmount, transaction.destinationAccount.currency);
}
}
}
if (transaction.sourceAccount) {
return formatAmount(transaction.sourceAmount, transaction.hideAmount, transaction.sourceAccount.currency);
}
return '';
}
function getDisplayMonthTotalAmount(amount: number, currency: string, symbol: string, incomplete: boolean): string {
const displayAmount = formatAmountWithCurrency(amount, currency);
return symbol + displayAmount + (incomplete ? '+' : '');
}
function getTransactionTypeName(type: number | null, defaultName: string): string {
switch (type){
case TransactionType.ModifyBalance:
return tt('Modify Balance');
case TransactionType.Income:
return tt('Income');
case TransactionType.Expense:
return tt('Expense');
case TransactionType.Transfer:
return tt('Transfer');
default:
return tt(defaultName);
}
}
return {
// states
loading,
customMinDatetime,
customMaxDatetime,
// computed states
currentTimezoneOffsetMinutes,
firstDayOfWeek,
defaultCurrency,
showTotalAmountInTransactionListPage,
showTagInTransactionListPage,
allDateRanges,
allAccounts,
allAvailableAccountsCount,
allCategories,
allPrimaryCategories,
allAvailableCategoriesCount,
allTransactionTags,
allAvailableTagsCount,
query,
queryDateRangeName,
queryMinTime,
queryMaxTime,
queryAllFilterCategoryIds,
queryAllFilterAccountIds,
queryAllFilterTagIds,
queryAllFilterCategoryIdsCount,
queryAllFilterAccountIdsCount,
queryAllFilterTagIdsCount,
queryAccountName,
queryCategoryName,
queryTagName,
queryAmount,
canAddTransaction,
// functions
getDisplayTime,
getDisplayLongDate,
getDisplayLongYearMonth,
getDisplayTimezone,
getDisplayTimeInDefaultTimezone,
getDisplayAmount,
getDisplayMonthTotalAmount,
getTransactionTypeName,
};
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff