mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-20 17:54:30 +08:00
add category preset for desktop page
This commit is contained in:
@@ -106,7 +106,7 @@
|
|||||||
<div class="d-flex align-center">
|
<div class="d-flex align-center">
|
||||||
<span>{{ $t('No available category') }}</span>
|
<span>{{ $t('No available category') }}</span>
|
||||||
<v-btn class="ml-3" color="default" variant="outlined"
|
<v-btn class="ml-3" color="default" variant="outlined"
|
||||||
@click="showPresetCategories"
|
@click="showPresetDialog = true"
|
||||||
v-if="hasSubCategories && noCategory">
|
v-if="hasSubCategories && noCategory">
|
||||||
{{ $t('Add Default Categories') }}
|
{{ $t('Add Default Categories') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -178,11 +178,16 @@
|
|||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
|
<preset-category-dialog :category-type="activeCategoryType" v-model:show="showPresetDialog"
|
||||||
|
@category:saved="presetCategorySaved" />
|
||||||
|
|
||||||
<confirm-dialog ref="confirmDialog"/>
|
<confirm-dialog ref="confirmDialog"/>
|
||||||
<snack-bar ref="snackbar" />
|
<snack-bar ref="snackbar" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import PresetCategoryDialog from './categories/PresetCategoryDialog.vue';
|
||||||
|
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
|
|
||||||
@@ -199,6 +204,9 @@ import {
|
|||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
PresetCategoryDialog
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeCategoryType: categoryConstants.allCategoryTypes.Expense,
|
activeCategoryType: categoryConstants.allCategoryTypes.Expense,
|
||||||
@@ -210,6 +218,7 @@ export default {
|
|||||||
categoryRemoving: {},
|
categoryRemoving: {},
|
||||||
displayOrderModified: false,
|
displayOrderModified: false,
|
||||||
showHidden: false,
|
showHidden: false,
|
||||||
|
showPresetDialog: false,
|
||||||
icons: {
|
icons: {
|
||||||
refresh: mdiRefresh,
|
refresh: mdiRefresh,
|
||||||
edit: mdiPencilOutline,
|
edit: mdiPencilOutline,
|
||||||
@@ -395,8 +404,11 @@ export default {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showPresetCategories() {
|
presetCategorySaved(e) {
|
||||||
|
if (e && e.message) {
|
||||||
|
this.$refs.snackbar.showMessage(e.message);
|
||||||
|
this.reload(false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
switchActiveCategoryType(activeCategoryType) {
|
switchActiveCategoryType(activeCategoryType) {
|
||||||
if (this.activeCategoryType === activeCategoryType) {
|
if (this.activeCategoryType === activeCategoryType) {
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<v-dialog scrollable width="600" max-height="600" :persistent="!!persistent" v-model="showState">
|
||||||
|
<v-card>
|
||||||
|
<v-toolbar color="primary">
|
||||||
|
<v-toolbar-title>{{ $t('Default Categories') }}</v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-card-text class="preset-transaction-categories pb-4">
|
||||||
|
<template :key="categoryType" v-for="(categories, categoryType) in allPresetCategories">
|
||||||
|
<div class="d-flex align-center mb-1">
|
||||||
|
<h4>{{ getCategoryTypeName(categoryType) }}</h4>
|
||||||
|
<v-spacer/>
|
||||||
|
<v-menu location="bottom">
|
||||||
|
<template #activator="{ props }">
|
||||||
|
<v-btn variant="text" :disabled="submitting"
|
||||||
|
v-bind="props">{{ currentLanguageName }}</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item :key="locale" :value="locale" v-for="(lang, locale) in allLanguages">
|
||||||
|
<v-list-item-title class="cursor-pointer" @click="currentLocale = locale">
|
||||||
|
{{ lang.displayName }}
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<v-expansion-panels class="border rounded mb-2" variant="accordion" multiple :disabled="submitting">
|
||||||
|
<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.icon" :color="category.color"></ItemIcon>
|
||||||
|
<span class="ml-3">{{ 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.icon" :color="subCategory.color"></ItemIcon>
|
||||||
|
</template>
|
||||||
|
<span class="ml-3">{{ 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>
|
||||||
|
</template>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn color="gray" :disabled="submitting" @click="showState = false">{{ $t('Cancel') }}</v-btn>
|
||||||
|
<v-btn :disabled="submitting" @click="save">
|
||||||
|
{{ $t('Save') }}
|
||||||
|
<v-progress-circular indeterminate size="24" class="ml-2" v-if="submitting"></v-progress-circular>
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
|
|
||||||
|
import categoryConstants from '@/consts/category.js';
|
||||||
|
import { categoriedArrayToPlainArray } from '@/lib/common.js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
mdiDotsVertical
|
||||||
|
} from '@mdi/js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: [
|
||||||
|
'categoryType',
|
||||||
|
'persistent',
|
||||||
|
'show'
|
||||||
|
],
|
||||||
|
emits: [
|
||||||
|
'update:show',
|
||||||
|
'category:saved'
|
||||||
|
],
|
||||||
|
data() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentLocale: self.$locale.getCurrentLanguageCode(),
|
||||||
|
allCategoryTypes: [],
|
||||||
|
submitting: false,
|
||||||
|
icons: {
|
||||||
|
more: mdiDotsVertical
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useTransactionCategoriesStore),
|
||||||
|
showState: {
|
||||||
|
get: function () {
|
||||||
|
return this.show;
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this.$emit('update:show', value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
allLanguages() {
|
||||||
|
return this.$locale.getAllLanguageInfos();
|
||||||
|
},
|
||||||
|
allPresetCategories() {
|
||||||
|
return this.$locale.getAllTransactionDefaultCategories(this.categoryType, this.currentLocale);
|
||||||
|
},
|
||||||
|
currentLanguageName() {
|
||||||
|
const languageInfo = this.$locale.getLanguageInfo(this.currentLocale);
|
||||||
|
|
||||||
|
if (!languageInfo) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return languageInfo.displayName;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
save() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
self.submitting = true;
|
||||||
|
|
||||||
|
const submitCategories = categoriedArrayToPlainArray(self.allPresetCategories);
|
||||||
|
|
||||||
|
self.transactionCategoriesStore.addCategories({
|
||||||
|
categories: submitCategories
|
||||||
|
}).then(() => {
|
||||||
|
self.submitting = false;
|
||||||
|
self.showState = false;
|
||||||
|
|
||||||
|
this.$emit('category:saved', {
|
||||||
|
message: 'You have added preset categories'
|
||||||
|
});
|
||||||
|
}).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>
|
||||||
|
.preset-transaction-categories .v-expansion-panel-text__wrapper {
|
||||||
|
padding: 0 0 0 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user