fix(payments): make duplicate check fully reactive via deep watch and enhance dark-mode warning visibility

This commit is contained in:
2026-08-23 13:35:41 +03:30
parent f7089d5ca7
commit 497b065b5c
+39 -9
View File
@@ -117,11 +117,16 @@
</div>
<!-- Duplicate Payment Warning -->
<div v-if="duplicateWarning?.hasDuplicate" class="p-3 bg-yellow-50 border-round border-1 border-yellow-400 text-yellow-900 text-sm flex align-items-start gap-2">
<i class="pi pi-exclamation-triangle text-yellow-600 text-lg mt-1 flex-shrink-0"></i>
<div
v-if="duplicateWarning && duplicateWarning.hasDuplicate"
class="p-3 border-round flex align-items-start gap-2 duplicate-warning-box"
>
<i class="pi pi-exclamation-triangle text-xl text-yellow-400 mt-1 flex-shrink-0"></i>
<div class="flex flex-column gap-1">
<span class="font-bold">هشدار: صورتحساب تکراری</span>
<span>برای این دانشجو قبلاً در کلاسهای انتخابشده صورتحساب ثبت شده است.</span>
<span class="font-bold text-yellow-300 text-sm">هشدار: برای این دانشجو قبلاً در این کلاس صورتحساب ثبت شده است.</span>
<span class="text-xs text-yellow-200" v-if="duplicateWarning.payments && duplicateWarning.payments.length">
صورتحساب قبلی با کد {{ duplicateWarning.payments.map(p => p.uniqueCode || p._id).join('، ') }} موجود است.
</span>
</div>
</div>
@@ -270,7 +275,7 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue';
import { ref, reactive, computed, watch, onMounted } from 'vue';
import { useDataTable } from '@/composables/useDataTable';
import { usePersianDate } from '@/composables/usePersianDate';
import { useToast } from '@/composables/useToast';
@@ -386,22 +391,39 @@ const eligibleUsers = computed(() => {
return usersList.value.filter((u) => eligibleIds?.has(String(u._id || u.id)));
});
const checkDuplicateInvoice = async () => {
if (!createForm.user || !createForm.classes?.length) {
const checkDuplicateInvoice = async (userIdVal = null) => {
const targetUser = userIdVal || createForm.user;
if (!targetUser || !createForm.classes || !createForm.classes.length) {
duplicateWarning.value = null;
return;
}
try {
const classIds = Array.isArray(createForm.classes)
? createForm.classes.map((c) => c?._id || c?.id || c).join(',')
: String(createForm.classes);
const res = await paymentApi.checkDuplicate({
userId: createForm.user,
classes: createForm.classes.join(',')
userId: String(targetUser?._id || targetUser?.id || targetUser),
classes: classIds
});
duplicateWarning.value = res.data?.data || res.data || res;
} catch (err) {
console.error('checkDuplicateInvoice error:', err);
duplicateWarning.value = null;
}
};
watch(
[() => createForm.user, () => createForm.classes],
async ([newUser, newClasses]) => {
if (newUser && newClasses && newClasses.length) {
await checkDuplicateInvoice(newUser);
} else {
duplicateWarning.value = null;
}
},
{ deep: true, immediate: true }
);
const onClassesSelected = async () => {
if (createForm.user && !eligibleUsers.value.some((u) => (u._id || u.id) === createForm.user)) {
createForm.user = null;
@@ -639,3 +661,11 @@ onMounted(() => {
fetchDropdownData();
});
</script>
<style scoped>
.duplicate-warning-box {
background: rgba(234, 179, 8, 0.15) !important;
border: 1px solid rgba(234, 179, 8, 0.6) !important;
color: #fef08a !important;
}
</style>