migrate transaction edit page to composition API and typescript
This commit is contained in:
@@ -5,7 +5,6 @@ type TemplateTypeName = 'Normal' | 'Schedule';
|
||||
export class TemplateType implements TypeAndName {
|
||||
private static readonly allInstances: TemplateType[] = [];
|
||||
private static readonly allInstancesByType: Record<number, TemplateType> = {};
|
||||
private static readonly allInstancesByTypeName: Record<string, TemplateType> = {};
|
||||
|
||||
public static readonly Normal = new TemplateType(1, 'Normal');
|
||||
public static readonly Schedule = new TemplateType(2, 'Schedule');
|
||||
@@ -19,17 +18,12 @@ export class TemplateType implements TypeAndName {
|
||||
|
||||
TemplateType.allInstances.push(this);
|
||||
TemplateType.allInstancesByType[type] = this;
|
||||
TemplateType.allInstancesByTypeName[name] = this;
|
||||
}
|
||||
|
||||
public static values(): TemplateType[] {
|
||||
return TemplateType.allInstances;
|
||||
}
|
||||
|
||||
public static all(): Record<TemplateTypeName, TemplateType> {
|
||||
return TemplateType.allInstancesByTypeName;
|
||||
}
|
||||
|
||||
public static valueOf(type: number): TemplateType | undefined {
|
||||
return TemplateType.allInstancesByType[type];
|
||||
}
|
||||
|
||||
+1
-1
@@ -434,7 +434,7 @@ export default {
|
||||
timeout: DEFAULT_IMPORT_API_TIMEOUT
|
||||
} as ApiRequestConfig);
|
||||
},
|
||||
uploadTransactionPicture: ({ pictureFile, clientSessionId }: { pictureFile: File, clientSessionId: string }): ApiResponsePromise<TransactionPictureInfoBasicResponse> => {
|
||||
uploadTransactionPicture: ({ pictureFile, clientSessionId }: { pictureFile: File, clientSessionId?: string }): ApiResponsePromise<TransactionPictureInfoBasicResponse> => {
|
||||
return axios.postForm<ApiResponse<TransactionPictureInfoBasicResponse>>('v1/transaction/pictures/upload.json', {
|
||||
picture: pictureFile,
|
||||
clientSessionId: clientSessionId
|
||||
|
||||
@@ -20,14 +20,14 @@ import {
|
||||
} from './category.ts';
|
||||
|
||||
export interface SetTransactionOptions {
|
||||
type: number;
|
||||
categoryId: string;
|
||||
accountId: string;
|
||||
destinationAccountId: string;
|
||||
amount: number;
|
||||
destinationAmount: number;
|
||||
tagIds: string;
|
||||
comment: string;
|
||||
type?: number;
|
||||
categoryId?: string;
|
||||
accountId?: string;
|
||||
destinationAccountId?: string;
|
||||
amount?: number;
|
||||
destinationAmount?: number;
|
||||
tagIds?: string;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
function getDisplayAmount(amount: number, currency: string, hideAmount: boolean, formatAmountWithCurrencyFunc: (value: number | string, currencyCode?: string) => string): string {
|
||||
|
||||
+24
-24
@@ -37,26 +37,6 @@ export function showAlert(message: string, confirmCallback: ((dialog: Dialog.Dia
|
||||
});
|
||||
}
|
||||
|
||||
export function showConfirm(message: string, confirmCallback: (dialog: Dialog.Dialog, e: Event) => void, cancelCallback: ((dialog: Dialog.Dialog, e: Event) => void) | undefined, translateFn: TranslateFunction): void {
|
||||
f7ready((f7) => {
|
||||
f7.dialog.create({
|
||||
title: translateFn('global.app.title'),
|
||||
text: translateFn(message),
|
||||
animate: isEnableAnimate(),
|
||||
buttons: [
|
||||
{
|
||||
text: translateFn('Cancel'),
|
||||
onClick: cancelCallback
|
||||
},
|
||||
{
|
||||
text: translateFn('OK'),
|
||||
onClick: confirmCallback
|
||||
}
|
||||
]
|
||||
}).open();
|
||||
});
|
||||
}
|
||||
|
||||
export function showToast(message: string, timeout: number | undefined, translateFn: TranslateFunction): void {
|
||||
f7ready((f7) => {
|
||||
f7.toast.create({
|
||||
@@ -210,7 +190,7 @@ export function scrollToSelectedItem(parentEl: Framework7Dom, containerSelector:
|
||||
}
|
||||
|
||||
export function useI18nUIComponents() {
|
||||
const i18nGlobal = useVueI18n();
|
||||
const { t } = useVueI18n();
|
||||
|
||||
function routeBackOnError<T>(f7router: Router.Router, errorRef: Ref<T>): void {
|
||||
const unwatch = watch(errorRef, (newValue) => {
|
||||
@@ -228,10 +208,30 @@ export function useI18nUIComponents() {
|
||||
});
|
||||
}
|
||||
|
||||
function showConfirm(message: string, confirmCallback?: (dialog: Dialog.Dialog, e: Event) => void, cancelCallback?: ((dialog: Dialog.Dialog, e: Event) => void) | undefined): void {
|
||||
f7ready((f7) => {
|
||||
f7.dialog.create({
|
||||
title: t('global.app.title'),
|
||||
text: t(message),
|
||||
animate: isEnableAnimate(),
|
||||
buttons: [
|
||||
{
|
||||
text: t('Cancel'),
|
||||
onClick: cancelCallback
|
||||
},
|
||||
{
|
||||
text: t('OK'),
|
||||
onClick: confirmCallback
|
||||
}
|
||||
]
|
||||
}).open();
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
showAlert: (message: string, confirmCallback?: (dialog: Dialog.Dialog, e: Event) => void) => showAlert(message, confirmCallback, i18nGlobal.t),
|
||||
showConfirm: (message: string, confirmCallback: (dialog: Dialog.Dialog, e: Event) => void, cancelCallback?: (dialog: Dialog.Dialog, e: Event) => void): void => showConfirm(message, confirmCallback, cancelCallback, i18nGlobal.t),
|
||||
showToast: (message: string, timeout?: number): void => showToast(message, timeout, i18nGlobal.t),
|
||||
showAlert: (message: string, confirmCallback?: (dialog: Dialog.Dialog, e: Event) => void) => showAlert(message, confirmCallback, t),
|
||||
showConfirm: showConfirm,
|
||||
showToast: (message: string, timeout?: number): void => showToast(message, timeout, t),
|
||||
routeBackOnError
|
||||
}
|
||||
}
|
||||
|
||||
+4
-269
@@ -1,29 +1,21 @@
|
||||
import { WeekDay, LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat, DateRange } from '@/core/datetime.ts';
|
||||
import { LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat, DateRange } from '@/core/datetime.ts';
|
||||
import { DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts';
|
||||
import { CurrencyDisplayType } from '@/core/currency.ts'
|
||||
import { AccountCategory } from '@/core/account.ts';
|
||||
import { TransactionTagFilterType } from '@/core/transaction.ts';
|
||||
|
||||
import { UTC_TIMEZONE, ALL_TIMEZONES } from '@/consts/timezone.ts';
|
||||
import { ALL_CURRENCIES } from '@/consts/currency.ts';
|
||||
import { KnownErrorCode, SPECIFIED_API_NOT_FOUND_ERRORS, PARAMETERIZED_ERRORS } from '@/consts/api.ts';
|
||||
|
||||
import {
|
||||
isString,
|
||||
isNumber,
|
||||
isBoolean,
|
||||
copyObjectTo
|
||||
isBoolean
|
||||
} from '@/lib/common.ts';
|
||||
|
||||
import {
|
||||
parseDateFromUnixTime,
|
||||
formatUnixTime,
|
||||
getYear,
|
||||
getTimezoneOffset,
|
||||
getTimezoneOffsetMinutes,
|
||||
getBrowserTimezoneOffset,
|
||||
getBrowserTimezoneOffsetMinutes,
|
||||
getTimeDifferenceHoursAndMinutes,
|
||||
getDateTimeFormatType,
|
||||
getRecentMonthDateRanges,
|
||||
isDateRangeMatchFullYears,
|
||||
@@ -31,8 +23,7 @@ import {
|
||||
} from '@/lib/datetime.ts';
|
||||
|
||||
import {
|
||||
formatAmount,
|
||||
getAdaptiveDisplayAmountRate
|
||||
formatAmount
|
||||
} from '@/lib/numeral.ts';
|
||||
|
||||
import {
|
||||
@@ -40,11 +31,6 @@ import {
|
||||
appendCurrencySymbol
|
||||
} from '@/lib/currency.ts';
|
||||
|
||||
import {
|
||||
getCategorizedAccountsMap,
|
||||
getAllFilteredAccountsBalance
|
||||
} from '@/lib/account.ts';
|
||||
|
||||
function getLocalizedDisplayNameAndType(typeAndNames, translateFn) {
|
||||
const ret = [];
|
||||
|
||||
@@ -78,10 +64,6 @@ function getCurrencyUnitName(currencyCode, isPlural, translateFn) {
|
||||
return '';
|
||||
}
|
||||
|
||||
function getMonthdayOrdinal(monthDay, translateFn) {
|
||||
return translateFn(`datetime.monthDayOrdinal.${monthDay}`);
|
||||
}
|
||||
|
||||
function getWeekdayShortName(weekDayName, translateFn) {
|
||||
return translateFn(`datetime.${weekDayName}.short`);
|
||||
}
|
||||
@@ -90,50 +72,6 @@ function getWeekdayLongName(weekDayName, translateFn) {
|
||||
return translateFn(`datetime.${weekDayName}.long`);
|
||||
}
|
||||
|
||||
function getMultiMonthdayShortNames(monthDays, translateFn) {
|
||||
if (!monthDays) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (monthDays.length === 1) {
|
||||
return translateFn('format.misc.monthDay', {
|
||||
ordinal: getMonthdayOrdinal(monthDays[0], translateFn)
|
||||
});
|
||||
} else {
|
||||
return translateFn('format.misc.monthDays', {
|
||||
multiMonthDays: joinMultiText(monthDays.map(monthDay =>
|
||||
translateFn('format.misc.eachMonthDayInMonthDays', {
|
||||
ordinal: getMonthdayOrdinal(monthDay, translateFn)
|
||||
})), translateFn)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getMultiWeekdayLongNames(weekdayTypes, firstDayOfWeek, translateFn) {
|
||||
const weekdayTypesMap = {};
|
||||
|
||||
if (!isNumber(firstDayOfWeek)) {
|
||||
firstDayOfWeek = WeekDay.DefaultFirstDay.type;
|
||||
}
|
||||
|
||||
for (let i = 0; i < weekdayTypes.length; i++) {
|
||||
weekdayTypesMap[weekdayTypes[i]] = true;
|
||||
}
|
||||
|
||||
const allWeekDays = getAllWeekDays(firstDayOfWeek, translateFn);
|
||||
const finalWeekdayNames = [];
|
||||
|
||||
for (let i = 0; i < allWeekDays.length; i++) {
|
||||
const weekDay = allWeekDays[i];
|
||||
|
||||
if (weekdayTypesMap[weekDay.type]) {
|
||||
finalWeekdayNames.push(weekDay.displayName);
|
||||
}
|
||||
}
|
||||
|
||||
return joinMultiText(finalWeekdayNames, translateFn);
|
||||
}
|
||||
|
||||
function getI18nLongDateFormat(translateFn, formatTypeValue) {
|
||||
const defaultLongDateFormatTypeName = translateFn('default.longDateFormat');
|
||||
return getDateTimeFormat(translateFn, LongDateFormat.all(), LongDateFormat.values(), 'format.longDate', defaultLongDateFormatTypeName, LongDateFormat.Default, formatTypeValue);
|
||||
@@ -184,110 +122,6 @@ function getDateTimeFormat(translateFn, allFormatMap, allFormatArray, localeForm
|
||||
return translateFn(`${localeFormatPathPrefix}.${type.key}`);
|
||||
}
|
||||
|
||||
function getAllTimezones(includeSystemDefault, translateFn) {
|
||||
const defaultTimezoneOffset = getBrowserTimezoneOffset();
|
||||
const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes();
|
||||
const allTimezoneInfos = [];
|
||||
|
||||
for (let i = 0; i < ALL_TIMEZONES.length; i++) {
|
||||
const utcOffset = (ALL_TIMEZONES[i].timezoneName !== UTC_TIMEZONE.timezoneName ? getTimezoneOffset(ALL_TIMEZONES[i].timezoneName) : '');
|
||||
const displayName = translateFn(`timezone.${ALL_TIMEZONES[i].displayName}`);
|
||||
|
||||
allTimezoneInfos.push({
|
||||
name: ALL_TIMEZONES[i].timezoneName,
|
||||
utcOffset: utcOffset,
|
||||
utcOffsetMinutes: getTimezoneOffsetMinutes(ALL_TIMEZONES[i].timezoneName),
|
||||
displayName: displayName,
|
||||
displayNameWithUtcOffset: `(UTC${utcOffset}) ${displayName}`
|
||||
});
|
||||
}
|
||||
|
||||
if (includeSystemDefault) {
|
||||
const defaultDisplayName = translateFn('System Default');
|
||||
|
||||
allTimezoneInfos.push({
|
||||
name: '',
|
||||
utcOffset: defaultTimezoneOffset,
|
||||
utcOffsetMinutes: defaultTimezoneOffsetMinutes,
|
||||
displayName: defaultDisplayName,
|
||||
displayNameWithUtcOffset: `(UTC${defaultTimezoneOffset}) ${defaultDisplayName}`
|
||||
});
|
||||
}
|
||||
|
||||
allTimezoneInfos.sort(function(c1, c2) {
|
||||
const utcOffset1 = parseInt(c1.utcOffset.replace(':', ''));
|
||||
const utcOffset2 = parseInt(c2.utcOffset.replace(':', ''));
|
||||
|
||||
if (utcOffset1 !== utcOffset2) {
|
||||
return utcOffset1 - utcOffset2;
|
||||
}
|
||||
|
||||
return c1.displayName.localeCompare(c2.displayName);
|
||||
})
|
||||
|
||||
return allTimezoneInfos;
|
||||
}
|
||||
|
||||
function getTimezoneDifferenceDisplayText(utcOffset, translateFn) {
|
||||
const defaultTimezoneOffset = getTimezoneOffsetMinutes();
|
||||
const offsetTime = getTimeDifferenceHoursAndMinutes(utcOffset - defaultTimezoneOffset);
|
||||
|
||||
if (utcOffset > defaultTimezoneOffset) {
|
||||
if (offsetTime.offsetMinutes) {
|
||||
return translateFn('format.misc.hoursMinutesAheadOfDefaultTimezone', {
|
||||
hours: offsetTime.offsetHours,
|
||||
minutes: offsetTime.offsetMinutes
|
||||
});
|
||||
} else {
|
||||
return translateFn('format.misc.hoursAheadOfDefaultTimezone', {
|
||||
hours: offsetTime.offsetHours
|
||||
});
|
||||
}
|
||||
} else if (utcOffset < defaultTimezoneOffset) {
|
||||
if (offsetTime.offsetMinutes) {
|
||||
return translateFn('format.misc.hoursMinutesBehindDefaultTimezone', {
|
||||
hours: offsetTime.offsetHours,
|
||||
minutes: offsetTime.offsetMinutes
|
||||
});
|
||||
} else {
|
||||
return translateFn('format.misc.hoursBehindDefaultTimezone', {
|
||||
hours: offsetTime.offsetHours
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return translateFn('Same time as default timezone');
|
||||
}
|
||||
}
|
||||
|
||||
function getAllWeekDays(firstDayOfWeek, translateFn) {
|
||||
const ret = [];
|
||||
const allWeekDays = WeekDay.values();
|
||||
|
||||
if (!isNumber(firstDayOfWeek)) {
|
||||
firstDayOfWeek = WeekDay.DefaultFirstDay.type;
|
||||
}
|
||||
|
||||
for (let i = firstDayOfWeek; i < allWeekDays.length; i++) {
|
||||
const weekDay = allWeekDays[i];
|
||||
|
||||
ret.push({
|
||||
type: weekDay.type,
|
||||
displayName: translateFn(`datetime.${weekDay.name}.long`)
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < firstDayOfWeek; i++) {
|
||||
const weekDay = allWeekDays[i];
|
||||
|
||||
ret.push({
|
||||
type: weekDay.type,
|
||||
displayName: translateFn(`datetime.${weekDay.name}.long`)
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getAllDateRanges(scene, includeCustom, includeBillingCycle, translateFn) {
|
||||
const ret = [];
|
||||
const allDateRanges = DateRange.values();
|
||||
@@ -460,11 +294,6 @@ function getNumberFormatOptions(translateFn, userStore, currencyCode) {
|
||||
};
|
||||
}
|
||||
|
||||
function getFormattedAmount(value, translateFn, userStore, currencyCode) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore, currencyCode);
|
||||
return formatAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getCurrentCurrencyDisplayType(translateFn, userStore) {
|
||||
let currencyDisplayType = CurrencyDisplayType.valueOf(userStore.currentUserCurrencyDisplayType);
|
||||
|
||||
@@ -525,96 +354,10 @@ function getFormattedAmountWithCurrency(value, currencyCode, translateFn, userSt
|
||||
return appendCurrencySymbol(value, currencyDisplayType, currencyCode, currencyUnit, currencyName, isPlural);
|
||||
}
|
||||
|
||||
function getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getAllTransactionTagFilterTypes(translateFn) {
|
||||
return getLocalizedDisplayNameAndType(TransactionTagFilterType.values(), translateFn);
|
||||
}
|
||||
|
||||
function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, translateFn) {
|
||||
const ret = [];
|
||||
const allCategories = AccountCategory.values();
|
||||
const categorizedAccounts = copyObjectTo(getCategorizedAccountsMap(allVisibleAccounts), {});
|
||||
|
||||
for (let i = 0; i < allCategories.length; i++) {
|
||||
const category = allCategories[i];
|
||||
|
||||
if (!categorizedAccounts[category.type]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const accountCategory = categorizedAccounts[category.type];
|
||||
|
||||
if (accountCategory.accounts) {
|
||||
for (let i = 0; i < accountCategory.accounts.length; i++) {
|
||||
const account = accountCategory.accounts[i];
|
||||
|
||||
if (showAccountBalance && account.isAsset) {
|
||||
account.displayBalance = getFormattedAmountWithCurrency(account.balance, account.currency, translateFn, userStore, settingsStore);
|
||||
} else if (showAccountBalance && account.isLiability) {
|
||||
account.displayBalance = getFormattedAmountWithCurrency(-account.balance, account.currency, translateFn, userStore, settingsStore);
|
||||
} else {
|
||||
account.displayBalance = '***';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showAccountBalance) {
|
||||
const accountsBalance = getAllFilteredAccountsBalance(categorizedAccounts, account => account.category === accountCategory.category);
|
||||
let totalBalance = 0;
|
||||
let hasUnCalculatedAmount = false;
|
||||
|
||||
for (let i = 0; i < accountsBalance.length; i++) {
|
||||
if (accountsBalance[i].currency === defaultCurrency) {
|
||||
if (accountsBalance[i].isAsset) {
|
||||
totalBalance += accountsBalance[i].balance;
|
||||
} else if (accountsBalance[i].isLiability) {
|
||||
totalBalance -= accountsBalance[i].balance;
|
||||
}
|
||||
} else {
|
||||
const balance = exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, defaultCurrency);
|
||||
|
||||
if (!isNumber(balance)) {
|
||||
hasUnCalculatedAmount = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (accountsBalance[i].isAsset) {
|
||||
totalBalance += Math.floor(balance);
|
||||
} else if (accountsBalance[i].isLiability) {
|
||||
totalBalance -= Math.floor(balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUnCalculatedAmount) {
|
||||
totalBalance = totalBalance + '+';
|
||||
}
|
||||
|
||||
accountCategory.displayBalance = getFormattedAmountWithCurrency(totalBalance, defaultCurrency, translateFn, userStore, settingsStore);
|
||||
} else {
|
||||
accountCategory.displayBalance = '***';
|
||||
}
|
||||
|
||||
ret.push(accountCategory);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function joinMultiText(textArray, translateFn) {
|
||||
if (!textArray || !textArray.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const separator = translateFn('format.misc.multiTextJoinSeparator');
|
||||
|
||||
return textArray.join(separator);
|
||||
}
|
||||
|
||||
function getLocalizedError(error) {
|
||||
if (error.errorCode === KnownErrorCode.ApiNotFound && SPECIFIED_API_NOT_FOUND_ERRORS[error.path]) {
|
||||
return {
|
||||
@@ -685,23 +428,15 @@ export function i18nFunctions(i18nGlobal) {
|
||||
return {
|
||||
getWeekdayShortName: (weekDay) => getWeekdayShortName(weekDay, i18nGlobal.t),
|
||||
getWeekdayLongName: (weekDay) => getWeekdayLongName(weekDay, i18nGlobal.t),
|
||||
getMultiMonthdayShortNames: (monthdays) => getMultiMonthdayShortNames(monthdays, i18nGlobal.t),
|
||||
getMultiWeekdayLongNames: (weekdayTypes, firstDayOfWeek) => getMultiWeekdayLongNames(weekdayTypes, firstDayOfWeek, i18nGlobal.t),
|
||||
formatUnixTimeToLongDateTime: (userStore, unixTime, utcOffset, currentUtcOffset) => formatUnixTime(unixTime, getI18nLongDateFormat(i18nGlobal.t, userStore.currentUserLongDateFormat) + ' ' + getI18nLongTimeFormat(i18nGlobal.t, userStore.currentUserLongTimeFormat), utcOffset, currentUtcOffset),
|
||||
formatUnixTimeToLongDate: (userStore, unixTime, utcOffset, currentUtcOffset) => formatUnixTime(unixTime, getI18nLongDateFormat(i18nGlobal.t, userStore.currentUserLongDateFormat), utcOffset, currentUtcOffset),
|
||||
formatUnixTimeToLongYear: (userStore, unixTime, utcOffset, currentUtcOffset) => formatUnixTime(unixTime, getI18nLongYearFormat(i18nGlobal.t, userStore.currentUserLongDateFormat), utcOffset, currentUtcOffset),
|
||||
formatUnixTimeToLongYearMonth: (userStore, unixTime, utcOffset, currentUtcOffset) => formatUnixTime(unixTime, getI18nLongYearMonthFormat(i18nGlobal.t, userStore.currentUserLongDateFormat), utcOffset, currentUtcOffset),
|
||||
formatUnixTimeToLongTime: (userStore, unixTime, utcOffset, currentUtcOffset) => formatUnixTime(unixTime, getI18nLongTimeFormat(i18nGlobal.t, userStore.currentUserLongTimeFormat), utcOffset, currentUtcOffset),
|
||||
formatUnixTimeToShortTime: (userStore, unixTime, utcOffset, currentUtcOffset) => formatUnixTime(unixTime, getI18nShortTimeFormat(i18nGlobal.t, userStore.currentUserShortTimeFormat), utcOffset, currentUtcOffset),
|
||||
getAllTimezones: (includeSystemDefault) => getAllTimezones(includeSystemDefault, i18nGlobal.t),
|
||||
getTimezoneDifferenceDisplayText: (utcOffset) => getTimezoneDifferenceDisplayText(utcOffset, i18nGlobal.t),
|
||||
getAllDateRanges: (scene, includeCustom, includeBillingCycle) => getAllDateRanges(scene, includeCustom, includeBillingCycle, i18nGlobal.t),
|
||||
getAllRecentMonthDateRanges: (userStore, includeAll, includeCustom) => getAllRecentMonthDateRanges(userStore, includeAll, includeCustom, i18nGlobal.t),
|
||||
getDateRangeDisplayName: (userStore, dateType, startTime, endTime) => getDateRangeDisplayName(userStore, dateType, startTime, endTime, i18nGlobal.t),
|
||||
formatAmount: (userStore, value, currencyCode) => getFormattedAmount(value, i18nGlobal.t, userStore, currencyCode),
|
||||
formatAmountWithCurrency: (settingsStore, userStore, value, currencyCode) => getFormattedAmountWithCurrency(value, currencyCode, i18nGlobal.t, userStore, settingsStore),
|
||||
getAdaptiveAmountRate: (userStore, amount1, amount2, fromExchangeRate, toExchangeRate) => getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, i18nGlobal.t, userStore),
|
||||
getAllTransactionTagFilterTypes: () => getAllTransactionTagFilterTypes(i18nGlobal.t),
|
||||
getCategorizedAccountsWithDisplayBalance: (allVisibleAccounts, showAccountBalance, defaultCurrency, settingsStore, userStore, exchangeRatesStore) => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, i18nGlobal.t)
|
||||
getAllTransactionTagFilterTypes: () => getAllTransactionTagFilterTypes(i18nGlobal.t)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,7 +86,6 @@ import { getI18nOptions } from '@/locales/helpers.ts';
|
||||
import { i18nFunctions } from '@/locales/helper.js';
|
||||
import {
|
||||
showAlert,
|
||||
showConfirm,
|
||||
showToast,
|
||||
showLoading,
|
||||
hideLoading,
|
||||
@@ -204,7 +203,6 @@ app.directive('TextareaAutoSize', TextareaAutoSize);
|
||||
app.config.globalProperties['$locale'] = i18nFunctions(i18n.global);
|
||||
|
||||
app.config.globalProperties['$alert'] = (message: string, confirmCallback: ((dialog: Dialog.Dialog, e: Event) => void) | undefined) => showAlert(message, confirmCallback, i18n.global.t);
|
||||
app.config.globalProperties['$confirm'] = (message: string, confirmCallback: (dialog: Dialog.Dialog, e: Event) => void, cancelCallback: ((dialog: Dialog.Dialog, e: Event) => void) | undefined) => showConfirm(message, confirmCallback, cancelCallback, i18n.global.t);
|
||||
app.config.globalProperties['$toast'] = (message: string, timeout: number | undefined) => showToast(message, timeout, i18n.global.t);
|
||||
app.config.globalProperties['$showLoading'] = showLoading;
|
||||
app.config.globalProperties['$hideLoading'] = hideLoading;
|
||||
|
||||
@@ -23,6 +23,18 @@ export class TransactionTemplate extends Transaction implements TransactionTempl
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
public from(other: TransactionTemplate): void {
|
||||
this.templateType = other.templateType;
|
||||
this.name = other.name;
|
||||
|
||||
if (this.templateType === TemplateType.Schedule.type) {
|
||||
this.scheduledFrequencyType = other.scheduledFrequencyType;
|
||||
this.scheduledFrequency = other.scheduledFrequency;
|
||||
this.utcOffset = other.utcOffset;
|
||||
this.timeZone = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public toTemplateCreateRequest(clientSessionId: string): TransactionTemplateCreateRequest {
|
||||
return {
|
||||
templateType: this.templateType,
|
||||
|
||||
@@ -43,7 +43,6 @@ import {
|
||||
countSplitItems
|
||||
} from '@/lib/common.ts';
|
||||
import {
|
||||
getCurrentUnixTime,
|
||||
getTimezoneOffsetMinutes,
|
||||
getBrowserTimezoneOffsetMinutes,
|
||||
getActualUnixTimeForStore,
|
||||
@@ -510,21 +509,6 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
||||
clearUserTransactionDraft();
|
||||
}
|
||||
|
||||
function generateNewTransactionModel(type: string): Transaction {
|
||||
const now: number = getCurrentUnixTime();
|
||||
const currentTimezone: string = settingsStore.appSettings.timeZone;
|
||||
|
||||
let defaultType: TransactionType = TransactionType.Expense;
|
||||
|
||||
if (type === TransactionType.Income.toString()) {
|
||||
defaultType = TransactionType.Income;
|
||||
} else if (type === TransactionType.Transfer.toString()) {
|
||||
defaultType = TransactionType.Transfer;
|
||||
}
|
||||
|
||||
return Transaction.createNewTransaction(defaultType, now, currentTimezone, getTimezoneOffsetMinutes(currentTimezone));
|
||||
}
|
||||
|
||||
function setTransactionSuitableDestinationAmount(transaction: Transaction, oldValue: number, newValue: number): void {
|
||||
if (transaction.type === TransactionType.Expense || transaction.type === TransactionType.Income) {
|
||||
transaction.destinationAmount = newValue;
|
||||
@@ -1133,7 +1117,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function uploadTransactionPicture({ pictureFile, clientSessionId }: { pictureFile: File, clientSessionId: string }): Promise<TransactionPictureInfoBasicResponse> {
|
||||
function uploadTransactionPicture({ pictureFile, clientSessionId }: { pictureFile: File, clientSessionId?: string }): Promise<TransactionPictureInfoBasicResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
services.uploadTransactionPicture({ pictureFile, clientSessionId }).then(response => {
|
||||
const data = response.data;
|
||||
@@ -1183,9 +1167,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function getTransactionPictureUrl(pictureInfo?: TransactionPictureInfoBasicResponse | null, disableBrowserCache?: boolean | string): string | null {
|
||||
function getTransactionPictureUrl(pictureInfo?: TransactionPictureInfoBasicResponse | null, disableBrowserCache?: boolean | string): string | undefined {
|
||||
if (!pictureInfo || !pictureInfo.originalUrl) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return services.getTransactionPictureUrlWithToken(pictureInfo.originalUrl, disableBrowserCache);
|
||||
@@ -1218,7 +1202,6 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
||||
isTransactionDraftModified,
|
||||
saveTransactionDraft,
|
||||
clearTransactionDraft,
|
||||
generateNewTransactionModel,
|
||||
setTransactionSuitableDestinationAmount,
|
||||
updateTransactionListInvalidState,
|
||||
resetTransactions,
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
import { ref, computed, watch } 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 { useTransactionsStore } from '@/stores/transaction.ts';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||
|
||||
import type { LocalizedTimezoneInfo } from '@/core/timezone.ts';
|
||||
import { CategoryType } from '@/core/category.ts';
|
||||
import { TransactionType } from '@/core/transaction.ts';
|
||||
import { TemplateType } from '@/core/template.ts';
|
||||
import { TRANSACTION_MAX_PICTURE_COUNT } from '@/consts/transaction.ts';
|
||||
|
||||
import { Account, type CategorizedAccountWithDisplayBalance } from '@/models/account.ts';
|
||||
import type { TransactionCategory } from '@/models/transaction_category.ts';
|
||||
import type { TransactionTag } from '@/models/transaction_tag.ts';
|
||||
import type { TransactionPictureInfoBasicResponse } from '@/models/transaction_picture_info.ts';
|
||||
import { Transaction } from '@/models/transaction.ts';
|
||||
import { TransactionTemplate } from '@/models/transaction_template.ts';
|
||||
|
||||
import {
|
||||
isArray
|
||||
} from '@/lib/common.ts';
|
||||
|
||||
import {
|
||||
getUtcOffsetByUtcOffsetMinutes,
|
||||
getTimezoneOffsetMinutes,
|
||||
getCurrentUnixTime
|
||||
} from '@/lib/datetime.ts';
|
||||
|
||||
import {
|
||||
getFirstAvailableCategoryId
|
||||
} from '@/lib/category.ts';
|
||||
|
||||
export enum TransactionEditPageType {
|
||||
Transaction = 'transaction',
|
||||
Template = 'template'
|
||||
}
|
||||
|
||||
export enum TransactionEditPageMode {
|
||||
Add = 'add',
|
||||
Edit = 'edit',
|
||||
View = 'view'
|
||||
}
|
||||
|
||||
export enum GeoLocationStatus {
|
||||
Getting = 'getting',
|
||||
Success = 'success',
|
||||
Error = 'error'
|
||||
}
|
||||
|
||||
export function useTransactionEditPageBase(type: TransactionEditPageType, initMode?: TransactionEditPageMode, transactionDefaultType?: number) {
|
||||
const {
|
||||
tt,
|
||||
getAllTimezones,
|
||||
getTimezoneDifferenceDisplayText,
|
||||
formatAmountWithCurrency,
|
||||
getAdaptiveAmountRate,
|
||||
getCategorizedAccountsWithDisplayBalance
|
||||
} = useI18n();
|
||||
|
||||
const settingsStore = useSettingsStore();
|
||||
const userStore = useUserStore();
|
||||
const accountsStore = useAccountsStore();
|
||||
const transactionCategoriesStore = useTransactionCategoriesStore();
|
||||
const transactionTagsStore = useTransactionTagsStore();
|
||||
const transactionsStore = useTransactionsStore();
|
||||
const exchangeRatesStore = useExchangeRatesStore();
|
||||
|
||||
const isSupportGeoLocation: boolean = !!navigator.geolocation;
|
||||
|
||||
const mode = ref<TransactionEditPageMode>(initMode ?? TransactionEditPageMode.Add);
|
||||
const editId = ref<string | null>(null);
|
||||
const addByTemplateId = ref<string | null>(null);
|
||||
const duplicateFromId = ref<string | null>(null);
|
||||
|
||||
const clientSessionId = ref<string>('');
|
||||
const loading = ref<boolean>(true);
|
||||
const submitting = ref<boolean>(false);
|
||||
const uploadingPicture = ref<boolean>(false);
|
||||
const geoLocationStatus = ref<GeoLocationStatus | null>(null);
|
||||
|
||||
const transaction = ref<Transaction | TransactionTemplate>(createNewTransactionModel(transactionDefaultType));
|
||||
|
||||
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
|
||||
const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.showAccountBalance);
|
||||
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
|
||||
const defaultAccountId = computed<string>(() => userStore.currentUserDefaultAccountId);
|
||||
const firstDayOfWeek = computed<number>(() => userStore.currentUserFirstDayOfWeek);
|
||||
|
||||
const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(true));
|
||||
const allAccounts = computed<Account[]>(() => accountsStore.allPlainAccounts);
|
||||
const allVisibleAccounts = computed<Account[]>(() => accountsStore.allVisiblePlainAccounts);
|
||||
const allAccountsMap = computed<Record<string, Account>>(() => accountsStore.allAccountsMap);
|
||||
const allVisibleCategorizedAccounts = computed<CategorizedAccountWithDisplayBalance[]>(() => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts.value, showAccountBalance.value));
|
||||
const allCategories = computed<Record<number, TransactionCategory[]>>(() => transactionCategoriesStore.allTransactionCategories);
|
||||
const allCategoriesMap = computed<Record<string, TransactionCategory>>(() => transactionCategoriesStore.allTransactionCategoriesMap);
|
||||
const allTags = computed<TransactionTag[]>(() => transactionTagsStore.allTransactionTags);
|
||||
const allTagsMap = computed<Record<string, TransactionTag>>(() => transactionTagsStore.allTransactionTagsMap);
|
||||
|
||||
const canAddTransactionPicture = computed<boolean>(() => {
|
||||
if (type !== TransactionEditPageType.Transaction || (mode.value !== TransactionEditPageMode.Add && mode.value !== TransactionEditPageMode.Edit)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !isArray(transaction.value.pictures) || transaction.value.pictures.length < TRANSACTION_MAX_PICTURE_COUNT;
|
||||
});
|
||||
|
||||
const title = computed<string>(() => {
|
||||
if (type === TransactionEditPageType.Transaction) {
|
||||
if (mode.value === TransactionEditPageMode.Add) {
|
||||
return 'Add Transaction';
|
||||
} else if (mode.value === TransactionEditPageMode.Edit) {
|
||||
return 'Edit Transaction';
|
||||
} else {
|
||||
return 'Transaction Detail';
|
||||
}
|
||||
} else if (type === TransactionEditPageType.Template && (transaction.value as TransactionTemplate).templateType === TemplateType.Normal.type) {
|
||||
if (mode.value === TransactionEditPageMode.Add) {
|
||||
return 'Add Transaction Template';
|
||||
} else if (mode.value === TransactionEditPageMode.Edit) {
|
||||
return 'Edit Transaction Template';
|
||||
}
|
||||
} else if (type === TransactionEditPageType.Template && (transaction.value as TransactionTemplate).templateType === TemplateType.Schedule.type) {
|
||||
if (mode.value === TransactionEditPageMode.Add) {
|
||||
return 'Add Scheduled Transaction';
|
||||
} else if (mode.value === TransactionEditPageMode.Edit) {
|
||||
return 'Edit Scheduled Transaction';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
const saveButtonTitle = computed<string>(() => {
|
||||
if (mode.value === TransactionEditPageMode.Add) {
|
||||
return 'Add';
|
||||
} else {
|
||||
return 'Save';
|
||||
}
|
||||
});
|
||||
|
||||
const cancelButtonTitle = computed<string>(() => {
|
||||
if (mode.value === TransactionEditPageMode.View) {
|
||||
return 'Close';
|
||||
} else {
|
||||
return 'Cancel';
|
||||
}
|
||||
});
|
||||
|
||||
const sourceAmountName = computed<string>(() => {
|
||||
if (transaction.value.type === TransactionType.Expense) {
|
||||
return 'Expense Amount';
|
||||
} else if (transaction.value.type === TransactionType.Income) {
|
||||
return 'Income Amount';
|
||||
} else if (transaction.value.type === TransactionType.Transfer) {
|
||||
return 'Transfer Out Amount';
|
||||
} else {
|
||||
return 'Amount';
|
||||
}
|
||||
});
|
||||
|
||||
const sourceAccountTitle = computed<string>(() => {
|
||||
if (transaction.value.type === TransactionType.Expense || transaction.value.type === TransactionType.Income) {
|
||||
return 'Account';
|
||||
} else if (transaction.value.type === TransactionType.Transfer) {
|
||||
return 'Source Account';
|
||||
} else {
|
||||
return 'Account';
|
||||
}
|
||||
});
|
||||
|
||||
const transferInAmountTitle = computed<string>(() => {
|
||||
const sourceAccount = allAccountsMap.value[transaction.value.sourceAccountId];
|
||||
const destinationAccount = allAccountsMap.value[transaction.value.destinationAccountId];
|
||||
|
||||
if (!sourceAccount || !destinationAccount || sourceAccount.currency === destinationAccount.currency) {
|
||||
return tt('Transfer In Amount');
|
||||
}
|
||||
|
||||
const fromExchangeRate = exchangeRatesStore.latestExchangeRateMap[sourceAccount.currency];
|
||||
const toExchangeRate = exchangeRatesStore.latestExchangeRateMap[destinationAccount.currency];
|
||||
const amountRate = getAdaptiveAmountRate(transaction.value.sourceAmount, transaction.value.destinationAmount, fromExchangeRate, toExchangeRate);
|
||||
|
||||
if (!amountRate) {
|
||||
return tt('Transfer In Amount');
|
||||
}
|
||||
|
||||
return tt('Transfer In Amount') + ` (${amountRate})`;
|
||||
});
|
||||
|
||||
const hasAvailableExpenseCategories = computed<boolean>(() => {
|
||||
if (!allCategories.value || !allCategories.value[CategoryType.Expense] || !allCategories.value[CategoryType.Expense].length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstAvailableCategoryId = getFirstAvailableCategoryId(allCategories.value[CategoryType.Expense]);
|
||||
return firstAvailableCategoryId !== '';
|
||||
});
|
||||
|
||||
const hasAvailableIncomeCategories = computed<boolean>(() => {
|
||||
if (!allCategories.value || !allCategories.value[CategoryType.Income] || !allCategories.value[CategoryType.Income].length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstAvailableCategoryId = getFirstAvailableCategoryId(allCategories.value[CategoryType.Income]);
|
||||
return firstAvailableCategoryId !== '';
|
||||
});
|
||||
|
||||
const hasAvailableTransferCategories = computed<boolean>(() => {
|
||||
if (!allCategories.value || !allCategories.value[CategoryType.Transfer] || !allCategories.value[CategoryType.Transfer].length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstAvailableCategoryId = getFirstAvailableCategoryId(allCategories.value[CategoryType.Transfer]);
|
||||
return firstAvailableCategoryId !== '';
|
||||
});
|
||||
|
||||
const sourceAccountName = computed<string>(() => {
|
||||
if (transaction.value.sourceAccountId) {
|
||||
return Account.findAccountNameById(allAccounts.value, transaction.value.sourceAccountId) || '';
|
||||
} else {
|
||||
return tt('None');
|
||||
}
|
||||
});
|
||||
|
||||
const destinationAccountName = computed<string>(() => {
|
||||
if (transaction.value.destinationAccountId) {
|
||||
return Account.findAccountNameById(allAccounts.value, transaction.value.destinationAccountId) || '';
|
||||
} else {
|
||||
return tt('None');
|
||||
}
|
||||
});
|
||||
|
||||
const sourceAccountCurrency = computed<string>(() => {
|
||||
const sourceAccount = allAccountsMap.value[transaction.value.sourceAccountId];
|
||||
|
||||
if (sourceAccount) {
|
||||
return sourceAccount.currency;
|
||||
}
|
||||
|
||||
return defaultCurrency.value;
|
||||
});
|
||||
|
||||
const destinationAccountCurrency = computed<string>(() => {
|
||||
const destinationAccount = allAccountsMap.value[transaction.value.destinationAccountId];
|
||||
|
||||
if (destinationAccount) {
|
||||
return destinationAccount.currency;
|
||||
}
|
||||
|
||||
return defaultCurrency.value;
|
||||
});
|
||||
|
||||
const transactionDisplayTimezone = computed<string>(() => {
|
||||
return `UTC${getUtcOffsetByUtcOffsetMinutes(transaction.value.utcOffset)}`;
|
||||
});
|
||||
|
||||
const transactionTimezoneTimeDifference = computed<string>(() => {
|
||||
return getTimezoneDifferenceDisplayText(transaction.value.utcOffset);
|
||||
});
|
||||
|
||||
const geoLocationStatusInfo = computed<string>(() => {
|
||||
if (geoLocationStatus.value === GeoLocationStatus.Success) {
|
||||
return '';
|
||||
} else if (geoLocationStatus.value === GeoLocationStatus.Getting) {
|
||||
return tt('Getting Location...');
|
||||
} else {
|
||||
return tt('No Location');
|
||||
}
|
||||
});
|
||||
|
||||
const inputEmptyProblemMessage = computed<string | null>(() => {
|
||||
if (transaction.value.type === TransactionType.Expense) {
|
||||
if (!transaction.value.expenseCategoryId || transaction.value.expenseCategoryId === '') {
|
||||
return 'Transaction category cannot be blank';
|
||||
}
|
||||
|
||||
if (!transaction.value.sourceAccountId || transaction.value.sourceAccountId === '') {
|
||||
return 'Transaction account cannot be blank';
|
||||
}
|
||||
} else if (transaction.value.type === TransactionType.Income) {
|
||||
if (!transaction.value.incomeCategoryId || transaction.value.incomeCategoryId === '') {
|
||||
return 'Transaction category cannot be blank';
|
||||
}
|
||||
|
||||
if (!transaction.value.sourceAccountId || transaction.value.sourceAccountId === '') {
|
||||
return 'Transaction account cannot be blank';
|
||||
}
|
||||
} else if (transaction.value.type === TransactionType.Transfer) {
|
||||
if (!transaction.value.transferCategoryId || transaction.value.transferCategoryId === '') {
|
||||
return 'Transaction category cannot be blank';
|
||||
}
|
||||
|
||||
if (!transaction.value.sourceAccountId || transaction.value.sourceAccountId === '') {
|
||||
return 'Source account cannot be blank';
|
||||
}
|
||||
|
||||
if (!transaction.value.destinationAccountId || transaction.value.destinationAccountId === '') {
|
||||
return 'Destination account cannot be blank';
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'template' && transaction.value instanceof TransactionTemplate) {
|
||||
if (!transaction.value.name) {
|
||||
return 'Template name cannot be blank';
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
const inputIsEmpty = computed<boolean>(() => {
|
||||
return !!inputEmptyProblemMessage.value;
|
||||
});
|
||||
|
||||
function createNewTransactionModel(transactionType?: number): Transaction | TransactionTemplate {
|
||||
const now: number = getCurrentUnixTime();
|
||||
const currentTimezone: string = settingsStore.appSettings.timeZone;
|
||||
|
||||
let defaultType: TransactionType = TransactionType.Expense;
|
||||
|
||||
if (transactionType === TransactionType.Income) {
|
||||
defaultType = TransactionType.Income;
|
||||
} else if (transactionType === TransactionType.Transfer) {
|
||||
defaultType = TransactionType.Transfer;
|
||||
}
|
||||
|
||||
let newTransaction: Transaction | TransactionTemplate = Transaction.createNewTransaction(defaultType, now, currentTimezone, getTimezoneOffsetMinutes(currentTimezone));
|
||||
|
||||
if (type === TransactionEditPageType.Template) {
|
||||
newTransaction = TransactionTemplate.createNewTransactionTemplate(newTransaction);
|
||||
}
|
||||
|
||||
return newTransaction;
|
||||
}
|
||||
|
||||
function swapTransactionData(swapAccount: boolean, swapAmount: boolean): void {
|
||||
if (swapAccount) {
|
||||
const oldSourceAccountId = transaction.value.sourceAccountId;
|
||||
transaction.value.sourceAccountId = transaction.value.destinationAccountId;
|
||||
transaction.value.destinationAccountId = oldSourceAccountId;
|
||||
}
|
||||
|
||||
if (swapAmount) {
|
||||
const oldSourceAmount = transaction.value.sourceAmount;
|
||||
transaction.value.sourceAmount = transaction.value.destinationAmount;
|
||||
transaction.value.destinationAmount = oldSourceAmount;
|
||||
}
|
||||
}
|
||||
|
||||
function getDisplayAmount(amount: number | string, hideAmount: boolean, currencyCode: string): string {
|
||||
if (hideAmount) {
|
||||
return formatAmountWithCurrency('***', currencyCode);
|
||||
}
|
||||
|
||||
return formatAmountWithCurrency(amount, currencyCode);
|
||||
}
|
||||
|
||||
function getTransactionPictureUrl(pictureInfo?: TransactionPictureInfoBasicResponse | null): string | undefined {
|
||||
return transactionsStore.getTransactionPictureUrl(pictureInfo);
|
||||
}
|
||||
|
||||
watch(() => transaction.value.sourceAmount, (newValue, oldValue) => {
|
||||
if (mode.value === TransactionEditPageMode.View || loading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
transactionsStore.setTransactionSuitableDestinationAmount(transaction.value, oldValue, newValue);
|
||||
});
|
||||
|
||||
watch(() => transaction.value.destinationAmount, (newValue) => {
|
||||
if (mode.value === TransactionEditPageMode.View || loading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (transaction.value.type === TransactionType.Expense || transaction.value.type === TransactionType.Income) {
|
||||
transaction.value.sourceAmount = newValue;
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => transaction.value.timeZone, (newValue) => {
|
||||
for (let i = 0; i < allTimezones.value.length; i++) {
|
||||
if (allTimezones.value[i].name === newValue) {
|
||||
transaction.value.utcOffset = allTimezones.value[i].utcOffsetMinutes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
// constants
|
||||
isSupportGeoLocation,
|
||||
// states
|
||||
mode,
|
||||
editId,
|
||||
addByTemplateId,
|
||||
duplicateFromId,
|
||||
clientSessionId,
|
||||
loading,
|
||||
submitting,
|
||||
uploadingPicture,
|
||||
geoLocationStatus,
|
||||
transaction,
|
||||
// computed states
|
||||
currentTimezoneOffsetMinutes,
|
||||
showAccountBalance,
|
||||
defaultCurrency,
|
||||
firstDayOfWeek,
|
||||
defaultAccountId,
|
||||
allTimezones,
|
||||
allAccounts,
|
||||
allVisibleAccounts,
|
||||
allAccountsMap,
|
||||
allVisibleCategorizedAccounts,
|
||||
allCategories,
|
||||
allCategoriesMap,
|
||||
allTags,
|
||||
allTagsMap,
|
||||
canAddTransactionPicture,
|
||||
title,
|
||||
saveButtonTitle,
|
||||
cancelButtonTitle,
|
||||
sourceAmountName,
|
||||
sourceAccountTitle,
|
||||
transferInAmountTitle,
|
||||
hasAvailableExpenseCategories,
|
||||
hasAvailableIncomeCategories,
|
||||
hasAvailableTransferCategories,
|
||||
sourceAccountName,
|
||||
destinationAccountName,
|
||||
sourceAccountCurrency,
|
||||
destinationAccountCurrency,
|
||||
transactionDisplayTimezone,
|
||||
transactionTimezoneTimeDifference,
|
||||
geoLocationStatusInfo,
|
||||
inputEmptyProblemMessage,
|
||||
inputIsEmpty,
|
||||
// functions
|
||||
createNewTransactionModel,
|
||||
swapTransactionData,
|
||||
getDisplayAmount,
|
||||
getTransactionPictureUrl
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<edit-dialog ref="editDialog" type="template" :persistent="true" />
|
||||
<edit-dialog ref="editDialog" :type="TransactionEditPageType.Template" :persistent="true" />
|
||||
|
||||
<confirm-dialog ref="confirmDialog"/>
|
||||
<snack-bar ref="snackbar" />
|
||||
@@ -149,6 +149,7 @@
|
||||
import ConfirmDialog from '@/components/desktop/ConfirmDialog.vue';
|
||||
import SnackBar from '@/components/desktop/SnackBar.vue';
|
||||
import EditDialog from '@/views/desktop/transactions/list/dialogs/EditDialog.vue';
|
||||
import { TransactionEditPageType } from '@/views/base/transactions/TransactionEditPageBase.ts';
|
||||
|
||||
import { ref, computed, useTemplateRef } from 'vue';
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user