diff --git a/cmd/user_data.go b/cmd/user_data.go index 61d1be2e..bb318f0a 100644 --- a/cmd/user_data.go +++ b/cmd/user_data.go @@ -658,6 +658,8 @@ func printUserInfo(user *models.User) { fmt.Printf("[DigitGroupingSymbol] %s (%d)\n", user.DigitGroupingSymbol, user.DigitGroupingSymbol) fmt.Printf("[DigitGrouping] %s (%d)\n", user.DigitGrouping, user.DigitGrouping) fmt.Printf("[CurrencyDisplayType] %s (%d)\n", user.CurrencyDisplayType, user.CurrencyDisplayType) + fmt.Printf("[ExpenseAmountColor] %s (%d)\n", user.ExpenseAmountColor, user.ExpenseAmountColor) + fmt.Printf("[IncomeAmountColor] %s (%d)\n", user.IncomeAmountColor, user.IncomeAmountColor) fmt.Printf("[Deleted] %t\n", user.Deleted) fmt.Printf("[EmailVerified] %t\n", user.EmailVerified) fmt.Printf("[CreatedAt] %s (%d)\n", utils.FormatUnixTimeToLongDateTimeInServerTimezone(user.CreatedUnixTime), user.CreatedUnixTime) diff --git a/pkg/api/users.go b/pkg/api/users.go index dec95bbd..30f4892b 100644 --- a/pkg/api/users.go +++ b/pkg/api/users.go @@ -369,6 +369,22 @@ func (a *UsersApi) UserUpdateProfileHandler(c *core.Context) (any, *errs.Error) userNew.CurrencyDisplayType = models.CURRENCY_DISPLAY_TYPE_INVALID } + if userUpdateReq.ExpenseAmountColor != nil && *userUpdateReq.ExpenseAmountColor != user.ExpenseAmountColor { + user.ExpenseAmountColor = *userUpdateReq.ExpenseAmountColor + userNew.ExpenseAmountColor = *userUpdateReq.ExpenseAmountColor + anythingUpdate = true + } else { + userNew.ExpenseAmountColor = models.AMOUNT_COLOR_TYPE_INVALID + } + + if userUpdateReq.IncomeAmountColor != nil && *userUpdateReq.IncomeAmountColor != user.IncomeAmountColor { + user.IncomeAmountColor = *userUpdateReq.IncomeAmountColor + userNew.IncomeAmountColor = *userUpdateReq.IncomeAmountColor + anythingUpdate = true + } else { + userNew.IncomeAmountColor = models.AMOUNT_COLOR_TYPE_INVALID + } + if modifyUserLanguage || userNew.DecimalSeparator != models.DECIMAL_SEPARATOR_INVALID || userNew.DigitGroupingSymbol != models.DIGIT_GROUPING_SYMBOL_INVALID { decimalSeparator := userNew.DecimalSeparator digitGroupingSymbol := userNew.DigitGroupingSymbol diff --git a/pkg/models/user.go b/pkg/models/user.go index 0bffaa0a..924b7ef0 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -47,6 +47,39 @@ func (s TransactionEditScope) String() string { } } +// AmountColorType represents the type of amount color in frontend +type AmountColorType byte + +// Amount Color Types +const ( + AMOUNT_COLOR_TYPE_DEFAULT AmountColorType = 0 + AMOUNT_COLOR_TYPE_GREEN AmountColorType = 1 + AMOUNT_COLOR_TYPE_RED AmountColorType = 2 + AMOUNT_COLOR_TYPE_YELLOW AmountColorType = 3 + AMOUNT_COLOR_TYPE_BLACK_OR_WHITE AmountColorType = 4 + AMOUNT_COLOR_TYPE_INVALID AmountColorType = 255 +) + +// String returns a textual representation of the amount color type enum +func (s AmountColorType) String() string { + switch s { + case AMOUNT_COLOR_TYPE_DEFAULT: + return "Default" + case AMOUNT_COLOR_TYPE_GREEN: + return "Green" + case AMOUNT_COLOR_TYPE_RED: + return "Red" + case AMOUNT_COLOR_TYPE_YELLOW: + return "Yellow" + case AMOUNT_COLOR_TYPE_BLACK_OR_WHITE: + return "Black or White" + case AMOUNT_COLOR_TYPE_INVALID: + return "Invalid" + default: + return fmt.Sprintf("Invalid(%d)", int(s)) + } +} + // User represents user data stored in database type User struct { Uid int64 `xorm:"PK"` @@ -68,6 +101,8 @@ type User struct { DigitGroupingSymbol DigitGroupingSymbol `xorm:"TINYINT"` DigitGrouping DigitGroupingType `xorm:"TINYINT"` CurrencyDisplayType CurrencyDisplayType `xorm:"TINYINT"` + ExpenseAmountColor AmountColorType `xorm:"TINYINT"` + IncomeAmountColor AmountColorType `xorm:"TINYINT"` Disabled bool Deleted bool `xorm:"NOT NULL"` EmailVerified bool `xorm:"NOT NULL"` @@ -97,6 +132,8 @@ type UserBasicInfo struct { DigitGroupingSymbol DigitGroupingSymbol `json:"digitGroupingSymbol"` DigitGrouping DigitGroupingType `json:"digitGrouping"` CurrencyDisplayType CurrencyDisplayType `json:"currencyDisplayType"` + ExpenseAmountColor AmountColorType `json:"expenseAmountColor"` + IncomeAmountColor AmountColorType `json:"incomeAmountColor"` EmailVerified bool `json:"emailVerified"` } @@ -154,6 +191,8 @@ type UserProfileUpdateRequest struct { DigitGroupingSymbol *DigitGroupingSymbol `json:"digitGroupingSymbol" binding:"omitempty,min=0,max=4"` DigitGrouping *DigitGroupingType `json:"digitGrouping" binding:"omitempty,min=0,max=2"` CurrencyDisplayType *CurrencyDisplayType `json:"currencyDisplayType" binding:"omitempty,min=0,max=9"` + ExpenseAmountColor *AmountColorType `json:"expenseAmountColor" binding:"omitempty,min=0,max=4"` + IncomeAmountColor *AmountColorType `json:"incomeAmountColor" binding:"omitempty,min=0,max=4"` } // UserProfileUpdateResponse represents the data returns to frontend after updating profile @@ -182,6 +221,8 @@ type UserProfileResponse struct { DigitGroupingSymbol DigitGroupingSymbol `json:"digitGroupingSymbol"` DigitGrouping DigitGroupingType `json:"digitGrouping"` CurrencyDisplayType CurrencyDisplayType `json:"currencyDisplayType"` + ExpenseAmountColor AmountColorType `json:"expenseAmountColor"` + IncomeAmountColor AmountColorType `json:"incomeAmountColor"` EmailVerified bool `json:"emailVerified"` LastLoginAt int64 `json:"lastLoginAt"` } @@ -249,6 +290,8 @@ func (u *User) ToUserBasicInfo() *UserBasicInfo { DigitGroupingSymbol: u.DigitGroupingSymbol, DigitGrouping: u.DigitGrouping, CurrencyDisplayType: u.CurrencyDisplayType, + ExpenseAmountColor: u.ExpenseAmountColor, + IncomeAmountColor: u.IncomeAmountColor, EmailVerified: u.EmailVerified, } } @@ -274,6 +317,8 @@ func (u *User) ToUserProfileResponse() *UserProfileResponse { DigitGroupingSymbol: u.DigitGroupingSymbol, DigitGrouping: u.DigitGrouping, CurrencyDisplayType: u.CurrencyDisplayType, + ExpenseAmountColor: u.ExpenseAmountColor, + IncomeAmountColor: u.IncomeAmountColor, EmailVerified: u.EmailVerified, LastLoginAt: u.LastLoginUnixTime, } diff --git a/pkg/services/users.go b/pkg/services/users.go index 95a7a130..4dd48faa 100644 --- a/pkg/services/users.go +++ b/pkg/services/users.go @@ -264,6 +264,14 @@ func (s *UserService) UpdateUser(c *core.Context, user *models.User, modifyUserL updateCols = append(updateCols, "currency_display_type") } + if models.AMOUNT_COLOR_TYPE_DEFAULT <= user.ExpenseAmountColor && user.ExpenseAmountColor <= models.AMOUNT_COLOR_TYPE_BLACK_OR_WHITE { + updateCols = append(updateCols, "expense_amount_color") + } + + if models.AMOUNT_COLOR_TYPE_DEFAULT <= user.IncomeAmountColor && user.IncomeAmountColor <= models.AMOUNT_COLOR_TYPE_BLACK_OR_WHITE { + updateCols = append(updateCols, "income_amount_color") + } + user.UpdatedUnixTime = now updateCols = append(updateCols, "updated_unix_time") diff --git a/src/DesktopApp.vue b/src/DesktopApp.vue index ff8a7bed..f2880ebb 100644 --- a/src/DesktopApp.vue +++ b/src/DesktopApp.vue @@ -17,7 +17,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import { isProduction } from '@/lib/version.js'; import { loadMapAssets } from '@/lib/map/index.js'; -import { getSystemTheme } from '@/lib/ui.js'; +import { getSystemTheme, setExpenseAndIncomeAmountColor } from '@/lib/ui.js'; export default { data() { @@ -61,6 +61,8 @@ export default { if (response.user) { localeDefaultSettings = self.$locale.setLanguage(response.user.language); self.settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings); + + setExpenseAndIncomeAmountColor(response.user.expenseAmountColor, response.user.incomeAmountColor); } }); diff --git a/src/MobileApp.vue b/src/MobileApp.vue index 97d342fd..17f35312 100644 --- a/src/MobileApp.vue +++ b/src/MobileApp.vue @@ -18,6 +18,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import { isProduction } from '@/lib/version.js'; import { getTheme, isEnableAnimate } from '@/lib/settings.js'; import { loadMapAssets } from '@/lib/map/index.js'; +import { setExpenseAndIncomeAmountColor } from '@/lib/ui.js'; import { isModalShowing, setAppFontSize } from '@/lib/ui.mobile.js'; export default { @@ -108,6 +109,8 @@ export default { if (response.user) { localeDefaultSettings = self.$locale.setLanguage(response.user.language); self.settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings); + + setExpenseAndIncomeAmountColor(response.user.expenseAmountColor, response.user.incomeAmountColor); } }); diff --git a/src/consts/color.js b/src/consts/color.js index 9a830e44..34a5450b 100644 --- a/src/consts/color.js +++ b/src/consts/color.js @@ -29,6 +29,59 @@ const defaultChartColors = [ '8e1d51' ]; +const allAmountColors = { + Green: { + type: 1, + name: 'Green', + lightThemeColor: '#009688', + darkThemeColor: '#009688', + expenseClassName: 'expense-amount-color-green', + incomeClassName: 'income-amount-color-green' + }, + Red: { + type: 2, + name: 'Red', + lightThemeColor: '#d43f3f', + darkThemeColor: '#d43f3f', + expenseClassName: 'expense-amount-color-red', + incomeClassName: 'income-amount-color-red' + }, + Yellow: { + type: 3, + name: 'Yellow', + lightThemeColor: '#e2b60a', + darkThemeColor: '#e2b60a', + expenseClassName: 'expense-amount-color-yellow', + incomeClassName: 'income-amount-color-yellow' + }, + BlackOrWhite: { + type: 4, + name: 'Black or White', + lightThemeColor: '#413935', + darkThemeColor: '#fcf0e3', + expenseClassName: 'expense-amount-color-blackorwhite', + incomeClassName: 'income-amount-color-blackorwhite' + } +} + +const allAmountColorsArray = [ + allAmountColors.Green, + allAmountColors.Red, + allAmountColors.Yellow, + allAmountColors.BlackOrWhite +]; + +const allAmountColorTypesMap = { + [allAmountColors.Green.type]: allAmountColors.Green, + [allAmountColors.Red.type]: allAmountColors.Red, + [allAmountColors.Yellow.type]: allAmountColors.Yellow, + [allAmountColors.BlackOrWhite.type]: allAmountColors.BlackOrWhite +}; + +const defaultExpenseIncomeAmountValue = 0; +const defaultExpenseAmountColor = allAmountColors.Green; +const defaultIncomeAmountColor = allAmountColors.Red; + export default { defaultColor: defaultColor, allAccountColors: allAvailableColors, @@ -36,4 +89,10 @@ export default { allCategoryColors: allAvailableColors, defaultCategoryColor: defaultColor, defaultChartColors: defaultChartColors, + allAmountColors: allAmountColors, + allAmountColorsArray: allAmountColorsArray, + allAmountColorTypesMap: allAmountColorTypesMap, + defaultExpenseIncomeAmountValue: defaultExpenseIncomeAmountValue, + defaultExpenseAmountColor: defaultExpenseAmountColor, + defaultIncomeAmountColor: defaultIncomeAmountColor, }; diff --git a/src/desktop-main.js b/src/desktop-main.js index add34426..faef0722 100644 --- a/src/desktop-main.js +++ b/src/desktop-main.js @@ -104,6 +104,7 @@ import '@/styles/desktop/template/layout/component/index.scss'; import '@/styles/desktop/template/layout/_default-layout.scss'; import '@/styles/desktop/global.scss'; import '@/styles/desktop/font-size.scss'; +import '@/styles/desktop/amount-color.scss'; import App from './DesktopApp.vue'; @@ -300,8 +301,7 @@ const vuetify = createVuetify({ 'error': '#ff3b30', 'error-darken-1': '#e1342b', 'on-error': '#ffffff', - 'income': '#ff3b30', - 'expense': '#009688', + 'teal': '#009688', 'background': '#faf8f4', 'on-background': '#413935', 'surface': '#fff', @@ -369,8 +369,7 @@ const vuetify = createVuetify({ 'error': '#ff3b30', 'error-darken-1': '#e1342b', 'on-error': '#ffffff', - 'income': '#ff3b30', - 'expense': '#009688', + 'teal': '#009688', 'background': '#000000', 'on-background': '#fcf0e3', 'surface': '#1c1c1d', diff --git a/src/lib/i18n.js b/src/lib/i18n.js index 9cad2b3a..8244965e 100644 --- a/src/lib/i18n.js +++ b/src/lib/i18n.js @@ -5,6 +5,7 @@ import numeralConstants from '@/consts/numeral.js'; import datetimeConstants from '@/consts/datetime.js'; import timezoneConstants from '@/consts/timezone.js'; import currencyConstants from '@/consts/currency.js'; +import colorConstants from '@/consts/color.js'; import accountConstants from '@/consts/account.js'; import categoryConstants from '@/consts/category.js'; import transactionConstants from '@/consts/transaction.js'; @@ -902,6 +903,37 @@ function getAmountPrependAndAppendText(currencyCode, userStore, settingsStore, t return getAmountPrependAndAppendCurrencySymbol(currencyDisplayType, currencyCode, currencyName); } +function getAllExpenseIncomeAmountColors(translateFn, expenseOrIncome) { + const allAmountColors = []; + let defaultAmountName = ''; + + if (expenseOrIncome === 1) { // expense + defaultAmountName = colorConstants.defaultExpenseAmountColor.name; + } else if (expenseOrIncome === 2) { // income + defaultAmountName = colorConstants.defaultIncomeAmountColor.name; + } + + if (defaultAmountName) { + defaultAmountName = translateFn('color.amount.' + defaultAmountName); + } + + allAmountColors.push({ + type: colorConstants.defaultExpenseIncomeAmountValue, + displayName: translateFn('System Default') + (defaultAmountName ? ` (${defaultAmountName})` : '') + }); + + for (let i = 0; i < colorConstants.allAmountColorsArray.length; i++) { + const amountColor = colorConstants.allAmountColorsArray[i]; + + allAmountColors.push({ + type: amountColor.type, + displayName: translateFn('color.amount.' + amountColor.name) + }); + } + + return allAmountColors; +} + function getAllAccountCategories(translateFn) { const allAccountCategories = []; @@ -1430,6 +1462,8 @@ export function i18nFunctions(i18nGlobal) { formatExchangeRateAmount: (userStore, value) => getFormatedExchangeRateAmount(value, i18nGlobal.t, userStore), getAdaptiveAmountRate: (userStore, amount1, amount2, fromExchangeRate, toExchangeRate) => getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, i18nGlobal.t, userStore), getAmountPrependAndAppendText: (settingsStore, userStore, currencyCode) => getAmountPrependAndAppendText(currencyCode, userStore, settingsStore, i18nGlobal.t), + 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/lib/services.js b/src/lib/services.js index dcbc7e6b..18aaa9f8 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -169,7 +169,7 @@ export default { getProfile: () => { return axios.get('v1/users/profile/get.json'); }, - updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat, decimalSeparator, digitGroupingSymbol, digitGrouping, currencyDisplayType }) => { + updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat, decimalSeparator, digitGroupingSymbol, digitGrouping, currencyDisplayType, expenseAmountColor, incomeAmountColor }) => { return axios.post('v1/users/profile/update.json', { email, nickname, @@ -187,7 +187,9 @@ export default { decimalSeparator, digitGroupingSymbol, digitGrouping, - currencyDisplayType + currencyDisplayType, + expenseAmountColor, + incomeAmountColor }); }, resendVerifyEmailByLoginedUser: () => { diff --git a/src/lib/ui.js b/src/lib/ui.js index 778d973f..ccd68ff1 100644 --- a/src/lib/ui.js +++ b/src/lib/ui.js @@ -1,3 +1,5 @@ +import colorConstants from '@/consts/color.js'; + export function getSystemTheme() { if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { return 'dark'; @@ -6,6 +8,66 @@ export function getSystemTheme() { } } +export function getExpenseAndIncomeAmountColor(expenseAmountColorType, incomeAmountColorType, isDarkMode) { + let expenseAmountColor = expenseAmountColorType ? colorConstants.allAmountColorTypesMap[expenseAmountColorType] : null; + let incomeAmountColor = incomeAmountColorType ? colorConstants.allAmountColorTypesMap[incomeAmountColorType] : null; + + if (!expenseAmountColor) { + expenseAmountColor = colorConstants.defaultExpenseAmountColor; + } + + if (!incomeAmountColor) { + incomeAmountColor = colorConstants.defaultIncomeAmountColor; + } + + if (isDarkMode) { + return { + expenseAmountColor: expenseAmountColor.darkThemeColor, + incomeAmountColor: incomeAmountColor.darkThemeColor + } + } else { + return { + expenseAmountColor: expenseAmountColor.lightThemeColor, + incomeAmountColor: incomeAmountColor.lightThemeColor + } + } +} + +export function setExpenseAndIncomeAmountColor(expenseAmountColorType, incomeAmountColorType) { + let expenseAmountColor = expenseAmountColorType ? colorConstants.allAmountColorTypesMap[expenseAmountColorType] : null; + let incomeAmountColor = incomeAmountColorType ? colorConstants.allAmountColorTypesMap[incomeAmountColorType] : null; + + if (!expenseAmountColor) { + expenseAmountColor = colorConstants.defaultExpenseAmountColor; + } + + if (!incomeAmountColor) { + incomeAmountColor = colorConstants.defaultIncomeAmountColor; + } + + const htmlElement = document.querySelector('html'); + + for (let i = 0; i < colorConstants.allAmountColorsArray.length; i++) { + const amountColor = colorConstants.allAmountColorsArray[i]; + + if (amountColor.type === expenseAmountColor.type) { + if (!htmlElement.classList.contains(amountColor.expenseClassName)) { + htmlElement.classList.add(amountColor.expenseClassName); + } + } else { + htmlElement.classList.remove(amountColor.expenseClassName); + } + + if (amountColor.type === incomeAmountColor.type) { + if (!htmlElement.classList.contains(amountColor.incomeClassName)) { + htmlElement.classList.add(amountColor.incomeClassName); + } + } else { + htmlElement.classList.remove(amountColor.incomeClassName); + } + } +} + export function startDownloadFile(fileName, fileData) { const dataObjectUrl = URL.createObjectURL(fileData); const dataLink = document.createElement('a'); diff --git a/src/locales/en.js b/src/locales/en.js index 7d00f245..e8f3cc38 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -181,6 +181,14 @@ export default { 'None': 'None', 'Thousands Separator': 'Thousands Separator', }, + 'color': { + 'amount': { + 'Green': 'Green', + 'Red': 'Red', + 'Yellow': 'Yellow', + 'Black or White': 'Black or White' + } + }, 'timezone': { 'International Date Line West': 'International Date Line West', 'Coordinated Universal Time-11': 'Coordinated Universal Time-11', @@ -775,6 +783,7 @@ export default { 'Sort': 'Sort', 'Date': 'Date', 'Time': 'Time', + 'Color': 'Color', 'Type': 'Type', 'All Types': 'All Types', 'More': 'More', @@ -1103,6 +1112,8 @@ export default { 'Currency Code': 'Currency Code', 'Currency Name': 'Currency Name', 'Currency Symbol': 'Currency Symbol', + 'Expense Amount Color': 'Expense Amount Color', + 'Income Amount Color': 'Income Amount Color', 'Show Account Balance': 'Show Account Balance', 'Hide Account Balance': 'Hide Account Balance', 'Page Settings': 'Page Settings', diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js index f507c3e8..cebfd986 100644 --- a/src/locales/zh_Hans.js +++ b/src/locales/zh_Hans.js @@ -181,6 +181,14 @@ export default { 'None': '无', 'Thousands Separator': '千位分隔符', }, + 'color': { + 'amount': { + 'Green': '绿色', + 'Red': '红色', + 'Yellow': '黄色', + 'Black or White': '黑色或白色' + } + }, 'timezone': { 'International Date Line West': '国际日期变更线西', 'Coordinated Universal Time-11': '协调世界时-11', @@ -775,6 +783,7 @@ export default { 'Sort': '排序', 'Date': '日期', 'Time': '时间', + 'Color': '颜色', 'Type': '类型', 'All Types': '全部类型', 'More': '更多', @@ -1103,6 +1112,8 @@ export default { 'Currency Code': '货币代码', 'Currency Name': '货币名称', 'Currency Symbol': '货币符号', + 'Expense Amount Color': '支出金额颜色', + 'Income Amount Color': '收入金额颜色', 'Show Account Balance': '显示账户余额', 'Hide Account Balance': '隐藏账户余额', 'Page Settings': '页面设置', diff --git a/src/mobile-main.js b/src/mobile-main.js index 0b691646..56e59c22 100644 --- a/src/mobile-main.js +++ b/src/mobile-main.js @@ -119,6 +119,7 @@ import '@/styles/mobile/font-size-x-large.css'; import '@/styles/mobile/font-size-xx-large.css'; import '@/styles/mobile/font-size-xxx-large.css'; import '@/styles/mobile/font-size-xxxx-large.css'; +import '@/styles/mobile/amount-color.css'; import App from '@/MobileApp.vue'; diff --git a/src/stores/index.js b/src/stores/index.js index b8f203d3..c3e6de41 100644 --- a/src/stores/index.js +++ b/src/stores/index.js @@ -384,7 +384,9 @@ export const useRootStore = defineStore('root', { decimalSeparator: profile.decimalSeparator, digitGroupingSymbol: profile.digitGroupingSymbol, digitGrouping: profile.digitGrouping, - currencyDisplayType: profile.currencyDisplayType + currencyDisplayType: profile.currencyDisplayType, + expenseAmountColor: profile.expenseAmountColor, + incomeAmountColor: profile.incomeAmountColor }).then(response => { const data = response.data; diff --git a/src/stores/user.js b/src/stores/user.js index c1ddffa8..fb8eeee1 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -69,6 +69,14 @@ export const useUserStore = defineStore('user', { currentUserCurrencyDisplayType(state) { const userInfo = state.currentUserInfo || {}; return userInfo.currencyDisplayType; + }, + currentUserExpenseAmountColor(state) { + const userInfo = state.currentUserInfo || {}; + return userInfo.expenseAmountColor; + }, + currentUserIncomeAmountColor(state) { + const userInfo = state.currentUserInfo || {}; + return userInfo.incomeAmountColor; } }, actions: { diff --git a/src/styles/desktop/amount-color.scss b/src/styles/desktop/amount-color.scss new file mode 100644 index 00000000..e3ba3db5 --- /dev/null +++ b/src/styles/desktop/amount-color.scss @@ -0,0 +1,133 @@ +:root { + --ebk-amount-color-green: 0, 150, 136; + --ebk-amount-color-red: 212, 63, 63; + --ebk-amount-color-yellow: 226, 182, 10; +} + +:root.expense-amount-color-green { + .v-theme--light, + .v-theme--dark { + --v-theme-expense: var(--ebk-amount-color-green); + } + + .text-expense { + color: rgb(var(--ebk-amount-color-green)); + } + + .bg-expense { + color: rgb(var(--v-theme-on-primary)) !important; + background-color: rgb(var(--ebk-amount-color-green)); + } +} + +:root.income-amount-color-green { + .v-theme--light, + .v-theme--dark { + --v-theme-income: var(--ebk-amount-color-green); + } + + .text-income { + color: rgb(var(--ebk-amount-color-green)); + } + + .bg-income { + color: rgb(var(--v-theme-on-primary)) !important; + background-color: rgb(var(--ebk-amount-color-green)); + } +} + +:root.expense-amount-color-red { + .v-theme--light, + .v-theme--dark { + --v-theme-expense: var(--ebk-amount-color-red); + } + + .text-expense { + color: rgb(var(--ebk-amount-color-red)); + } + + .bg-expense { + color: rgb(var(--v-theme-on-primary)) !important; + background-color: rgb(var(--ebk-amount-color-red)); + } +} + +:root.income-amount-color-red { + .v-theme--light, + .v-theme--dark { + --v-theme-income: var(--ebk-amount-color-red); + } + + .text-income { + color: rgb(var(--ebk-amount-color-red)); + } + + .bg-income { + color: rgb(var(--v-theme-on-primary)) !important; + background-color: rgb(var(--ebk-amount-color-red)); + } +} + +:root.expense-amount-color-yellow { + .v-theme--light, + .v-theme--dark { + --v-theme-expense: var(--ebk-amount-color-yellow); + } + + .text-expense { + color: rgb(var(--ebk-amount-color-yellow)); + } + + .bg-expense { + color: rgb(var(--v-theme-on-primary)) !important; + background-color: rgb(var(--ebk-amount-color-yellow)); + } +} + +:root.income-amount-color-yellow { + .v-theme--light, + .v-theme--dark { + --v-theme-income: var(--ebk-amount-color-yellow); + } + + .text-income { + color: rgb(var(--ebk-amount-color-yellow)); + } + + .bg-income { + color: rgb(var(--v-theme-on-primary)) !important; + background-color: rgb(var(--ebk-amount-color-yellow)); + } +} + +:root.expense-amount-color-blackorwhite { + .v-theme--light, + .v-theme--dark { + --v-theme-expense: var(--v-theme-on-surface); + + .text-expense { + color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)); + } + + .bg-expense { + color: rgb(var(--v-theme-surface)) !important; + background-color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)); + } + } +} + +:root.income-amount-color-blackorwhite { + .v-theme--light, + .v-theme--dark { + --v-theme-income: var(--v-theme-on-surface); + + .text-income { + color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)); + } + + .bg-income { + color: rgb(var(--v-theme-surface)) !important; + background-color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)); + } + } +} diff --git a/src/styles/mobile/amount-color.css b/src/styles/mobile/amount-color.css new file mode 100644 index 00000000..12fa54bb --- /dev/null +++ b/src/styles/mobile/amount-color.css @@ -0,0 +1,47 @@ +:root { + --ebk-amount-color-green: 0, 150, 136; + --ebk-amount-color-red: 212, 63, 63; + --ebk-amount-color-yellow: 226, 182, 10; + --ebk-amount-color-black: 65, 57, 53; + --ebk-amount-color-white: 250, 240, 237; +} + +:root.expense-amount-color-green .text-expense { + color: rgb(var(--ebk-amount-color-green)) !important; +} + +:root.income-amount-color-green .text-income { + color: rgb(var(--ebk-amount-color-green)) !important; +} + +:root.expense-amount-color-red .text-expense { + color: rgb(var(--ebk-amount-color-red)) !important; +} + +:root.income-amount-color-red .text-income { + color: rgb(var(--ebk-amount-color-red)) !important; +} + +:root.expense-amount-color-yellow .text-expense { + color: rgb(var(--ebk-amount-color-yellow)) !important; +} + +:root.income-amount-color-yellow .text-income { + color: rgb(var(--ebk-amount-color-yellow)) !important; +} + +:root.expense-amount-color-blackorwhite .text-expense { + color: rgb(var(--ebk-amount-color-black)) !important; +} + +:root.dark.expense-amount-color-blackorwhite .text-expense { + color: rgb(var(--ebk-amount-color-white)) !important; +} + +:root.income-amount-color-blackorwhite .text-income { + color: rgb(var(--ebk-amount-color-black)) !important; +} + +:root.dark.income-amount-color-blackorwhite .text-income { + color: rgb(var(--ebk-amount-color-white)) !important; +} diff --git a/src/views/desktop/SignupPage.vue b/src/views/desktop/SignupPage.vue index 08876a19..6d28f25f 100644 --- a/src/views/desktop/SignupPage.vue +++ b/src/views/desktop/SignupPage.vue @@ -223,7 +223,7 @@ :append-icon="icons.next" @click="switchToNextTab" v-if="currentStep === 'basicSetting'">{{ $t('Next') }} - -
{{ incomeAmount }}
+
{{ incomeAmount }}
{{ expenseAmount }}
diff --git a/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue b/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue index 0cdfa60e..3aba6f78 100644 --- a/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue +++ b/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue @@ -25,6 +25,8 @@