mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-17 00:12:11 +08:00
add add/edit transaction category dialog
This commit is contained in:
@@ -170,7 +170,8 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<preset-category-dialog :category-type="activeCategoryType" v-model:show="showPresetDialog"
|
||||
<edit-dialog ref="editDialog" :persistent="true" />
|
||||
<preset-dialog :category-type="activeCategoryType" v-model:show="showPresetDialog"
|
||||
@category:saved="presetCategorySaved" />
|
||||
|
||||
<confirm-dialog ref="confirmDialog"/>
|
||||
@@ -178,7 +179,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PresetCategoryDialog from './list/dialogs/PresetDialog.vue';
|
||||
import EditDialog from './list/dialogs/EditDialog.vue';
|
||||
import PresetDialog from './list/dialogs/PresetDialog.vue';
|
||||
|
||||
import { useDisplay } from 'vuetify';
|
||||
|
||||
@@ -201,7 +203,8 @@ import {
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PresetCategoryDialog
|
||||
EditDialog,
|
||||
PresetDialog
|
||||
},
|
||||
data() {
|
||||
const { mdAndUp } = useDisplay();
|
||||
@@ -376,10 +379,36 @@ export default {
|
||||
});
|
||||
},
|
||||
add() {
|
||||
const self = this;
|
||||
|
||||
self.$refs.editDialog.open({
|
||||
type: self.activeCategoryType,
|
||||
parentId: self.primaryCategoryId
|
||||
}).then(result => {
|
||||
if (result && result.message) {
|
||||
self.$refs.snackbar.showMessage(result.message);
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error) {
|
||||
self.$refs.snackbar.showError(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
edit() {
|
||||
edit(category) {
|
||||
const self = this;
|
||||
|
||||
self.$refs.editDialog.open({
|
||||
id: category.id,
|
||||
currentCategory: category
|
||||
}).then(result => {
|
||||
if (result && result.message) {
|
||||
self.$refs.snackbar.showMessage(result.message);
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error) {
|
||||
self.$refs.snackbar.showError(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
hide(category, hidden) {
|
||||
const self = this;
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<v-dialog width="600" :persistent="!!persistent" v-model="showState">
|
||||
<v-card>
|
||||
<v-toolbar color="primary">
|
||||
<v-toolbar-title>
|
||||
<span>{{ $t(title) }}</span>
|
||||
<v-progress-circular indeterminate size="22" class="ml-2" v-if="loading"></v-progress-circular>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-card-text class="pa-4 mt-2">
|
||||
<v-row>
|
||||
<v-col cols="12" md="12">
|
||||
<v-text-field
|
||||
type="text"
|
||||
clearable
|
||||
persistent-placeholder
|
||||
:disabled="loading || submitting"
|
||||
:label="$t('Category Name')"
|
||||
:placeholder="$t('Category Name')"
|
||||
v-model="category.name"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<icon-select :all-icon-infos="allCategoryIcons"
|
||||
:label="$t('Category Icon')"
|
||||
:color="category.color"
|
||||
:disabled="loading || submitting"
|
||||
v-model="category.icon" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<color-select :all-color-infos="allCategoryColors"
|
||||
:label="$t('Category Color')"
|
||||
:disabled="loading || submitting"
|
||||
v-model="category.color" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="12">
|
||||
<v-textarea
|
||||
type="text"
|
||||
persistent-placeholder
|
||||
:disabled="loading || submitting"
|
||||
:label="$t('Description')"
|
||||
:placeholder="$t('Your category description (optional)')"
|
||||
v-model="category.comment"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col class="pt-0" cols="12" md="12" v-if="editCategoryId">
|
||||
<v-switch inset :disabled="loading || submitting"
|
||||
:label="$t('Visible')" v-model="category.visible"/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="gray" :disabled="loading || submitting" @click="cancel">{{ $t('Cancel') }}</v-btn>
|
||||
<v-btn :disabled="inputIsEmpty || loading || submitting" @click="save">
|
||||
{{ $t(saveButtonTitle) }}
|
||||
<v-progress-circular indeterminate size="24" class="ml-2" v-if="submitting"></v-progress-circular>
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<snack-bar ref="snackbar" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||
|
||||
import categoryConstants from '@/consts/category.js';
|
||||
import iconConstants from '@/consts/icon.js';
|
||||
import colorConstants from '@/consts/color.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'persistent',
|
||||
'show'
|
||||
],
|
||||
expose: [
|
||||
'open'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
showState: false,
|
||||
editCategoryId: null,
|
||||
loading: false,
|
||||
category: {
|
||||
type: categoryConstants.allCategoryTypes.Income,
|
||||
name: '',
|
||||
parentId: '0',
|
||||
icon: iconConstants.defaultCategoryIconId,
|
||||
color: colorConstants.defaultCategoryColor,
|
||||
comment: '',
|
||||
visible: true
|
||||
},
|
||||
submitting: false,
|
||||
resolve: null,
|
||||
reject: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTransactionCategoriesStore),
|
||||
title() {
|
||||
if (!this.editCategoryId) {
|
||||
if (this.category.parentId === '0') {
|
||||
return 'Add Primary Category';
|
||||
} else {
|
||||
return 'Add Secondary Category';
|
||||
}
|
||||
} else {
|
||||
return 'Edit Category';
|
||||
}
|
||||
},
|
||||
saveButtonTitle() {
|
||||
if (!this.editCategoryId) {
|
||||
return 'Add';
|
||||
} else {
|
||||
return 'Save';
|
||||
}
|
||||
},
|
||||
allCategoryIcons() {
|
||||
return iconConstants.allCategoryIcons;
|
||||
},
|
||||
allCategoryColors() {
|
||||
return colorConstants.allCategoryColors;
|
||||
},
|
||||
inputIsEmpty() {
|
||||
return !!this.inputEmptyProblemMessage;
|
||||
},
|
||||
inputEmptyProblemMessage() {
|
||||
if (!this.category.name) {
|
||||
return 'Category name cannot be empty';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open(options) {
|
||||
const self = this;
|
||||
self.showState = true;
|
||||
self.loading = true;
|
||||
self.submitting = false;
|
||||
|
||||
self.category.id = null;
|
||||
self.category.type = categoryConstants.allCategoryTypes.Income;
|
||||
self.category.parentId = '0';
|
||||
self.category.name = '';
|
||||
self.category.icon = iconConstants.defaultCategoryIconId;
|
||||
self.category.color = colorConstants.defaultCategoryColor;
|
||||
self.category.comment = '';
|
||||
self.category.visible = true;
|
||||
|
||||
if (options.id) {
|
||||
if (options.currentCategory) {
|
||||
self.setCategory(options.currentCategory);
|
||||
}
|
||||
|
||||
self.editCategoryId = options.id;
|
||||
self.transactionCategoriesStore.getCategory({
|
||||
categoryId: self.editCategoryId
|
||||
}).then(category => {
|
||||
self.setCategory(category);
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.loading = false;
|
||||
self.showState = false;
|
||||
|
||||
if (!error.processed) {
|
||||
if (self.reject) {
|
||||
self.reject(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (options.parentId) {
|
||||
self.editCategoryId = null;
|
||||
|
||||
const categoryType = parseInt(options.type);
|
||||
|
||||
if (categoryType !== categoryConstants.allCategoryTypes.Income &&
|
||||
categoryType !== categoryConstants.allCategoryTypes.Expense &&
|
||||
categoryType !== categoryConstants.allCategoryTypes.Transfer) {
|
||||
self.loading = false;
|
||||
self.showState = false;
|
||||
|
||||
if (self.reject) {
|
||||
self.reject('Parameter Invalid');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self.category.type = categoryType;
|
||||
self.category.parentId = options.parentId;
|
||||
|
||||
self.loading = false;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
self.resolve = resolve;
|
||||
self.reject = reject;
|
||||
});
|
||||
},
|
||||
save() {
|
||||
const self = this;
|
||||
|
||||
const problemMessage = self.inputEmptyProblemMessage;
|
||||
|
||||
if (problemMessage) {
|
||||
self.$refs.snackbar.showMessage(problemMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
self.submitting = true;
|
||||
|
||||
const submitCategory = {
|
||||
type: self.category.type,
|
||||
name: self.category.name,
|
||||
parentId: self.category.parentId,
|
||||
icon: self.category.icon,
|
||||
color: self.category.color,
|
||||
comment: self.category.comment
|
||||
};
|
||||
|
||||
if (self.editCategoryId) {
|
||||
submitCategory.id = self.category.id;
|
||||
submitCategory.hidden = !self.category.visible;
|
||||
}
|
||||
|
||||
self.transactionCategoriesStore.saveCategory({
|
||||
category: submitCategory
|
||||
}).then(() => {
|
||||
self.submitting = false;
|
||||
|
||||
let message = 'You have saved this category';
|
||||
|
||||
if (!self.editCategoryId) {
|
||||
message = 'You have added a new category';
|
||||
}
|
||||
|
||||
if (self.resolve) {
|
||||
self.resolve({
|
||||
message: message
|
||||
});
|
||||
}
|
||||
|
||||
self.showState = false;
|
||||
}).catch(error => {
|
||||
self.submitting = false;
|
||||
|
||||
if (!error.processed) {
|
||||
self.$refs.snackbar.showError(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
cancel() {
|
||||
if (this.reject) {
|
||||
this.reject();
|
||||
}
|
||||
|
||||
this.showState = false;
|
||||
},
|
||||
setCategory(category) {
|
||||
this.category.id = category.id;
|
||||
this.category.type = category.type;
|
||||
this.category.parentId = category.type.parentId;
|
||||
this.category.name = category.name;
|
||||
this.category.icon = category.icon;
|
||||
this.category.color = category.color;
|
||||
this.category.comment = category.comment;
|
||||
this.category.visible = !category.hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -351,7 +351,7 @@ import {
|
||||
categoryTypeToTransactionType,
|
||||
transactionTypeToCategoryType
|
||||
} from '@/lib/category.js';
|
||||
import { scrollToMenuListItem } from '@/lib/ui.desktop.js';
|
||||
import { scrollToSelectedItem } from '@/lib/ui.desktop.js';
|
||||
|
||||
import {
|
||||
mdiMagnify,
|
||||
@@ -816,7 +816,7 @@ export default {
|
||||
},
|
||||
scrollMenuToSelectedItem(menu) {
|
||||
this.$nextTick(() => {
|
||||
scrollToMenuListItem(menu.contentEl);
|
||||
scrollToSelectedItem(menu.contentEl, 'div.v-list', 'div.v-list-item.list-item-selected');
|
||||
});
|
||||
},
|
||||
getDisplayTime(transaction) {
|
||||
|
||||
Reference in New Issue
Block a user