diff --git a/src/locales/helpers.ts b/src/locales/helpers.ts index a3a506f4..146ed6e6 100644 --- a/src/locales/helpers.ts +++ b/src/locales/helpers.ts @@ -1363,6 +1363,8 @@ export function useI18n() { formatUnixTimeToShortDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat(), utcOffset, currentUtcOffset), formatUnixTimeToLongYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearFormat(), utcOffset, currentUtcOffset), formatUnixTimeToShortYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToLongMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMMM', utcOffset, currentUtcOffset), + formatUnixTimeToShortMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMM', utcOffset, currentUtcOffset), formatUnixTimeToLongYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearMonthFormat(), utcOffset, currentUtcOffset), formatUnixTimeToShortYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearMonthFormat(), utcOffset, currentUtcOffset), formatUnixTimeToLongMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongMonthDayFormat(), utcOffset, currentUtcOffset), diff --git a/src/models/transaction.ts b/src/models/transaction.ts index b2ce576f..c2a638e6 100644 --- a/src/models/transaction.ts +++ b/src/models/transaction.ts @@ -128,14 +128,40 @@ export interface TransactionStatisticTrendsRequest extends YearMonthRangeRequest } export const ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE = [ - 'today', 'thisWeek', 'thisMonth', 'thisYear', 'lastMonth', - 'monthBeforeLastMonth', 'monthBeforeLast2Months', 'monthBeforeLast3Months', - 'monthBeforeLast4Months', 'monthBeforeLast5Months', 'monthBeforeLast6Months', - 'monthBeforeLast7Months', 'monthBeforeLast8Months', 'monthBeforeLast9Months', 'monthBeforeLast10Months' + 'today', + 'thisWeek', + 'thisMonth', + 'thisYear', + 'lastMonth', + 'monthBeforeLastMonth', + 'monthBeforeLast2Months', + 'monthBeforeLast3Months', + 'monthBeforeLast4Months', + 'monthBeforeLast5Months', + 'monthBeforeLast6Months', + 'monthBeforeLast7Months', + 'monthBeforeLast8Months', + 'monthBeforeLast9Months', + 'monthBeforeLast10Months' ] as const; export type TransactionAmountsRequestType = typeof ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE[number]; +export const LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES: TransactionAmountsRequestType[] = [ + 'monthBeforeLast10Months', + 'monthBeforeLast9Months', + 'monthBeforeLast8Months', + 'monthBeforeLast7Months', + 'monthBeforeLast6Months', + 'monthBeforeLast5Months', + 'monthBeforeLast4Months', + 'monthBeforeLast3Months', + 'monthBeforeLast2Months', + 'monthBeforeLastMonth', + 'lastMonth', + 'thisMonth' +]; + export interface TransactionAmountsRequestParams extends PartialRecord { readonly useTransactionTimezone: boolean; today?: StartEndTime; @@ -226,6 +252,14 @@ export interface TransactionAmountsResponseItemAmountInfo { export type TransactionOverviewResponse = PartialRecord; +export type TransactionOverviewDisplayTime = PartialRecord; + +export interface TransactionOverviewDisplayTimeItem { + readonly displayTime?: string; + readonly startTime?: string; + readonly endTime?: string; +} + export interface TransactionOverviewResponseItem { readonly valid: boolean; readonly incomeAmount: number; diff --git a/src/stores/overview.ts b/src/stores/overview.ts index 81e00cd7..14bd5905 100644 --- a/src/stores/overview.ts +++ b/src/stores/overview.ts @@ -8,6 +8,7 @@ import { useExchangeRatesStore } from './exchangeRates.ts'; import type { WritableStartEndTime } from '@/core/datetime.ts'; import { TimezoneTypeForStatistics } from '@/core/timezone.ts'; import type { + TransactionAmountsRequestType, TransactionAmountsRequestParams, TransactionAmountsResponse, TransactionOverviewResponse @@ -29,7 +30,7 @@ import { import logger from '@/lib/logger.ts'; import services from '@/lib/services.ts'; -interface TransactionDataRange extends Record { +interface TransactionDataRange extends Record { today: { startTime: number; endTime: number; @@ -260,8 +261,8 @@ export const useOverviewStore = defineStore('overview', () => { transactionDataRange.value.monthBeforeLastMonth.endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 2, 'months'); for (let i = 2; i <= 10; i++) { - transactionDataRange.value[`monthBeforeLast${i}Months`].startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), i + 1, 'months'); - transactionDataRange.value[`monthBeforeLast${i}Months`].endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), i + 1, 'months'); + transactionDataRange.value[`monthBeforeLast${i}Months` as TransactionAmountsRequestType].startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), i + 1, 'months'); + transactionDataRange.value[`monthBeforeLast${i}Months` as TransactionAmountsRequestType].endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), i + 1, 'months'); } } diff --git a/src/views/base/HomePageBase.ts b/src/views/base/HomePageBase.ts new file mode 100644 index 00000000..783739c0 --- /dev/null +++ b/src/views/base/HomePageBase.ts @@ -0,0 +1,106 @@ +import { 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 { useOverviewStore } from '@/stores/overview.ts'; + +import { Account } from '@/models/account.ts'; +import type { + TransactionOverviewDisplayTime, + TransactionOverviewResponseItem +} from '@/models/transaction.ts'; + +export function useHomePageBase() { + const { + formatUnixTimeToLongDate, + formatUnixTimeToLongYear, + formatUnixTimeToLongMonth, + formatUnixTimeToLongMonthDay, + formatAmountWithCurrency + } = useI18n(); + + const settingsStore = useSettingsStore(); + const userStore = useUserStore(); + const accountsStore = useAccountsStore(); + const overviewStore = useOverviewStore(); + + const showAmountInHomePage = computed({ + get: () => settingsStore.appSettings.showAmountInHomePage, + set: (value) => settingsStore.setShowAmountInHomePage(value) + }); + + const defaultCurrency = computed(() => userStore.currentUserDefaultCurrency); + const allAccounts = computed(() => accountsStore.allAccounts); + + const netAssets = computed(() => { + const netAssets = accountsStore.getNetAssets(showAmountInHomePage.value); + return formatAmountWithCurrency(netAssets, defaultCurrency.value) as string; + }); + + const totalAssets = computed(() => { + const totalAssets = accountsStore.getTotalAssets(showAmountInHomePage.value); + return formatAmountWithCurrency(totalAssets, defaultCurrency.value) as string; + }); + + const totalLiabilities = computed(() => { + const totalLiabilities = accountsStore.getTotalLiabilities(showAmountInHomePage.value); + return formatAmountWithCurrency(totalLiabilities, defaultCurrency.value) as string; + }); + + const displayDateRange = computed(() => { + return { + today: { + displayTime: formatUnixTimeToLongDate(overviewStore.transactionDataRange.today.startTime), + }, + thisWeek: { + startTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisWeek.startTime), + endTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisWeek.endTime) + }, + thisMonth: { + displayTime: formatUnixTimeToLongMonth(overviewStore.transactionDataRange.thisMonth.startTime), + startTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisMonth.startTime), + endTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisMonth.endTime) + }, + thisYear: { + displayTime: formatUnixTimeToLongYear(overviewStore.transactionDataRange.thisYear.startTime) + } + }; + }); + + const transactionOverview = computed(() => overviewStore.transactionOverview); + + function getDisplayAmount(amount: number, incomplete: boolean): string { + if (!showAmountInHomePage.value) { + return formatAmountWithCurrency('***', defaultCurrency.value) as string; + } + + return formatAmountWithCurrency(amount, defaultCurrency.value) + (incomplete ? '+' : ''); + } + + function getDisplayIncomeAmount(category: TransactionOverviewResponseItem): string { + return getDisplayAmount(category.incomeAmount, category.incompleteIncomeAmount); + } + + function getDisplayExpenseAmount(category: TransactionOverviewResponseItem): string { + return getDisplayAmount(category.expenseAmount, category.incompleteExpenseAmount); + } + + return { + // computed states + showAmountInHomePage, + defaultCurrency, + allAccounts, + netAssets, + totalAssets, + totalLiabilities, + displayDateRange, + transactionOverview, + // functions + getDisplayAmount, + getDisplayIncomeAmount, + getDisplayExpenseAmount + }; +} diff --git a/src/views/desktop/HomePage.vue b/src/views/desktop/HomePage.vue index dbf7aab1..28558089 100644 --- a/src/views/desktop/HomePage.vue +++ b/src/views/desktop/HomePage.vue @@ -5,9 +5,9 @@ - {{ $t('Refresh') }} + {{ tt('Refresh') }} @@ -30,11 +30,11 @@
- {{ $t('Monthly income') }} + {{ tt('Monthly income') }} {{ transactionOverview && transactionOverview.thisMonth ? getDisplayIncomeAmount(transactionOverview.thisMonth) : '-' }}
- {{ $t('View Details') }} + {{ tt('View Details') }} @@ -44,12 +44,12 @@
- {{ $t('format.misc.youHaveAccounts', { count: allAccounts.length }) }} + {{ tt('format.misc.youHaveAccounts', { count: allAccounts.length }) }}
@@ -63,7 +63,7 @@
- {{ $t('Total assets') }} + {{ tt('Total assets') }} {{ totalAssets }}
@@ -79,7 +79,7 @@
- {{ $t('Total liabilities') }} + {{ tt('Total liabilities') }} {{ totalLiabilities }}
@@ -95,7 +95,7 @@
- {{ $t('Net assets') }} + {{ tt('Net assets') }} {{ netAssets }}
@@ -111,14 +111,14 @@ @@ -127,14 +127,14 @@ @@ -143,14 +143,14 @@ @@ -159,14 +159,14 @@ @@ -184,25 +184,26 @@ - diff --git a/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue b/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue index f3932452..c2de60b2 100644 --- a/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue +++ b/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue @@ -42,7 +42,7 @@ import { } from '@/lib/datetime.ts'; import { getExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; -interface MonthlyIncomeAndExpenseCardClickEvent { +export interface MonthlyIncomeAndExpenseCardClickEvent { transactionType: TransactionType; monthStartTime: number; }