feat: add messaging toggles, password reset UI, and payment discounts

Add notification channel toggles to settings, password reset SMS action on user form, and discount/payable amount display on payment views.
This commit is contained in:
2026-08-16 06:58:09 +03:30
parent 5fe7eb090e
commit 92eb394466
8 changed files with 361 additions and 21 deletions
+38 -4
View File
@@ -27,7 +27,15 @@
</div>
<div>
<span class="text-muted text-xs block mb-1">مبلغ کل صورتحساب</span>
<span class="font-bold text-color text-xl">{{ toPersianDigits(payment.amount?.toLocaleString()) }} تومان</span>
<span class="font-bold text-color text-xl">{{ toPersianDigits((payment.amount || 0).toLocaleString()) }} تومان</span>
</div>
<div v-if="payment.discount">
<span class="text-muted text-xs block mb-1">تخفیف</span>
<span class="font-semibold text-orange-500 text-lg">{{ toPersianDigits((payment.discount || 0).toLocaleString()) }} تومان</span>
</div>
<div>
<span class="text-muted text-xs block mb-1">مبلغ قابل پرداخت</span>
<span class="font-bold text-color text-xl">{{ toPersianDigits(payableAmount.toLocaleString()) }} تومان</span>
</div>
<div>
<span class="text-muted text-xs block mb-1">مبلغ کل دریافتی</span>
@@ -35,12 +43,16 @@
</div>
<div>
<span class="text-muted text-xs block mb-1">باقیمانده</span>
<span class="font-bold text-red-500 text-lg">{{ toPersianDigits((payment.amount - (payment.paidAmount || 0)).toLocaleString()) }} تومان</span>
<span class="font-bold text-red-500 text-lg">{{ toPersianDigits(remainingAmount.toLocaleString()) }} تومان</span>
</div>
<div>
<span class="text-muted text-xs block mb-1">وضعیت پرداخت</span>
<StatusTag :status="payment.status" type="payment" />
</div>
<div>
<span class="text-muted text-xs block mb-1">یادداشت</span>
<p class="text-sm text-color m-0 white-space-pre-wrap line-height-3">{{ payment.notes || '—' }}</p>
</div>
</div>
</div>
</div>
@@ -76,6 +88,11 @@
{{ formatJalali(data.createdAt || data.date) }}
</template>
</Column>
<Column field="notes" header="یادداشت">
<template #body="{ data }">
<span class="white-space-pre-wrap">{{ data.notes || '—' }}</span>
</template>
</Column>
</DataTable>
</div>
</div>
@@ -96,6 +113,16 @@
<label class="font-semibold text-sm">شماره فیش / پیگیری *</label>
<InputText v-model.trim="trxForm.receiptNumber" class="w-full text-sm" dir="ltr" />
</div>
<div class="flex flex-column gap-2">
<label class="font-semibold text-sm" for="trx-notes">یادداشت</label>
<Textarea
id="trx-notes"
v-model="trxForm.notes"
rows="3"
class="w-full text-sm"
placeholder="یادداشت داخلی درباره این تراکنش…"
/>
</div>
</div>
<template #footer>
<Button label="انصراف" text severity="secondary" @click="showTransactionModal = false" />
@@ -106,11 +133,12 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { paymentApi } from '@/api/paymentApi';
import { usePersianDate } from '@/composables/usePersianDate';
import { useToast } from '@/composables/useToast';
import { getPayableAmount } from '@/utils/paymentAmount';
import PageHeader from '@/components/common/PageHeader.vue';
import PermissionGate from '@/components/common/PermissionGate.vue';
import StatusTag from '@/components/common/StatusTag.vue';
@@ -122,6 +150,7 @@ import Dialog from 'primevue/dialog';
import Dropdown from 'primevue/select';
import InputText from 'primevue/inputtext';
import InputNumber from 'primevue/inputnumber';
import Textarea from 'primevue/textarea';
const route = useRoute();
const paymentId = route.params.id;
@@ -141,9 +170,13 @@ const methodOptions = [
const trxForm = reactive({
amount: 500000,
method: 'card',
receiptNumber: ''
receiptNumber: '',
notes: ''
});
const payableAmount = computed(() => getPayableAmount(payment.value || {}));
const remainingAmount = computed(() => Math.max(0, payableAmount.value - (payment.value?.paidAmount || 0)));
const fetchPayment = async () => {
try {
const res = await paymentApi.getOne(paymentId);
@@ -162,6 +195,7 @@ const handleRecordTransaction = async () => {
await paymentApi.recordTransaction(paymentId, trxForm);
showSuccess('تراکنش جدید با موفقیت ثبت شد');
showTransactionModal.value = false;
trxForm.notes = '';
fetchPayment();
} catch (err) {
showError(err);