diff --git a/src/core/datetime.ts b/src/core/datetime.ts index a8d09e94..f0c96161 100644 --- a/src/core/datetime.ts +++ b/src/core/datetime.ts @@ -62,6 +62,12 @@ export interface LocalizedMeridiemIndicator { readonly displayValues: string[]; } +export interface LocalizedDateTimeFormat extends TypeAndDisplayName { + readonly type: number; + readonly format: string; + readonly displayName: string; +} + export interface LocalizedDateRange extends TypeAndDisplayName { readonly type: number; readonly displayName: string; diff --git a/src/locales/helper.js b/src/locales/helper.js index d001b953..e98040a2 100644 --- a/src/locales/helper.js +++ b/src/locales/helper.js @@ -2,11 +2,10 @@ import moment from 'moment-timezone'; import { DEFAULT_LANGUAGE, ALL_LANGUAGES } from '@/locales/index.ts'; -import { Month, WeekDay, MeridiemIndicator, LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat, DateRange, LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE } from '@/core/datetime.ts'; +import { Month, WeekDay, MeridiemIndicator, LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat, DateRange } from '@/core/datetime.ts'; import { TimezoneTypeForStatistics } from '@/core/timezone.ts'; import { DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts'; -import { CurrencyDisplayType, CurrencySortingType } from '@/core/currency.ts'; -import { PresetAmountColor } from '@/core/color.ts'; +import { CurrencyDisplayType, CurrencySortingType } from '@/core/currency.ts' import { AccountType, AccountCategory } from '@/core/account.ts'; import { CategoryType } from '@/core/category.ts'; import { TransactionEditScopeType, TransactionTagFilterType } from '@/core/transaction.ts'; @@ -30,7 +29,6 @@ import { isPM, parseDateFromUnixTime, formatUnixTime, - formatCurrentTime, getYear, getTimezoneOffset, getTimezoneOffsetMinutes, @@ -67,42 +65,6 @@ function getLanguageDisplayName(translateFn, languageName) { return translateFn(`language.${languageName}`); } -function getAllLanguageInfoArray(translateFn, includeSystemDefault) { - const ret = []; - - for (const languageTag in ALL_LANGUAGES) { - if (!Object.prototype.hasOwnProperty.call(ALL_LANGUAGES, languageTag)) { - continue; - } - - const languageInfo = ALL_LANGUAGES[languageTag]; - let displayName = languageInfo.displayName; - let languageNameInCurrentLanguage = getLanguageDisplayName(translateFn, languageInfo.name); - - if (languageNameInCurrentLanguage && languageNameInCurrentLanguage !== displayName) { - displayName = `${languageNameInCurrentLanguage} (${displayName})`; - } - - ret.push({ - languageTag: languageTag, - displayName: displayName - }); - } - - ret.sort(function (lang1, lang2) { - return lang1.languageTag.localeCompare(lang2.languageTag); - }); - - if (includeSystemDefault) { - ret.splice(0, 0, { - languageTag: '', - displayName: translateFn('System Default') - }); - } - - return ret; -} - function getLanguageInfo(locale) { return ALL_LANGUAGES[locale]; } @@ -302,26 +264,6 @@ function getAllMinWeekdayNames(translateFn) { return ret; } -function getAllLongDateFormats(translateFn) { - const defaultLongDateFormatTypeName = translateFn('default.longDateFormat'); - return getDateTimeFormats(translateFn, LongDateFormat.all(), LongDateFormat.values(), 'format.longDate', defaultLongDateFormatTypeName, LongDateFormat.Default); -} - -function getAllShortDateFormats(translateFn) { - const defaultShortDateFormatTypeName = translateFn('default.shortDateFormat'); - return getDateTimeFormats(translateFn, ShortDateFormat.all(), ShortDateFormat.values(), 'format.shortDate', defaultShortDateFormatTypeName, ShortDateFormat.Default); -} - -function getAllLongTimeFormats(translateFn) { - const defaultLongTimeFormatTypeName = translateFn('default.longTimeFormat'); - return getDateTimeFormats(translateFn, LongTimeFormat.all(), LongTimeFormat.values(), 'format.longTime', defaultLongTimeFormatTypeName, LongTimeFormat.Default); -} - -function getAllShortTimeFormats(translateFn) { - const defaultShortTimeFormatTypeName = translateFn('default.shortTimeFormat'); - return getDateTimeFormats(translateFn, ShortTimeFormat.all(), ShortTimeFormat.values(), 'format.shortTime', defaultShortTimeFormatTypeName, ShortTimeFormat.Default); -} - function getMonthdayOrdinal(monthDay, translateFn) { return translateFn(`datetime.monthDayOrdinal.${monthDay}`); } @@ -445,31 +387,6 @@ function formatYearQuarter(translateFn, year, quarter) { } } -function getDateTimeFormats(translateFn, allFormatMap, allFormatArray, localeFormatPathPrefix, localeDefaultFormatTypeName, systemDefaultFormatType) { - const defaultFormat = getDateTimeFormat(translateFn, allFormatMap, allFormatArray, - localeFormatPathPrefix, localeDefaultFormatTypeName, systemDefaultFormatType, LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE); - const ret = []; - - ret.push({ - type: LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE, - format: defaultFormat, - displayName: `${translateFn('Language Default')} (${formatCurrentTime(defaultFormat)})` - }); - - for (let i = 0; i < allFormatArray.length; i++) { - const formatType = allFormatArray[i]; - const format = translateFn(`${localeFormatPathPrefix}.${formatType.key}`); - - ret.push({ - type: formatType.type, - format: format, - displayName: formatCurrentTime(format) - }); - } - - return ret; -} - function getDateTimeFormat(translateFn, allFormatMap, allFormatArray, localeFormatPathPrefix, localeDefaultFormatTypeName, systemDefaultFormatType, formatTypeValue) { const type = getDateTimeFormatType(allFormatMap, allFormatArray, formatTypeValue, localeDefaultFormatTypeName, systemDefaultFormatType); return translateFn(`${localeFormatPathPrefix}.${type.key}`); @@ -974,39 +891,6 @@ function getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRat return getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, numberFormatOptions); } -function getAllExpenseIncomeAmountColors(translateFn, expenseOrIncome) { - const ret = []; - let defaultAmountName = ''; - - if (expenseOrIncome === 1) { // expense - defaultAmountName = PresetAmountColor.DefaultExpenseColor.name; - } else if (expenseOrIncome === 2) { // income - defaultAmountName = PresetAmountColor.DefaultIncomeColor.name; - } - - if (defaultAmountName) { - defaultAmountName = translateFn('color.amount.' + defaultAmountName); - } - - ret.push({ - type: PresetAmountColor.SystemDefaultType, - displayName: translateFn('System Default') + (defaultAmountName ? ` (${defaultAmountName})` : '') - }); - - const allPresetAmountColors = PresetAmountColor.values(); - - for (let i = 0; i < allPresetAmountColors.length; i++) { - const amountColor = allPresetAmountColors[i]; - - ret.push({ - type: amountColor.type, - displayName: translateFn('color.amount.' + amountColor.name) - }); - } - - return ret; -} - function getAllAccountCategories(translateFn) { const ret = []; const allCategories = AccountCategory.values(); @@ -1373,14 +1257,9 @@ export function translateError(message, translateFn) { export function i18nFunctions(i18nGlobal) { return { - getAllLanguageInfoArray: (includeSystemDefault) => getAllLanguageInfoArray(i18nGlobal.t, includeSystemDefault), getDefaultCurrency: () => getDefaultCurrency(i18nGlobal.t), getDefaultFirstDayOfWeek: () => getDefaultFirstDayOfWeek(i18nGlobal.t), getCurrencyName: (currencyCode) => getCurrencyName(currencyCode, i18nGlobal.t), - getAllLongDateFormats: () => getAllLongDateFormats(i18nGlobal.t), - getAllShortDateFormats: () => getAllShortDateFormats(i18nGlobal.t), - getAllLongTimeFormats: () => getAllLongTimeFormats(i18nGlobal.t), - getAllShortTimeFormats: () => getAllShortTimeFormats(i18nGlobal.t), getMonthdayShortName: (monthDay) => getMonthdayShortName(monthDay, i18nGlobal.t), getWeekdayShortName: (weekDay) => getWeekdayShortName(weekDay, i18nGlobal.t), getWeekdayLongName: (weekDay) => getWeekdayLongName(weekDay, i18nGlobal.t), @@ -1420,8 +1299,6 @@ export function i18nFunctions(i18nGlobal) { 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), - getAllExpenseAmountColors: () => getAllExpenseIncomeAmountColors(i18nGlobal.t, 1), - getAllIncomeAmountColors: () => getAllExpenseIncomeAmountColors(i18nGlobal.t, 2), getAllAccountCategories: () => getAllAccountCategories(i18nGlobal.t), getAllAccountTypes: () => getAllAccountTypes(i18nGlobal.t), getAllCategoricalChartTypes: () => getAllCategoricalChartTypes(i18nGlobal.t), diff --git a/src/locales/helpers.ts b/src/locales/helpers.ts index 64afa0eb..7c7b71f8 100644 --- a/src/locales/helpers.ts +++ b/src/locales/helpers.ts @@ -9,6 +9,7 @@ import { type DateFormat, type TimeFormat, type LocalizedMeridiemIndicator, + type LocalizedDateTimeFormat, type LocalizedDateRange, type LocalizedRecentMonthDateRange, Month, @@ -19,7 +20,8 @@ import { LongTimeFormat, ShortTimeFormat, DateRange, - DateRangeScene + DateRangeScene, + LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE } from '@/core/datetime.ts'; import { @@ -44,6 +46,10 @@ import { CurrencySortingType } from '@/core/currency.ts'; +import { + PresetAmountColor +} from '@/core/color.ts'; + import { type LocalizedAccountCategory, AccountType, @@ -98,6 +104,7 @@ import { import { isPM, formatUnixTime, + formatCurrentTime, getTimezoneOffset, getTimezoneOffsetMinutes, getBrowserTimezoneOffset, @@ -706,6 +713,30 @@ export function useI18n() { return ret; } + function getLocalizedDateTimeFormats(type: string, allFormatMap: Record, allFormatArray: T[], languageDefaultTypeNameKey: string, systemDefaultFormatType: T): LocalizedDateTimeFormat[] { + const defaultFormat = getLocalizedDateTimeFormat(type, allFormatMap, allFormatArray, LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE, languageDefaultTypeNameKey, systemDefaultFormatType); + const ret: LocalizedDateTimeFormat[] = []; + + ret.push({ + type: LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE, + format: defaultFormat, + displayName: `${t('Language Default')} (${formatCurrentTime(defaultFormat)})` + }); + + for (let i = 0; i < allFormatArray.length; i++) { + const formatType = allFormatArray[i]; + const format = t(`format.${type}.${formatType.key}`); + + ret.push({ + type: formatType.type, + format: format, + displayName: formatCurrentTime(format) + }); + } + + return ret; + } + function getAllDateRanges(scene: DateRangeScene, includeCustom?: boolean, includeBillingCycle?: boolean): LocalizedDateRange[] { const ret: LocalizedDateRange[] = []; const allDateRanges = DateRange.values(); @@ -869,6 +900,39 @@ export function useI18n() { return ret; } + function getAllExpenseIncomeAmountColors(categoryType: CategoryType): TypeAndDisplayName[] { + const ret: TypeAndDisplayName[] = []; + let defaultAmountName = ''; + + if (categoryType === CategoryType.Expense) { + defaultAmountName = PresetAmountColor.DefaultExpenseColor.name; + } else if (categoryType === CategoryType.Income) { // income + defaultAmountName = PresetAmountColor.DefaultIncomeColor.name; + } + + if (defaultAmountName) { + defaultAmountName = t('color.amount.' + defaultAmountName); + } + + ret.push({ + type: PresetAmountColor.SystemDefaultType, + displayName: t('System Default') + (defaultAmountName ? ` (${defaultAmountName})` : '') + }); + + const allPresetAmountColors = PresetAmountColor.values(); + + for (let i = 0; i < allPresetAmountColors.length; i++) { + const amountColor = allPresetAmountColors[i]; + + ret.push({ + type: amountColor.type, + displayName: t('color.amount.' + amountColor.name) + }); + } + + return ret; + } + function getAllAccountCategories(): LocalizedAccountCategory[] { const ret: LocalizedAccountCategory[] = []; const allCategories = AccountCategory.values(); @@ -1359,6 +1423,10 @@ export function useI18n() { getAllShortWeekdayNames, getAllMinWeekdayNames, getAllWeekDays, + getAllLongDateFormats: () => getLocalizedDateTimeFormats('longDate', LongDateFormat.all(), LongDateFormat.values(), 'longDateFormat', LongDateFormat.Default), + getAllShortDateFormats: () => getLocalizedDateTimeFormats('shortDate', ShortDateFormat.all(), ShortDateFormat.values(), 'shortDateFormat', ShortDateFormat.Default), + getAllLongTimeFormats: () => getLocalizedDateTimeFormats('longTime', LongTimeFormat.all(), LongTimeFormat.values(), 'longTimeFormat', LongTimeFormat.Default), + getAllShortTimeFormats: () => getLocalizedDateTimeFormats('shortTime', ShortTimeFormat.all(), ShortTimeFormat.values(), 'shortTimeFormat', ShortTimeFormat.Default), getAllDateRanges, getAllRecentMonthDateRanges, getAllTimezones, @@ -1368,6 +1436,8 @@ export function useI18n() { getAllDigitGroupingTypes, getAllCurrencyDisplayTypes, getAllCurrencySortingTypes: () => getLocalizedDisplayNameAndType(CurrencySortingType.values()), + getAllExpenseAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Expense), + getAllIncomeAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Income), getAllAccountCategories, getAllAccountTypes: () => getLocalizedDisplayNameAndType(AccountType.values()), getAllCategoricalChartTypes: () => getLocalizedDisplayNameAndType(CategoricalChartType.values()), diff --git a/src/models/account.ts b/src/models/account.ts index a7c332e8..262215f0 100644 --- a/src/models/account.ts +++ b/src/models/account.ts @@ -215,6 +215,16 @@ export class Account implements AccountInfoResponse { return accounts; } + + public static findAccountNameById(accounts: Account[], accountId: string, defaultName?: string): string | undefined { + for (const account of accounts) { + if (account.id === accountId) { + return account.name; + } + } + + return defaultName; + } } export interface AccountCreateRequest { diff --git a/src/models/user.ts b/src/models/user.ts index e172eae8..0cf770ef 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -15,18 +15,18 @@ export class User { public defaultCurrency: string; public firstDayOfWeek: number; - public defaultAccountId?: string; - public transactionEditScope?: number; - public longDateFormat?: number; - public shortDateFormat?: number; - public longTimeFormat?: number; - public shortTimeFormat?: number; - public decimalSeparator?: number; - public digitGroupingSymbol?: number; - public digitGrouping?: number; - public currencyDisplayType?: number; - public expenseAmountColor?: number; - public incomeAmountColor?: number; + public defaultAccountId: string = ''; + public transactionEditScope: number = 1; + public longDateFormat: number = 0; + public shortDateFormat: number = 0; + public longTimeFormat: number = 0; + public shortTimeFormat: number = 0; + public decimalSeparator: number = 0; + public digitGroupingSymbol: number = 0; + public digitGrouping: number = 0; + public currencyDisplayType: number = 0; + public expenseAmountColor: number = 0; + public incomeAmountColor: number = 0; private constructor(language: string, defaultCurrency: string, firstDayOfWeek: number) { this.language = language; @@ -34,6 +34,27 @@ export class User { this.firstDayOfWeek = firstDayOfWeek; } + public from(user: User | UserBasicInfo | UserProfileResponse): void { + this.username = user.username; + this.email = user.email; + this.nickname = user.nickname; + this.language = user.language; + this.defaultCurrency = user.defaultCurrency; + this.firstDayOfWeek = user.firstDayOfWeek; + this.defaultAccountId = user.defaultAccountId; + this.transactionEditScope = user.transactionEditScope; + this.longDateFormat = user.longDateFormat; + this.shortDateFormat = user.shortDateFormat; + this.longTimeFormat = user.longTimeFormat; + this.shortTimeFormat = user.shortTimeFormat; + this.decimalSeparator = user.decimalSeparator; + this.digitGroupingSymbol = user.digitGroupingSymbol; + this.digitGrouping = user.digitGrouping; + this.currencyDisplayType = user.currencyDisplayType; + this.expenseAmountColor = user.expenseAmountColor; + this.incomeAmountColor = user.incomeAmountColor; + } + public toRegisterRequest(categories?: LocalizedPresetCategory[]): UserRegisterRequest { return { username: this.username, @@ -71,20 +92,20 @@ export class User { }; } - public static of(profileResponse: UserProfileResponse): User { - const user = new User(profileResponse.language, profileResponse.defaultCurrency, profileResponse.firstDayOfWeek); - user.defaultAccountId = profileResponse.defaultAccountId; - user.transactionEditScope = profileResponse.transactionEditScope; - user.longDateFormat = profileResponse.longDateFormat; - user.shortDateFormat = profileResponse.shortDateFormat; - user.longTimeFormat = profileResponse.longTimeFormat; - user.shortTimeFormat = profileResponse.shortTimeFormat; - user.decimalSeparator = profileResponse.decimalSeparator; - user.digitGroupingSymbol = profileResponse.digitGroupingSymbol; - user.digitGrouping = profileResponse.digitGrouping; - user.currencyDisplayType = profileResponse.currencyDisplayType; - user.expenseAmountColor = profileResponse.expenseAmountColor; - user.incomeAmountColor = profileResponse.incomeAmountColor; + public static of(userInfo: UserBasicInfo): User { + const user = new User(userInfo.language, userInfo.defaultCurrency, userInfo.firstDayOfWeek); + user.defaultAccountId = userInfo.defaultAccountId; + user.transactionEditScope = userInfo.transactionEditScope; + user.longDateFormat = userInfo.longDateFormat; + user.shortDateFormat = userInfo.shortDateFormat; + user.longTimeFormat = userInfo.longTimeFormat; + user.shortTimeFormat = userInfo.shortTimeFormat; + user.decimalSeparator = userInfo.decimalSeparator; + user.digitGroupingSymbol = userInfo.digitGroupingSymbol; + user.digitGrouping = userInfo.digitGrouping; + user.currencyDisplayType = userInfo.currencyDisplayType; + user.expenseAmountColor = userInfo.expenseAmountColor; + user.incomeAmountColor = userInfo.incomeAmountColor; return user; } diff --git a/src/stores/index.ts b/src/stores/index.ts index e5dffd86..cf9e7fdb 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -372,27 +372,7 @@ export const useRootStore = defineStore('root', () => { function updateUserProfile({ profile, currentPassword }: { profile: User, currentPassword?: string }): Promise { return new Promise((resolve, reject) => { - services.updateProfile({ - password: profile.password, - oldPassword: currentPassword, - email: profile.email, - nickname: profile.nickname, - defaultAccountId: profile.defaultAccountId, - transactionEditScope: profile.transactionEditScope, - language: profile.language, - defaultCurrency: profile.defaultCurrency, - firstDayOfWeek: profile.firstDayOfWeek, - longDateFormat: profile.longDateFormat, - shortDateFormat: profile.shortDateFormat, - longTimeFormat: profile.longTimeFormat, - shortTimeFormat: profile.shortTimeFormat, - decimalSeparator: profile.decimalSeparator, - digitGroupingSymbol: profile.digitGroupingSymbol, - digitGrouping: profile.digitGrouping, - currencyDisplayType: profile.currencyDisplayType, - expenseAmountColor: profile.expenseAmountColor, - incomeAmountColor: profile.incomeAmountColor - }).then(response => { + services.updateProfile(profile.toProfileUpdateRequest(currentPassword)).then(response => { const data = response.data; if (!data || !data.success || !data.result) { diff --git a/src/stores/user.ts b/src/stores/user.ts index 27f8dc20..b2746ef9 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -19,6 +19,7 @@ import type { import { isObject, + isString, isNumber } from '@/lib/common.ts'; @@ -289,12 +290,20 @@ export const useUserStore = defineStore('user', () => { }); } - function getUserAvatarUrl(userInfo: UserBasicInfo, disableBrowserCache: boolean | string): string | null { - if (!userInfo || !userInfo.avatar) { + function getUserAvatarUrl(userInfoOrAvatarUrl: UserBasicInfo | string, disableBrowserCache: boolean | string): string | null { + let avatarUrl = ''; + + if (isObject(userInfoOrAvatarUrl)) { + avatarUrl = userInfoOrAvatarUrl.avatar; + } else if (isString(userInfoOrAvatarUrl)) { + avatarUrl = userInfoOrAvatarUrl; + } + + if (!avatarUrl) { return null; } - return services.getInternalAvatarUrlWithToken(userInfo.avatar, disableBrowserCache); + return services.getInternalAvatarUrlWithToken(avatarUrl, disableBrowserCache); } return { diff --git a/src/views/base/users/UserProfilePageBase.ts b/src/views/base/users/UserProfilePageBase.ts new file mode 100644 index 00000000..eaebb929 --- /dev/null +++ b/src/views/base/users/UserProfilePageBase.ts @@ -0,0 +1,212 @@ +import { ref, computed } from 'vue'; + +import { type LanguageOption } from '@/locales/index.ts'; +import { useI18n } from '@/locales/helpers.ts'; + +import { useSettingsStore } from '@/stores/setting.ts'; +import { useAccountsStore } from '@/stores/account.ts'; +import { useOverviewStore } from '@/stores/overview.ts'; + +import type { TypeAndDisplayName } from '@/core/base.ts'; +import { WeekDay } from '@/core/datetime.ts'; +import type { LocalizedDigitGroupingType } from '@/core/numeral.ts'; +import type { LocalizedCurrencyInfo } from '@/core/currency.ts'; + +import { type UserBasicInfo, User } from '@/models/user.ts'; +import { type CategorizedAccount, Account} from '@/models/account.ts'; + +import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; +import { getCategorizedAccounts } from '@/lib/account.ts'; + +export function useUserProfilePageBase() { + const { + getDefaultCurrency, + getDefaultFirstDayOfWeek, + getAllLanguageOptions, + getAllCurrencies, + getAllWeekDays, + getAllLongDateFormats, + getAllShortDateFormats, + getAllLongTimeFormats, + getAllShortTimeFormats, + getAllDecimalSeparators, + getAllDigitGroupingSymbols, + getAllDigitGroupingTypes, + getAllCurrencyDisplayTypes, + getAllExpenseAmountColors, + getAllIncomeAmountColors, + getAllTransactionEditScopeTypes, + setLanguage + } = useI18n(); + + const settingsStore = useSettingsStore(); + const accountsStore = useAccountsStore(); + const overviewStore = useOverviewStore(); + + const defaultFirstDayOfWeekName = getDefaultFirstDayOfWeek(); + const defaultFirstDayOfWeek = WeekDay.parse(defaultFirstDayOfWeekName) ? (WeekDay.parse(defaultFirstDayOfWeekName) as WeekDay).type : WeekDay.DefaultFirstDay.type; + + const newProfile = ref(User.createNewUser('', getDefaultCurrency(), defaultFirstDayOfWeek)); + const oldProfile = ref(User.createNewUser('', getDefaultCurrency(), defaultFirstDayOfWeek)); + + const emailVerified = ref(false); + const loading = ref(false); + const resending = ref(false); + const saving = ref(false); + + const allLanguages = computed(() => getAllLanguageOptions(true)); + const allCurrencies = computed(() => getAllCurrencies()); + const allAccounts = computed(() => accountsStore.allPlainAccounts); + const allVisibleAccounts = computed(() => accountsStore.allVisiblePlainAccounts); + const allVisibleCategorizedAccounts = computed(() => getCategorizedAccounts(allVisibleAccounts.value)); + const allWeekDays = computed(() => getAllWeekDays()); + const allLongDateFormats = computed(() => getAllLongDateFormats()); + const allShortDateFormats = computed(() => getAllShortDateFormats()); + const allLongTimeFormats = computed(() => getAllLongTimeFormats()); + const allShortTimeFormats = computed(() => getAllShortTimeFormats()); + const allDecimalSeparators = computed(() => getAllDecimalSeparators()); + const allDigitGroupingSymbols = computed(() => getAllDigitGroupingSymbols()); + const allDigitGroupingTypes = computed(() => getAllDigitGroupingTypes()); + const allCurrencyDisplayTypes = computed(() => getAllCurrencyDisplayTypes()); + const allExpenseAmountColorTypes = computed(() => getAllExpenseAmountColors()); + const allIncomeAmountColorTypes = computed(() => getAllIncomeAmountColors()); + const allTransactionEditScopeTypes = computed(() => getAllTransactionEditScopeTypes()); + + const supportDigitGroupingSymbol = computed(() => { + for (const digitGroupingType of allDigitGroupingTypes.value) { + if (digitGroupingType.type === newProfile.value.digitGrouping) { + return digitGroupingType.enabled; + } + } + + return false; + }); + + const inputIsNotChangedProblemMessage = computed(() => { + if (!newProfile.value.password && !newProfile.value.confirmPassword && !newProfile.value.email && !newProfile.value.nickname) { + return 'Nothing has been modified'; + } else if (!newProfile.value.password && !newProfile.value.confirmPassword && + newProfile.value.email === oldProfile.value.email && + newProfile.value.nickname === oldProfile.value.nickname && + newProfile.value.defaultAccountId === oldProfile.value.defaultAccountId && + newProfile.value.transactionEditScope === oldProfile.value.transactionEditScope && + newProfile.value.language === oldProfile.value.language && + newProfile.value.defaultCurrency === oldProfile.value.defaultCurrency && + newProfile.value.firstDayOfWeek === oldProfile.value.firstDayOfWeek && + newProfile.value.longDateFormat === oldProfile.value.longDateFormat && + newProfile.value.shortDateFormat === oldProfile.value.shortDateFormat && + newProfile.value.longTimeFormat === oldProfile.value.longTimeFormat && + newProfile.value.shortTimeFormat === oldProfile.value.shortTimeFormat && + newProfile.value.decimalSeparator === oldProfile.value.decimalSeparator && + newProfile.value.digitGroupingSymbol === oldProfile.value.digitGroupingSymbol && + newProfile.value.digitGrouping === oldProfile.value.digitGrouping && + newProfile.value.currencyDisplayType === oldProfile.value.currencyDisplayType && + newProfile.value.expenseAmountColor === oldProfile.value.expenseAmountColor && + newProfile.value.incomeAmountColor === oldProfile.value.incomeAmountColor) { + return 'Nothing has been modified'; + } else if (!newProfile.value.password && newProfile.value.confirmPassword) { + return 'Password cannot be blank'; + } else if (newProfile.value.password && !newProfile.value.confirmPassword) { + return 'Password confirmation cannot be blank'; + } else { + return null; + } + }); + + const inputInvalidProblemMessage = computed(() => { + if (newProfile.value.password && newProfile.value.confirmPassword && newProfile.value.password !== newProfile.value.confirmPassword) { + return 'Password and password confirmation do not match'; + } else if (!newProfile.value.email) { + return 'Email address cannot be blank'; + } else if (!newProfile.value.nickname) { + return 'Nickname cannot be blank'; + } else if (!newProfile.value.defaultCurrency) { + return 'Default currency cannot be blank'; + } else { + return null; + } + }); + + const langAndRegionInputInvalidProblemMessage = computed(() => { + if (!newProfile.value.defaultCurrency) { + return 'Default currency cannot be blank'; + } else { + return null; + } + }); + + const extendInputInvalidProblemMessage = computed(() => { + return null; + }); + + const inputIsNotChanged = computed(() => !!inputIsNotChangedProblemMessage.value); + const inputIsInvalid = computed(() => !!inputInvalidProblemMessage.value); + const langAndRegionInputIsInvalid = computed(() => !!langAndRegionInputInvalidProblemMessage.value); + const extendInputIsInvalid = computed(() => !!extendInputInvalidProblemMessage.value); + + function setCurrentUserProfile(profile: UserBasicInfo): void { + emailVerified.value = profile.emailVerified; + oldProfile.value.from(profile); + newProfile.value.from(oldProfile.value); + } + + function reset(): void { + newProfile.value.from(oldProfile.value); + } + + function doAfterProfileUpdate(user: UserBasicInfo): void { + if (user) { + if (user.firstDayOfWeek !== oldProfile.value.firstDayOfWeek) { + overviewStore.resetTransactionOverview(); + } + + setCurrentUserProfile(user); + + const localeDefaultSettings = setLanguage(user.language); + settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings); + + setExpenseAndIncomeAmountColor(user.expenseAmountColor, user.incomeAmountColor); + } + } + + return { + // states + newProfile, + oldProfile, + emailVerified, + loading, + resending, + saving, + // computed states + allLanguages, + allCurrencies, + allAccounts, + allVisibleAccounts, + allVisibleCategorizedAccounts, + allWeekDays, + allLongDateFormats, + allShortDateFormats, + allLongTimeFormats, + allShortTimeFormats, + allDecimalSeparators, + allDigitGroupingSymbols, + allDigitGroupingTypes, + allCurrencyDisplayTypes, + allExpenseAmountColorTypes, + allIncomeAmountColorTypes, + allTransactionEditScopeTypes, + supportDigitGroupingSymbol, + inputIsNotChangedProblemMessage, + inputInvalidProblemMessage, + langAndRegionInputInvalidProblemMessage, + extendInputInvalidProblemMessage, + inputIsNotChanged, + inputIsInvalid, + langAndRegionInputIsInvalid, + extendInputIsInvalid, + // functions + setCurrentUserProfile, + reset, + doAfterProfileUpdate + }; +} diff --git a/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue b/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue index f27700f8..bd4a3529 100644 --- a/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue +++ b/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue @@ -3,13 +3,13 @@