support duplicating / modifying / deleting transaction in reconciliation statement page
This commit is contained in:
@@ -73,7 +73,7 @@
|
||||
class="skeleton-text margin-vertical transaction-info-list reconciliation-statement-list"
|
||||
v-if="finishQuery && loading">
|
||||
<ul>
|
||||
<f7-list-item chevron-center media-item
|
||||
<f7-list-item chevron-center
|
||||
:key="index"
|
||||
:class="{ 'transaction-info': type === 't', 'last-transaction-of-day': index === 2, 'reconciliation-statement-transaction-date': type === 'd' }"
|
||||
:link="type === 't' ? '#' : null"
|
||||
@@ -139,76 +139,94 @@
|
||||
:virtual-list-params="{ items: allReconciliationStatementVirtualListItems, renderExternal, height: 'auto' }"
|
||||
v-if="finishQuery && !loading && allReconciliationStatementVirtualListItems && allReconciliationStatementVirtualListItems.length">
|
||||
<ul>
|
||||
<f7-list-item
|
||||
chevron-center
|
||||
media-item
|
||||
:key="item.index"
|
||||
:class="{ 'transaction-info': item.type == 'transaction', 'last-transaction-of-day': allReconciliationStatementVirtualListItems[item.index + 1] && allReconciliationStatementVirtualListItems[item.index + 1].type === 'date', 'reconciliation-statement-transaction-date': item.type == 'date' }"
|
||||
:style="`top: ${virtualDataItems.topPosition}px`"
|
||||
:virtual-list-index="item.index"
|
||||
:link="item.type == 'transaction' && item.transaction && item.transaction.type !== TransactionType.ModifyBalance ? `/transaction/detail?id=${item.transaction?.id}&type=${item.transaction.type}` : null"
|
||||
v-for="item in virtualDataItems.items"
|
||||
<f7-list-item chevron-center
|
||||
:key="item.index"
|
||||
:id="item.transaction ? getTransactionDomId(item.transaction) : undefined"
|
||||
:class="{ 'transaction-info': item.type == 'transaction', 'last-transaction-of-day': allReconciliationStatementVirtualListItems[item.index + 1] && allReconciliationStatementVirtualListItems[item.index + 1].type === 'date', 'reconciliation-statement-transaction-date': item.type == 'date' }"
|
||||
:style="`top: ${virtualDataItems.topPosition}px`"
|
||||
:virtual-list-index="item.index"
|
||||
:swipeout="item.type == 'transaction' && item.transaction"
|
||||
:accordion-item="item.type == 'transaction' && item.transaction"
|
||||
:link="item.type == 'transaction' && item.transaction && item.transaction.type !== TransactionType.ModifyBalance ? `/transaction/detail?id=${item.transaction?.id}&type=${item.transaction.type}` : null"
|
||||
v-for="item in virtualDataItems.items"
|
||||
>
|
||||
<div class="display-flex no-padding-horizontal" v-if="item.type == 'date' && item.displayDate">
|
||||
<div class="actual-item-inner">
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">
|
||||
<small>{{ item.displayDate }}</small>
|
||||
<template #inner>
|
||||
<div class="display-flex no-padding-horizontal" v-if="item.type == 'date' && item.displayDate">
|
||||
<div class="actual-item-inner">
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">
|
||||
<small>{{ item.displayDate }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="display-flex no-padding-horizontal" v-if="item.type == 'transaction' && item.transaction">
|
||||
<div class="item-media">
|
||||
<div class="transaction-icon display-flex align-items-center">
|
||||
<ItemIcon icon-type="category"
|
||||
:icon-id="allCategoriesMap[item.transaction.categoryId]?.icon"
|
||||
:color="allCategoriesMap[item.transaction.categoryId]?.color"
|
||||
v-if="allCategoriesMap[item.transaction.categoryId] && allCategoriesMap[item.transaction.categoryId]?.color"></ItemIcon>
|
||||
<f7-icon v-else-if="!allCategoriesMap[item.transaction.categoryId] || !allCategoriesMap[item.transaction.categoryId]?.color"
|
||||
f7="pencil_ellipsis_rectangle">
|
||||
</f7-icon>
|
||||
<div class="display-flex no-padding-horizontal" v-if="item.type == 'transaction' && item.transaction">
|
||||
<div class="item-media">
|
||||
<div class="transaction-icon display-flex align-items-center">
|
||||
<ItemIcon icon-type="category"
|
||||
:icon-id="allCategoriesMap[item.transaction.categoryId]?.icon"
|
||||
:color="allCategoriesMap[item.transaction.categoryId]?.color"
|
||||
v-if="allCategoriesMap[item.transaction.categoryId] && allCategoriesMap[item.transaction.categoryId]?.color"></ItemIcon>
|
||||
<f7-icon v-else-if="!allCategoriesMap[item.transaction.categoryId] || !allCategoriesMap[item.transaction.categoryId]?.color"
|
||||
f7="pencil_ellipsis_rectangle">
|
||||
</f7-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actual-item-inner">
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">
|
||||
<div class="transaction-category-name no-padding">
|
||||
<div class="actual-item-inner">
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">
|
||||
<div class="transaction-category-name no-padding">
|
||||
<span v-if="item.transaction.type === TransactionType.ModifyBalance">
|
||||
{{ tt('Modify Balance') }}
|
||||
</span>
|
||||
<span v-else-if="item.transaction.type !== TransactionType.ModifyBalance && allCategoriesMap[item.transaction.categoryId]">
|
||||
<span v-else-if="item.transaction.type !== TransactionType.ModifyBalance && allCategoriesMap[item.transaction.categoryId]">
|
||||
{{ allCategoriesMap[item.transaction.categoryId].name }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-after">
|
||||
<div class="transaction-amount"
|
||||
:class="{ 'text-expense': item.transaction.type === TransactionType.Expense, 'text-income': item.transaction.type === TransactionType.Income }">
|
||||
<span v-if="item.transaction.type === TransactionType.Transfer && item.transaction.destinationAccountId === accountId">{{ getDisplayDestinationAmount(item.transaction) }}</span>
|
||||
<span v-else-if="item.transaction.type !== TransactionType.Transfer || item.transaction.destinationAccountId !== accountId">{{ getDisplaySourceAmount(item.transaction) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-after">
|
||||
<div class="transaction-amount"
|
||||
:class="{ 'text-expense': item.transaction.type === TransactionType.Expense, 'text-income': item.transaction.type === TransactionType.Income }">
|
||||
<span v-if="item.transaction.type === TransactionType.Transfer && item.transaction.destinationAccountId === accountId">{{ getDisplayDestinationAmount(item.transaction) }}</span>
|
||||
<span v-else-if="item.transaction.type !== TransactionType.Transfer || item.transaction.destinationAccountId !== accountId">{{ getDisplaySourceAmount(item.transaction) }}</span>
|
||||
<div class="item-text">
|
||||
<div class="transaction-description" v-if="item.transaction.comment">
|
||||
<span>{{ item.transaction.comment }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-text">
|
||||
<div class="transaction-description" v-if="item.transaction.comment">
|
||||
<span>{{ item.transaction.comment }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-footer">
|
||||
<div class="transaction-footer display-flex justify-content-space-between">
|
||||
<div class="flex-shrink-0">
|
||||
<span>{{ getDisplayTime(item.transaction) }}</span>
|
||||
<span v-if="item.transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ `(${getDisplayTimezone(item.transaction)})` }}</span>
|
||||
</div>
|
||||
<div class="account-balance flex-shrink-1">
|
||||
<span>{{ isCurrentLiabilityAccount ? tt('Outstanding Balance') : tt('Balance') }}</span>
|
||||
<span style="margin-left: 4px">{{ getDisplayAccountBalance(item.transaction) }}</span>
|
||||
<div class="item-footer">
|
||||
<div class="transaction-footer display-flex justify-content-space-between">
|
||||
<div class="flex-shrink-0">
|
||||
<span>{{ getDisplayTime(item.transaction) }}</span>
|
||||
<span v-if="item.transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ `(${getDisplayTimezone(item.transaction)})` }}</span>
|
||||
</div>
|
||||
<div class="account-balance flex-shrink-1">
|
||||
<span>{{ isCurrentLiabilityAccount ? tt('Outstanding Balance') : tt('Balance') }}</span>
|
||||
<span style="margin-left: 4px">{{ getDisplayAccountBalance(item.transaction) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<f7-swipeout-actions right v-if="item.type == 'transaction' && item.transaction">
|
||||
<f7-swipeout-button color="primary" close
|
||||
:text="tt('Duplicate')"
|
||||
v-if="item.transaction.type !== TransactionType.ModifyBalance"
|
||||
@click="duplicateTransaction(item.transaction)"></f7-swipeout-button>
|
||||
<f7-swipeout-button color="orange" close
|
||||
:text="tt('Edit')"
|
||||
v-if="item.transaction.editable && item.transaction.type !== TransactionType.ModifyBalance"
|
||||
@click="editTransaction(item.transaction)"></f7-swipeout-button>
|
||||
<f7-swipeout-button color="red" class="padding-left padding-right"
|
||||
v-if="item.transaction.editable"
|
||||
@click="removeTransaction(item.transaction, false)">
|
||||
<f7-icon f7="trash"></f7-icon>
|
||||
</f7-swipeout-button>
|
||||
</f7-swipeout-actions>
|
||||
</f7-list-item>
|
||||
</ul>
|
||||
</f7-list>
|
||||
@@ -231,6 +249,16 @@
|
||||
<f7-actions-button bold close>{{ tt('Cancel') }}</f7-actions-button>
|
||||
</f7-actions-group>
|
||||
</f7-actions>
|
||||
|
||||
<f7-actions close-by-outside-click close-on-escape :opened="showDeleteActionSheet" @actions:closed="showDeleteActionSheet = false">
|
||||
<f7-actions-group>
|
||||
<f7-actions-label>{{ tt('Are you sure you want to delete this transaction?') }}</f7-actions-label>
|
||||
<f7-actions-button color="red" @click="removeTransaction(transactionToDelete, true)">{{ tt('Delete') }}</f7-actions-button>
|
||||
</f7-actions-group>
|
||||
<f7-actions-group>
|
||||
<f7-actions-button bold close>{{ tt('Cancel') }}</f7-actions-button>
|
||||
</f7-actions-group>
|
||||
</f7-actions>
|
||||
</f7-page>
|
||||
</template>
|
||||
|
||||
@@ -239,7 +267,7 @@ import { ref, computed } from 'vue';
|
||||
import type { Router } from 'framework7/types';
|
||||
|
||||
import { useI18n } from '@/locales/helpers.ts';
|
||||
import { useI18nUIComponents } from '@/lib/ui/mobile.ts';
|
||||
import { useI18nUIComponents, showLoading, hideLoading, onSwipeoutDeleted } from '@/lib/ui/mobile.ts';
|
||||
import { useReconciliationStatementPageBase } from '@/views/base/accounts/ReconciliationStatementPageBase.ts';
|
||||
|
||||
import { useAccountsStore } from '@/stores/account.ts';
|
||||
@@ -278,7 +306,7 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const { tt, getAllDateRanges, formatUnixTimeToLongDateTime } = useI18n();
|
||||
const { showToast, routeBackOnError } = useI18nUIComponents();
|
||||
const { showAlert, showToast, routeBackOnError } = useI18nUIComponents();
|
||||
|
||||
const {
|
||||
accountId,
|
||||
@@ -291,6 +319,7 @@ const {
|
||||
isCurrentLiabilityAccount,
|
||||
allCategoriesMap,
|
||||
currentAccount,
|
||||
currentAccountCurrency,
|
||||
displayStartDateTime,
|
||||
displayEndDateTime,
|
||||
displayTotalInflows,
|
||||
@@ -314,8 +343,10 @@ const finishQuery = ref<boolean>(false);
|
||||
const loading = ref<boolean>(false);
|
||||
const loadingError = ref<unknown | null>(null);
|
||||
const queryDateRangeType = ref<number>(DateRange.ThisMonth.type);
|
||||
const transactionToDelete = ref<TransactionReconciliationStatementResponseItem | null>(null);
|
||||
const showCustomDateRangeSheet = ref<boolean>(false);
|
||||
const showMoreActionSheet = ref<boolean>(false);
|
||||
const showDeleteActionSheet = ref<boolean>(false);
|
||||
const virtualDataItems = ref<ReconciliationStatementVirtualListData>({
|
||||
items: [],
|
||||
topPosition: 0
|
||||
@@ -359,6 +390,10 @@ const allReconciliationStatementVirtualListItems = computed<ReconciliationStatem
|
||||
return ret;
|
||||
});
|
||||
|
||||
function getTransactionDomId(transaction: TransactionReconciliationStatementResponseItem): string {
|
||||
return 'transaction_' + transaction.id;
|
||||
}
|
||||
|
||||
function init(): void {
|
||||
const query = props.f7route.query;
|
||||
const defaultDateRange = getDateRangeByDateType(queryDateRangeType.value, firstDayOfWeek.value, fiscalYearStart.value);
|
||||
@@ -447,6 +482,48 @@ function addTransaction(): void {
|
||||
props.f7router.navigate(`/transaction/add?accountId=${accountId.value}`);
|
||||
}
|
||||
|
||||
function duplicateTransaction(transaction: TransactionReconciliationStatementResponseItem): void {
|
||||
props.f7router.navigate(`/transaction/add?id=${transaction.id}&type=${transaction.type}`);
|
||||
}
|
||||
|
||||
function editTransaction(transaction: TransactionReconciliationStatementResponseItem): void {
|
||||
props.f7router.navigate(`/transaction/edit?id=${transaction.id}&type=${transaction.type}`);
|
||||
}
|
||||
|
||||
function removeTransaction(transaction: TransactionReconciliationStatementResponseItem | null, confirm: boolean): void {
|
||||
if (!transaction) {
|
||||
showAlert('An error occurred');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm) {
|
||||
transactionToDelete.value = transaction;
|
||||
showDeleteActionSheet.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
showDeleteActionSheet.value = false;
|
||||
transactionToDelete.value = null;
|
||||
showLoading();
|
||||
|
||||
transactionsStore.deleteTransaction({
|
||||
transaction: transaction,
|
||||
defaultCurrency: currentAccountCurrency.value,
|
||||
beforeResolve: (done) => {
|
||||
onSwipeoutDeleted(getTransactionDomId(transaction), done);
|
||||
}
|
||||
}).then(() => {
|
||||
hideLoading();
|
||||
reload(false);
|
||||
}).catch(error => {
|
||||
hideLoading();
|
||||
|
||||
if (!error.processed) {
|
||||
showToast(error.message || error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderExternal(vl: unknown, vlData: ReconciliationStatementVirtualListData): void {
|
||||
virtualDataItems.value = vlData;
|
||||
}
|
||||
@@ -490,7 +567,8 @@ init();
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.list.reconciliation-statement-list li.transaction-info.last-transaction-of-day > .item-link > .item-content > .item-inner:after {
|
||||
.list.reconciliation-statement-list li.transaction-info.last-transaction-of-day > .item-link > .item-content > .item-inner:after,
|
||||
.list.reconciliation-statement-list li.transaction-info.last-transaction-of-day > .swipeout-content > .item-link > .item-content > .item-inner:after {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user