migrate transaction tag sheet to composition API and typescript
This commit is contained in:
@@ -5,17 +5,17 @@
|
|||||||
<f7-toolbar>
|
<f7-toolbar>
|
||||||
<div class="swipe-handler"></div>
|
<div class="swipe-handler"></div>
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<f7-link sheet-close :text="$t('Cancel')"></f7-link>
|
<f7-link sheet-close :text="tt('Cancel')"></f7-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<f7-link :text="$t('Done')" v-if="allTags && allTags.length && !noAvailableTag" @click="save"></f7-link>
|
<f7-link :text="tt('Done')" v-if="allTags && allTags.length && !noAvailableTag" @click="save"></f7-link>
|
||||||
<f7-link :class="{'disabled': newTag}"
|
<f7-link :class="{'disabled': newTag}"
|
||||||
:text="$t('Add')" v-if="!allTags || !allTags.length || noAvailableTag" @click="addNewTag"></f7-link>
|
:text="tt('Add')" v-if="!allTags || !allTags.length || noAvailableTag" @click="addNewTag"></f7-link>
|
||||||
</div>
|
</div>
|
||||||
</f7-toolbar>
|
</f7-toolbar>
|
||||||
<f7-page-content>
|
<f7-page-content>
|
||||||
<f7-list class="no-margin-top no-margin-bottom" v-if="(!allTags || !allTags.length || noAvailableTag) && !newTag">
|
<f7-list class="no-margin-top no-margin-bottom" v-if="(!allTags || !allTags.length || noAvailableTag) && !newTag">
|
||||||
<f7-list-item :title="$t('No available tag')"></f7-list-item>
|
<f7-list-item :title="tt('No available tag')"></f7-list-item>
|
||||||
</f7-list>
|
</f7-list>
|
||||||
<f7-list dividers class="no-margin-top no-margin-bottom tag-selection-list" v-else-if="(allTags && allTags.length && !noAvailableTag) || newTag">
|
<f7-list dividers class="no-margin-top no-margin-bottom tag-selection-list" v-else-if="(allTags && allTags.length && !noAvailableTag) || newTag">
|
||||||
<f7-list-item checkbox
|
<f7-list-item checkbox
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
</f7-block>
|
</f7-block>
|
||||||
</template>
|
</template>
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
<f7-list-item :title="$t('Add new tag')"
|
<f7-list-item :title="tt('Add new tag')"
|
||||||
v-if="allowAddNewTag && !newTag"
|
v-if="allowAddNewTag && !newTag"
|
||||||
@click="addNewTag()">
|
@click="addNewTag()">
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
<div class="display-flex">
|
<div class="display-flex">
|
||||||
<f7-input class="list-title-input padding-left-half"
|
<f7-input class="list-title-input padding-left-half"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('Tag Title')"
|
:placeholder="tt('Tag Title')"
|
||||||
v-model:value="newTag.name"
|
v-model:value="newTag.name"
|
||||||
@keyup.enter="saveNewTag()">
|
@keyup.enter="saveNewTag()">
|
||||||
</f7-input>
|
</f7-input>
|
||||||
@@ -75,131 +75,126 @@
|
|||||||
</f7-sheet>
|
</f7-sheet>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapStores } from 'pinia';
|
import { ref, computed } from 'vue';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
|
||||||
|
import { useI18n } from '@/locales/helpers.ts';
|
||||||
|
import { useI18nUIComponents, showLoading, hideLoading } from '@/lib/ui/mobile.ts';
|
||||||
|
|
||||||
import { TransactionTag } from '@/models/transaction_tag.ts';
|
import { TransactionTag } from '@/models/transaction_tag.ts';
|
||||||
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
|
|
||||||
import { copyArrayTo } from '@/lib/common.ts';
|
import { copyArrayTo } from '@/lib/common.ts';
|
||||||
import { scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
import { type Framework7Dom, scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
||||||
|
|
||||||
export default {
|
const props = defineProps<{
|
||||||
props: [
|
modelValue: string[];
|
||||||
'modelValue',
|
allowAddNewTag?: boolean;
|
||||||
'allowAddNewTag',
|
show: boolean;
|
||||||
'show'
|
}>();
|
||||||
],
|
const emit = defineEmits<{
|
||||||
emits: [
|
(e: 'update:modelValue', value: string[]): void;
|
||||||
'update:modelValue',
|
(e: 'update:show', value: boolean): void;
|
||||||
'update:show'
|
}>();
|
||||||
],
|
|
||||||
data() {
|
|
||||||
const self = this;
|
|
||||||
const transactionTagsStore = useTransactionTagsStore();
|
|
||||||
|
|
||||||
return {
|
const { tt } = useI18n();
|
||||||
heightClass: self.getHeightClass(transactionTagsStore.allTransactionTags),
|
const { showToast } = useI18nUIComponents();
|
||||||
selectedItemIds: copyArrayTo(self.modelValue, []),
|
|
||||||
newTag: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapStores(useTransactionTagsStore),
|
|
||||||
allTags() {
|
|
||||||
return this.transactionTagsStore.allTransactionTags;
|
|
||||||
},
|
|
||||||
noAvailableTag() {
|
|
||||||
for (let i = 0; i < this.allTags.length; i++) {
|
|
||||||
if (!this.allTags[i].hidden) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
const transactionTagsStore = useTransactionTagsStore();
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
save() {
|
|
||||||
this.$emit('update:modelValue', this.selectedItemIds);
|
|
||||||
this.$emit('update:show', false);
|
|
||||||
},
|
|
||||||
onSheetOpen(event) {
|
|
||||||
this.selectedItemIds = copyArrayTo(this.modelValue, []);
|
|
||||||
this.newTag = null;
|
|
||||||
scrollToSelectedItem(event.$el, '.page-content', 'li.list-item-selected');
|
|
||||||
},
|
|
||||||
onSheetClosed() {
|
|
||||||
this.$emit('update:show', false);
|
|
||||||
this.heightClass = this.getHeightClass(this.allTags);
|
|
||||||
},
|
|
||||||
changeTagSelection(e) {
|
|
||||||
const tagId = e.target.value;
|
|
||||||
|
|
||||||
if (e.target.checked) {
|
const selectedItemIds = ref<string[]>(copyArrayTo(props.modelValue, []));
|
||||||
for (let i = 0; i < this.selectedItemIds.length; i++) {
|
const newTag = ref<TransactionTag | null>(null);
|
||||||
if (this.selectedItemIds[i] === tagId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectedItemIds.push(tagId);
|
const allTags = computed(() => transactionTagsStore.allTransactionTags);
|
||||||
} else {
|
|
||||||
for (let i = 0; i < this.selectedItemIds.length; i++) {
|
|
||||||
if (this.selectedItemIds[i] === tagId) {
|
|
||||||
this.selectedItemIds.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addNewTag() {
|
|
||||||
this.newTag = TransactionTag.createNewTag();
|
|
||||||
},
|
|
||||||
saveNewTag() {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
self.$showLoading();
|
const noAvailableTag = computed<boolean>(() => {
|
||||||
|
if (transactionTagsStore.allTransactionTags) {
|
||||||
self.transactionTagsStore.saveTag({
|
for (let i = 0; i < transactionTagsStore.allTransactionTags.length; i++) {
|
||||||
tag: self.newTag
|
if (!transactionTagsStore.allTransactionTags[i].hidden) {
|
||||||
}).then(tag => {
|
return false;
|
||||||
self.$hideLoading();
|
|
||||||
self.newTag = null;
|
|
||||||
|
|
||||||
if (tag && tag.id) {
|
|
||||||
self.selectedItemIds.push(tag.id);
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
self.$hideLoading();
|
|
||||||
|
|
||||||
if (!error.processed) {
|
|
||||||
self.$toast(error.message || error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
cancelSaveNewTag() {
|
|
||||||
this.newTag = null;
|
|
||||||
},
|
|
||||||
isChecked(itemId) {
|
|
||||||
for (let i = 0; i < this.selectedItemIds.length; i++) {
|
|
||||||
if (this.selectedItemIds[i] === itemId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
getHeightClass(allTags) {
|
|
||||||
if (allTags && allTags.length > 10) {
|
|
||||||
return 'tag-selection-huge-sheet';
|
|
||||||
} else if (allTags && allTags.length > 6) {
|
|
||||||
return 'tag-selection-large-sheet';
|
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const heightClass = computed<string>(() => {
|
||||||
|
if (transactionTagsStore.allTransactionTags && transactionTagsStore.allTransactionTags.length > 10) {
|
||||||
|
return 'tag-selection-huge-sheet';
|
||||||
|
} else if (transactionTagsStore.allTransactionTags && transactionTagsStore.allTransactionTags.length > 6) {
|
||||||
|
return 'tag-selection-large-sheet';
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function isChecked(itemId: string): boolean {
|
||||||
|
return selectedItemIds.value.indexOf(itemId) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTagSelection(e: Event): void {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
const tagId = target.value;
|
||||||
|
const index = selectedItemIds.value.indexOf(tagId);
|
||||||
|
|
||||||
|
if (target.checked) {
|
||||||
|
if (index < 0) {
|
||||||
|
selectedItemIds.value.push(tagId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index >= 0) {
|
||||||
|
selectedItemIds.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function save(): void {
|
||||||
|
emit('update:modelValue', selectedItemIds.value);
|
||||||
|
emit('update:show', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewTag(): void {
|
||||||
|
newTag.value = TransactionTag.createNewTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveNewTag(): void {
|
||||||
|
if (!newTag.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showLoading();
|
||||||
|
|
||||||
|
transactionTagsStore.saveTag({
|
||||||
|
tag: newTag.value
|
||||||
|
}).then(tag => {
|
||||||
|
hideLoading();
|
||||||
|
newTag.value = null;
|
||||||
|
|
||||||
|
if (tag && tag.id) {
|
||||||
|
selectedItemIds.value.push(tag.id);
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
hideLoading();
|
||||||
|
|
||||||
|
if (!error.processed) {
|
||||||
|
showToast(error.message || error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelSaveNewTag(): void {
|
||||||
|
newTag.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSheetOpen(event: { $el: Framework7Dom }): void {
|
||||||
|
selectedItemIds.value = copyArrayTo(props.modelValue, []);
|
||||||
|
newTag.value = null;
|
||||||
|
scrollToSelectedItem(event.$el, '.page-content', 'li.list-item-selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSheetClosed(): void {
|
||||||
|
emit('update:show', false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -394,7 +394,7 @@ export function copyObjectTo(fromObject: Record<string, unknown> | undefined, to
|
|||||||
return (toObject as Record<string, unknown>);
|
return (toObject as Record<string, unknown>);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function copyArrayTo(fromArray: unknown[], toArray: unknown[]): unknown[] {
|
export function copyArrayTo<T>(fromArray: T[], toArray: T[]): T[] {
|
||||||
if (!isArray(fromArray)) {
|
if (!isArray(fromArray)) {
|
||||||
return toArray;
|
return toArray;
|
||||||
}
|
}
|
||||||
@@ -410,9 +410,9 @@ export function copyArrayTo(fromArray: unknown[], toArray: unknown[]): unknown[]
|
|||||||
const toValue = toArray[i];
|
const toValue = toArray[i];
|
||||||
|
|
||||||
if (isArray(fromValue)) {
|
if (isArray(fromValue)) {
|
||||||
toArray[i] = copyArrayTo(fromValue as unknown[], toValue as unknown[]);
|
toArray[i] = copyArrayTo(fromValue as unknown[], toValue as unknown[]) as T;
|
||||||
} else if (isObject(fromValue)) {
|
} else if (isObject(fromValue)) {
|
||||||
toArray[i] = copyObjectTo(fromValue as Record<string, unknown>, toValue as Record<string, unknown>);
|
toArray[i] = copyObjectTo(fromValue as Record<string, unknown>, toValue as Record<string, unknown>) as T;
|
||||||
} else {
|
} else {
|
||||||
if (fromValue !== toValue) {
|
if (fromValue !== toValue) {
|
||||||
toArray[i] = fromValue;
|
toArray[i] = fromValue;
|
||||||
@@ -420,9 +420,9 @@ export function copyArrayTo(fromArray: unknown[], toArray: unknown[]): unknown[]
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isArray(fromValue)) {
|
if (isArray(fromValue)) {
|
||||||
toArray.push(copyArrayTo(fromValue as unknown[], []));
|
toArray.push(copyArrayTo(fromValue as unknown[], []) as T);
|
||||||
} else if (isObject(fromValue)) {
|
} else if (isObject(fromValue)) {
|
||||||
toArray.push(copyObjectTo(fromValue as Record<string, unknown>, {}));
|
toArray.push(copyObjectTo(fromValue as Record<string, unknown>, {}) as T);
|
||||||
} else {
|
} else {
|
||||||
toArray.push(fromValue);
|
toArray.push(fromValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function showToast(message: string, timeout: number | undefined, translat
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showLoading(delayConditionFunc: () => boolean, delayMills: number): void {
|
export function showLoading(delayConditionFunc?: () => boolean, delayMills?: number): void {
|
||||||
if (!delayConditionFunc) {
|
if (!delayConditionFunc) {
|
||||||
f7ready((f7) => {
|
f7ready((f7) => {
|
||||||
return f7.preloader.show();
|
return f7.preloader.show();
|
||||||
|
|||||||
Reference in New Issue
Block a user