add sign up page

This commit is contained in:
MaysWind
2023-07-08 00:29:22 +08:00
parent 9d0b874488
commit 48d9a09307
9 changed files with 828 additions and 44 deletions
+137
View File
@@ -0,0 +1,137 @@
<template>
<i class="item-icon" :class="icon" :style="style">
<slot></slot>
</i>
</template>
<script>
import iconConstatns from '@/consts/icon.js';
import colorConstatns from '@/consts/color.js';
import { isNumber } from '@/lib/common.js';
export default {
props: [
'iconType',
'iconId',
'color',
'defaultColor',
'additionalColorAttr'
],
computed: {
icon() {
if (this.iconType === 'account') {
return this.getAccountIcon(this.iconId);
} else if (this.iconType === 'category') {
return this.getCategoryIcon(this.iconId);
} else if (this.iconType === 'fixed') {
return this.iconId;
} else {
return '';
}
},
style() {
let defaultColor = 'var(--default-icon-color)';
if (this.defaultColor) {
defaultColor = this.defaultColor;
}
if (this.iconType === 'account') {
return this.getAccountIconStyle(this.color, defaultColor, this.additionalColorAttr);
} else if (this.iconType === 'category') {
return this.getCategoryIconStyle(this.color, defaultColor, this.additionalColorAttr);
} else {
return this.getDefaultIconStyle(this.color, defaultColor, this.additionalColorAttr);
}
}
},
methods: {
getAccountIcon(iconId) {
if (isNumber(iconId)) {
iconId = iconId.toString();
}
if (!iconConstatns.allAccountIcons[iconId]) {
return iconConstatns.defaultAccountIcon.icon;
}
return iconConstatns.allAccountIcons[iconId].icon;
},
getCategoryIcon(iconId) {
if (isNumber(iconId)) {
iconId = iconId.toString();
}
if (!iconConstatns.allCategoryIcons[iconId]) {
return iconConstatns.defaultCategoryIcon.icon;
}
return iconConstatns.allCategoryIcons[iconId].icon;
},
getAccountIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstatns.defaultAccountColor) {
color = '#' + color;
} else {
color = defaultColor;
}
const ret = {
color: color
};
if (additionalColorAttr) {
ret[additionalColorAttr] = color;
}
return ret;
},
getCategoryIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstatns.defaultCategoryColor) {
color = '#' + color;
} else {
color = defaultColor;
}
const ret = {
color: color
};
if (additionalColorAttr) {
ret[additionalColorAttr] = color;
}
return ret;
},
getDefaultIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstatns.defaultColor) {
color = '#' + color;
} else {
color = defaultColor;
}
const ret = {
color: color
};
if (additionalColorAttr) {
ret[additionalColorAttr] = color;
}
return ret;
}
}
}
</script>
<style>
.item-icon {
font-size: var(--ebk-icon-font-size);
display: inline-block;
vertical-align: middle;
background-size: 100% auto;
background-position: center;
background-repeat: no-repeat;
font-style: normal;
position: relative;
}
</style>
+99
View File
@@ -0,0 +1,99 @@
<template>
<div class="d-flex" :style="`min-width: ${minWidth}px`" v-if="minWidth"></div>
<v-slide-group class="slide-group-with-stepper mb-10 hidden-xs" show-arrows>
<v-slide-group-item :key="idx" v-for="(step, idx) in steps">
<div class="cursor-pointer mx-1"
:class="{ 'slide-group-step-active': isStepActive(step), 'slide-group-step-completed': isStepCompleted(idx) }"
@click="changeStep(step)">
<div class="d-flex align-center gap-x-2">
<div class="d-flex align-center gap-2">
<div class="d-flex align-center justify-center" style="block-size: 24px; inline-size: 24px;">
<div class="slide-group-stepper-indicator"></div>
</div>
<h4 class="text-h4 step-number">{{ `0${idx + 1}` }}</h4>
</div>
<div style="line-height: 0;">
<h6 class="text-sm font-weight-medium step-title">{{ step.title }}</h6>
<span class="text-xs step-subtitle">{{ step.subTitle }}</span>
</div>
<div class="slide-group-stepper-link-line" v-if="idx < steps.length - 1"></div>
</div>
</div>
</v-slide-group-item>
</v-slide-group>
<v-slide-group class="slide-group-with-stepper mb-3 hidden-sm-and-up" direction="vertical">
<v-slide-group-item :key="idx" v-for="(step, idx) in steps">
<div class="cursor-pointer mx-1 mb-3"
:class="{ 'slide-group-step-active': isStepActive(step), 'slide-group-step-completed': isStepCompleted(idx) }"
@click="changeStep(step)">
<div class="d-flex align-center gap-x-2">
<div class="d-flex align-center gap-2">
<div class="d-flex align-center justify-center" style="block-size: 24px; inline-size: 24px;">
<div class="slide-group-stepper-indicator"></div>
</div>
<h4 class="text-h4 step-number">{{ `0${idx + 1}` }}</h4>
</div>
<div style="line-height: 0;">
<h6 class="text-sm font-weight-medium step-title">{{ step.title }}</h6>
<span class="text-xs step-subtitle">{{ step.subTitle }}</span>
</div>
</div>
</div>
</v-slide-group-item>
</v-slide-group>
</template>
<script>
export default {
props: [
'steps',
'currentStep',
'minWidth'
],
emits: [
'step:change'
],
methods: {
changeStep(step) {
this.$emit('step:change', step.name);
},
isStepActive(step) {
return this.currentStep === step.name;
},
isStepCompleted(stepIndex) {
for (let i = 0; i < this.steps.length; i++) {
if (this.steps[i].name === this.currentStep) {
return stepIndex < i;
}
}
return false;
}
}
}
</script>
<style>
.slide-group-with-stepper .v-slide-group__content .slide-group-stepper-link-line {
background-color: rgb(var(--v-theme-primary));
border-radius: 0.1875rem;
block-size: .1875rem;
inline-size: 3.75rem;
opacity: var(--v-activated-opacity);
}
.slide-group-with-stepper .v-slide-group__content .slide-group-stepper-indicator {
background-color: rgb(var(--v-theme-surface));
border: 0.3125rem solid rgb(var(--v-theme-primary));
border-radius: 50%;
block-size: 1.25rem;
inline-size: 1.25rem;
opacity: var(--v-activated-opacity);
}
.slide-group-with-stepper .v-slide-group__content .slide-group-step-completed .slide-group-stepper-indicator,
.slide-group-with-stepper .v-slide-group__content .slide-group-step-active .slide-group-stepper-indicator,
.slide-group-with-stepper .v-slide-group__content .slide-group-step-completed .slide-group-stepper-link-line {
opacity: 1;
}
</style>
+13
View File
@@ -12,6 +12,7 @@ import { VCard, VCardActions, VCardItem, VCardSubtitle, VCardText, VCardTitle }
import { VChip } from 'vuetify/components/VChip';
import { VDialog } from 'vuetify/components/VDialog';
import { VDivider } from 'vuetify/components/VDivider';
import { VExpansionPanel, VExpansionPanelText, VExpansionPanelTitle, VExpansionPanels } from 'vuetify/components/VExpansionPanel';
import { VForm } from 'vuetify/components/VForm';
import { VContainer, VCol, VRow, VSpacer } from 'vuetify/components/VGrid';
import { VIcon } from 'vuetify/components/VIcon';
@@ -26,6 +27,7 @@ import { VProgressCircular } from 'vuetify/components/VProgressCircular';
import { VProgressLinear } from 'vuetify/components/VProgressLinear';
import { VSelect } from 'vuetify/components/VSelect';
import { VSheet } from 'vuetify/components/VSheet';
import { VSlideGroup, VSlideGroupItem } from 'vuetify/components/VSlideGroup';
import { VSnackbar } from 'vuetify/components/VSnackbar';
import { VSwitch } from 'vuetify/components/VSwitch';
import { VTabs, VTab } from 'vuetify/components/VTabs';
@@ -58,7 +60,9 @@ import {
import PinCodeInput from '@/components/common/PinCodeInput.vue';
import ItemIcon from '@/components/desktop/ItemIcon.vue';
import AmountInput from '@/components/desktop/AmountInput.vue';
import StepsBar from '@/components/desktop/StepsBar.vue';
import ConfirmDialog from '@/components/desktop/ConfirmDialog.vue';
import SnackBar from '@/components/desktop/SnackBar.vue';
@@ -68,6 +72,7 @@ import '@/styles/desktop/template/layout/index.scss';
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 App from './DesktopApp.vue';
@@ -90,6 +95,10 @@ const vuetify = createVuetify({
VChip,
VDialog,
VDivider,
VExpansionPanel,
VExpansionPanelText,
VExpansionPanelTitle,
VExpansionPanels,
VForm,
VContainer,
VCol,
@@ -115,6 +124,8 @@ const vuetify = createVuetify({
VProgressLinear,
VSelect,
VSheet,
VSlideGroup,
VSlideGroupItem,
VSnackbar,
VSwitch,
VTabs,
@@ -334,7 +345,9 @@ app.component('VueDatePicker', VueDatePicker);
app.component('PinCodeInput', PinCodeInput);
app.component('ItemIcon', ItemIcon);
app.component('AmountInput', AmountInput);
app.component('StepsBar', StepsBar);
app.component('ConfirmDialog', ConfirmDialog);
app.component('SnackBar', SnackBar);
+7
View File
@@ -711,6 +711,8 @@ export default {
'Default': 'Default',
'Done': 'Done',
'Continue': 'Continue',
'Previous': 'Previous',
'Next': 'Next',
'Status': 'Status',
'Enable': 'Enable',
'Enabled': 'Enabled',
@@ -996,8 +998,13 @@ export default {
'Transaction Edit Page': 'Transaction Edit Page',
'Automatically Add Geolocation': 'Automatically Add Geolocation',
'Enable Animation': 'Enable Animation',
'Basic Information': 'Basic Information',
'User Information': 'User Information',
'Enter Your Basic Information': 'Enter Your Basic Information',
'Use preset transaction categories': 'Use preset transaction categories',
'Use Preset Transaction Categories': 'Use Preset Transaction Categories',
'Preset Categories': 'Preset Categories',
'Set Whether You Use The Preset Transaction Categories': 'Set Whether You Use The Preset Transaction Categories',
'You have been successfully registered': 'You have been successfully registered',
'You have been successfully registered, but something wrong with adding preset categories. You can re-add preset categories in settings page anytime.': 'You have been successfully registered, but something wrong with adding preset categories. You can re-add preset categories in settings page anytime.',
'Unable to sign up': 'Unable to sign up',
+7
View File
@@ -711,6 +711,8 @@ export default {
'Default': '默认',
'Done': '完成',
'Continue': '继续',
'Previous': '上一步',
'Next': '下一步',
'Status': '状态',
'Enable': '启用',
'Enabled': '启用',
@@ -996,8 +998,13 @@ export default {
'Transaction Edit Page': '交易编辑页面',
'Automatically Add Geolocation': '自动添加地理位置',
'Enable Animation': '启用动画',
'Basic Information': '基本信息',
'User Information': '用户信息',
'Enter Your Basic Information': '输入您的基本信息',
'Use preset transaction categories': '使用预设交易分类',
'Use Preset Transaction Categories': '使用预设交易分类',
'Preset Categories': '预设分类',
'Set Whether You Use The Preset Transaction Categories': '设置是否使用预设交易分类',
'You have been successfully registered': '注册成功',
'You have been successfully registered, but something wrong with adding preset categories. You can re-add preset categories in settings page anytime.': '注册成功,但是添加预设分类时出错。您可以随时在设置页面中重新添加预设分类。',
'Unable to sign up': '无法注册',
+3
View File
@@ -0,0 +1,3 @@
:root {
--ebk-icon-font-size: 28px;
}
+6
View File
@@ -11,6 +11,12 @@
pointer-events: none !important;
}
@media (min-width: 600px) {
.text-right-sm {
text-align: right !important;
}
}
/** custom class **/
.pin-codes-input {
--ebk-pin-code-input-height: 56px;
+515 -3
View File
@@ -1,13 +1,525 @@
<template>
<div class="auth-wrapper d-flex align-center justify-center pa-4">
<div class="layout-wrapper">
<router-link class="d-inline" to="/">
<div class="auth-logo d-flex align-start gap-x-3">
<img alt="logo" class="login-page-logo" src="/img/ezbookkeeping-192.png" />
<h1 class="font-weight-medium leading-normal text-2xl">{{ $t('global.app.title') }}</h1>
</div>
</router-link>
<v-row no-gutters class="auth-wrapper">
<v-col cols="12" md="4" class="d-none d-md-flex align-center justify-center position-relative">
<div class="d-flex auth-img-footer" v-if="currentTheme !== 'dark'">
<v-img src="/img/desktop/background.svg"/>
</div>
<div class="d-flex auth-img-footer" v-if="currentTheme === 'dark'">
<v-img src="/img/desktop/background-dark.svg"/>
</div>
<div class="d-flex align-center justify-center w-100 pt-10">
<v-img max-width="320px" src="/img/desktop/people2.svg"/>
</div>
</v-col>
<v-col cols="12" md="8" class="auth-card d-flex align-center justify-center pa-10">
<v-card variant="flat" class="mt-12 mt-sm-0 pt-sm-12 pt-md-0">
<StepsBar min-width="700" :steps="[
{
'name': 'basicSetting',
'title': $t('User Information'),
'subTitle': $t('Basic Information')
},
{
'name': 'presetCategories',
'title': $t('Transaction Categories'),
'subTitle': $t('Preset Categories')
}
]" :current-step="currentStep" @step:change="switchToTab" />
<v-window class="mt-5 disable-tab-transition" style="max-width: 700px" v-model="currentStep">
<v-form>
<v-window-item value="basicSetting">
<h5 class="text-h5 mb-1">{{ $t('Basic Information') }}</h5>
<p class="text-sm mb-5">{{ $t('Enter Your Basic Information') }}</p>
<v-row>
<v-col cols="12" md="6">
<v-text-field
type="text"
autocomplete="username"
clearable
:disabled="submitting"
:label="$t('Username')"
:placeholder="$t('Your username')"
v-model="user.username"
/>
</v-col>
<v-col cols="12" md="6">
<v-text-field
type="text"
autocomplete="nickname"
clearable
:disabled="submitting"
:label="$t('Nickname')"
:placeholder="$t('Your nickname')"
v-model="user.nickname"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="12">
<v-text-field
type="email"
autocomplete="email"
clearable
:disabled="submitting"
:label="$t('E-mail')"
:placeholder="$t('Your email address')"
v-model="user.email"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="6">
<v-text-field
autocomplete="new-password"
clearable
:disabled="submitting"
:label="$t('Password')"
:placeholder="$t('Your password, at least 6 characters')"
:type="isPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isPasswordVisible ? icons.eyeSlash : icons.eye"
v-model="user.password"
@click:append-inner="isPasswordVisible = !isPasswordVisible"
/>
</v-col>
<v-col cols="12" md="6">
<v-text-field
autocomplete="new-password"
clearable
:disabled="submitting"
:label="$t('Confirmation Password')"
:placeholder="$t('Re-enter the password')"
:type="isConfirmPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isConfirmPasswordVisible ? icons.eyeSlash : icons.eye"
v-model="user.confirmPassword"
@click:append-inner="isConfirmPasswordVisible = !isConfirmPasswordVisible"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="12">
<v-select
item-title="displayName"
item-value="code"
:disabled="submitting"
:label="$t('Language')"
:placeholder="$t('Language')"
:items="allLanguages"
v-model="currentLocale"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="6">
<v-autocomplete
item-title="displayName"
item-value="code"
:disabled="submitting"
:label="$t('Default Currency')"
:placeholder="$t('Default Currency')"
:items="allCurrencies"
:no-data-text="$t('No results')"
v-model="user.defaultCurrency"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
:disabled="submitting"
:label="$t('First Day of Week')"
:placeholder="$t('First Day of Week')"
:items="allWeekDays"
v-model="user.firstDayOfWeek"
/>
</v-col>
</v-row>
</v-window-item>
<v-window-item value="presetCategories" class="signup-preset-categories">
<h5 class="text-h5 mb-1">{{ $t('Preset Categories') }}</h5>
<p class="text-sm mb-5">{{ $t('Set Whether You Use The Preset Transaction Categories') }}</p>
<v-row class="mb-5">
<v-col cols="12" sm="6">
<v-switch inset :label="$t('Use Preset Transaction Categories')"
v-model="usePresetCategories"/>
</v-col>
<v-col cols="12" sm="6" class="text-right-sm">
<v-menu location="bottom">
<template #activator="{ props }">
<v-btn variant="text" v-bind="props">{{ currentLanguageName }}</v-btn>
</template>
<v-list>
<v-list-item v-for="lang in allLanguages" :key="lang.code">
<v-list-item-title
class="cursor-pointer"
@click="currentLocale = lang.code">
{{ lang.displayName }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-col>
</v-row>
<div class="overflow-y-auto px-3" :class="{ 'disabled': !usePresetCategories }" style="max-height: 323px">
<v-row :key="categoryType" v-for="(categories, categoryType) in presetCategories">
<v-col cols="12" md="12">
<h4 class="mb-3">{{ getCategoryTypeName(categoryType) }}</h4>
<v-expansion-panels variant="accordion" multiple>
<v-expansion-panel :key="idx" v-for="(category, idx) in categories">
<v-expansion-panel-title class="py-0">
<ItemIcon icon-type="category" :icon-id="category.categoryIconId" :color="category.color"></ItemIcon>
<span class="ml-3">{{ $t('category.' + category.name) }}</span>
</v-expansion-panel-title>
<v-expansion-panel-text v-if="category.subCategories.length">
<v-list rounded density="comfortable" class="pa-0">
<template :key="subIdx"
v-for="(subCategory, subIdx) in category.subCategories">
<v-list-item>
<template #prepend>
<ItemIcon icon-type="category" :icon-id="subCategory.categoryIconId" :color="subCategory.color"></ItemIcon>
</template>
<span class="ml-3">{{ $t('category.' + subCategory.name) }}</span>
</v-list-item>
<v-divider v-if="subIdx !== category.subCategories.length - 1"/>
</template>
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</v-col>
</v-row>
</div>
</v-window-item>
</v-form>
</v-window>
<div class="d-flex justify-sm-space-between gap-4 flex-wrap justify-center mt-5">
<v-btn :color="currentStep === 'basicSetting' ? 'default' : 'primary'"
:disabled="currentStep === 'basicSetting'"
:prepend-icon="icons.previous"
@click="switchToPreviousTab">{{ $t('Previous') }}</v-btn>
<v-btn :color="currentStep === 'presetCategories' ? 'secondary' : 'primary'"
:disabled="currentStep === 'presetCategories'"
:append-icon="icons.next"
@click="switchToNextTab"
v-if="currentStep !== 'presetCategories'">{{ $t('Next') }}</v-btn>
<v-btn color="expense"
:disabled="submitting"
:append-icon="icons.submit"
@click="submit"
v-if="currentStep === 'presetCategories'">{{ $t('Submit') }}</v-btn>
</div>
</v-card>
</v-col>
</v-row>
<snack-bar ref="snackbar" />
<v-overlay class="justify-center align-center" :persistent="true" v-model="submitting">
<v-progress-circular indeterminate></v-progress-circular>
</v-overlay>
</div>
</template>
<script>
export default {
created() {
import { useTheme } from 'vuetify';
import { mapStores } from 'pinia';
import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.js';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import categoryConstants from '@/consts/category.js';
import { getNameByKeyValue, copyArrayTo } from '@/lib/common.js';
import {
mdiArrowLeft,
mdiArrowRight,
mdiCheck,
mdiEyeOffOutline,
mdiEyeOutline
} from '@mdi/js';
export default {
data() {
const self = this;
const settingsStore = useSettingsStore();
return {
user: {
username: '',
password: '',
confirmPassword: '',
email: '',
nickname: '',
language: self.$i18n.locale,
defaultCurrency: settingsStore.localeDefaultSettings.currency,
firstDayOfWeek: settingsStore.localeDefaultSettings.firstDayOfWeek,
},
currentStep: 'basicSetting',
isPasswordVisible: false,
isConfirmPasswordVisible: false,
submitting: false,
presetCategories: {
[categoryConstants.allCategoryTypes.Income]: copyArrayTo(categoryConstants.defaultIncomeCategories, []),
[categoryConstants.allCategoryTypes.Expense]: copyArrayTo(categoryConstants.defaultExpenseCategories, []),
[categoryConstants.allCategoryTypes.Transfer]: copyArrayTo(categoryConstants.defaultTransferCategories, [])
},
usePresetCategories: false,
icons: {
previous: mdiArrowLeft,
next: mdiArrowRight,
submit: mdiCheck,
eye: mdiEyeOutline,
eyeSlash: mdiEyeOffOutline
}
};
},
computed: {
...mapStores(useRootStore, useSettingsStore, useTransactionCategoriesStore, useExchangeRatesStore),
allLanguages() {
return this.$locale.getAllLanguageInfoArray(false);
},
allCurrencies() {
return this.$locale.getAllCurrencies();
},
allWeekDays() {
return this.$locale.getAllWeekDays();
},
currentLocale: {
get: function () {
return this.$i18n.locale;
},
set: function (value) {
const isCurrencyDefault = this.user.defaultCurrency === this.settingsStore.localeDefaultSettings.currency;
const isFirstWeekDayDefault = this.user.firstDayOfWeek === this.settingsStore.localeDefaultSettings.firstDayOfWeek;
this.user.language = value;
const localeDefaultSettings = this.$locale.setLanguage(value);
this.settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings);
if (isCurrencyDefault) {
this.user.defaultCurrency = this.settingsStore.localeDefaultSettings.currency;
}
if (isFirstWeekDayDefault) {
this.user.firstDayOfWeek = this.settingsStore.localeDefaultSettings.firstDayOfWeek;
}
}
},
currentTheme: {
get: function () {
return this.globalTheme.global.name.value;
}
},
currentLanguageName() {
const languageInfo = this.$locale.getLanguageInfo(this.currentLocale);
if (!languageInfo) {
return '';
}
return languageInfo.displayName;
},
currentDayOfWeekName() {
return getNameByKeyValue(this.allWeekDays, this.user.firstDayOfWeek, 'type', 'displayName');
},
inputIsEmpty() {
return !!this.inputEmptyProblemMessage;
},
inputIsInvalid() {
return !!this.inputInvalidProblemMessage;
},
inputEmptyProblemMessage() {
if (!this.user.username) {
return 'Username cannot be empty';
} else if (!this.user.nickname) {
return 'Nickname cannot be empty';
} else if (!this.user.email) {
return 'Email address cannot be empty';
} else if (!this.user.password) {
return 'Password cannot be empty';
} else if (!this.user.confirmPassword) {
return 'Confirmation password cannot be empty';
} else if (!this.user.defaultCurrency) {
return 'Default currency cannot be empty';
} else {
return null;
}
},
inputInvalidProblemMessage() {
if (this.user.password && this.user.confirmPassword && this.user.password !== this.user.confirmPassword) {
return 'Password and confirmation password do not match';
} else {
return null;
}
}
},
setup() {
const theme = useTheme();
return {
globalTheme: theme
};
},
methods: {
switchToTab(tabName) {
if (tabName === 'basicSetting') {
this.currentStep = 'basicSetting';
} else if (tabName === 'presetCategories') {
const problemMessage = this.inputEmptyProblemMessage || this.inputInvalidProblemMessage;
if (problemMessage) {
this.$refs.snackbar.showMessage(problemMessage);
return;
}
this.currentStep = 'presetCategories';
}
},
switchToPreviousTab() {
this.switchToTab('basicSetting');
},
switchToNextTab() {
this.switchToTab('presetCategories');
},
submit() {
const self = this;
const router = self.f7router;
const problemMessage = self.inputEmptyProblemMessage || self.inputInvalidProblemMessage;
if (problemMessage) {
self.$refs.snackbar.showMessage(problemMessage);
return;
}
self.submitting = true;
const allCategories = [];
if (self.usePresetCategories) {
for (let categoryType in self.presetCategories) {
if (!Object.prototype.hasOwnProperty.call(self.presetCategories, categoryType)) {
continue;
}
const categories = self.presetCategories[categoryType];
for (let j = 0; j < categories.length; j++) {
const category = categories[j];
const submitCategory = {
name: self.$t('category.' + category.name),
type: parseInt(categoryType),
icon: category.categoryIconId,
color: category.color,
subCategories: []
}
for (let k = 0; k < category.subCategories.length; k++) {
const subCategory = category.subCategories[k];
submitCategory.subCategories.push({
name: self.$t('category.' + subCategory.name),
type: parseInt(categoryType),
icon: subCategory.categoryIconId,
color: subCategory.color
});
}
allCategories.push(submitCategory);
}
}
}
self.rootStore.register({
user: self.user
}).then(response => {
if (!self.$user.isUserLogined()) {
self.submitting = false;
if (self.usePresetCategories) {
self.$refs.snackbar.showMessage('You have been successfully registered, but something wrong with adding preset categories. You can re-add preset categories in settings page anytime.');
} else {
self.$refs.snackbar.showMessage('You have been successfully registered');
}
this.$router.replace('/');
return;
}
if (response.user) {
const localeDefaultSettings = self.$locale.setLanguage(response.user.language);
self.settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings);
}
if (self.settingsStore.appSettings.autoUpdateExchangeRatesData) {
self.exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
}
if (!self.usePresetCategories) {
self.submitting = false;
self.$refs.snackbar.showMessage('You have been successfully registered');
this.$router.replace('/');
return;
}
self.transactionCategoriesStore.addCategories({
categories: allCategories
}).then(() => {
self.submitting = false;
self.$refs.snackbar.showMessage('You have been successfully registered');
router.navigate('/');
}).catch(() => {
self.submitting = false;
self.$refs.snackbar.showMessage('You have been successfully registered, but something wrong with adding preset categories. You can re-add preset categories in settings page anytime.');
this.$router.replace('/');
});
}).catch(error => {
self.submitting = false;
if (!error.processed) {
self.$refs.snackbar.showError(error);
}
});
},
getCategoryTypeName(categoryType) {
switch (categoryType) {
case categoryConstants.allCategoryTypes.Income.toString():
return this.$t('Income Categories');
case categoryConstants.allCategoryTypes.Expense.toString():
return this.$t('Expense Categories');
case categoryConstants.allCategoryTypes.Transfer.toString():
return this.$t('Transfer Categories');
default:
return this.$t('Transaction Categories');
}
}
}
}
</script>
<style>
.signup-preset-categories .v-expansion-panel-text__wrapper {
padding: 0 0 0 20px;
}
</style>