diff --git a/src/composables/usePersianDate.js b/src/composables/usePersianDate.js index de1cc4a..a4c890e 100644 --- a/src/composables/usePersianDate.js +++ b/src/composables/usePersianDate.js @@ -19,34 +19,49 @@ export function usePersianDate() { return result; }; - const formatJalali = (date, formatStr = 'YYYY/MM/DD') => { + const formatJalali = (date, formatStr = 'jYYYY/jMM/jDD') => { if (!date) return '-'; try { - return moment(date).locale('fa').format(formatStr); + return toPersianDigits(moment(date).locale('fa').format(formatStr)); } catch (e) { return '-'; } }; const formatJalaliWithTime = (date) => { - return formatJalali(date, 'YYYY/MM/DD - HH:mm'); + return formatJalali(date, 'jYYYY/jMM/jDD - HH:mm'); }; - const jalaliToIso = (jalaliStr) => { - if (!jalaliStr) return null; + const toJalaliPickerValue = (value) => { + if (!value) return ''; try { - const latinStr = toLatinDigits(jalaliStr); - return moment(latinStr, 'jYYYY/jMM/jDD').toISOString(); + return moment(value).locale('fa').format('jYYYY/jMM/jDD'); } catch (e) { - return null; + return ''; } }; + const toGregorianIso = (jalaliValue) => { + if (!jalaliValue) return undefined; + if (jalaliValue instanceof Date) return jalaliValue.toISOString(); + try { + const latin = toLatinDigits(String(jalaliValue)); + const m = moment(latin, 'jYYYY/jMM/jDD'); + return m.isValid() ? m.toDate().toISOString() : undefined; + } catch (e) { + return undefined; + } + }; + + const jalaliToIso = (jalaliStr) => toGregorianIso(jalaliStr) || null; + return { toPersianDigits, toLatinDigits, formatJalali, formatJalaliWithTime, + toJalaliPickerValue, + toGregorianIso, jalaliToIso }; } diff --git a/src/views/payments/PaymentDetailView.vue b/src/views/payments/PaymentDetailView.vue index fa84cd9..afe67d2 100644 --- a/src/views/payments/PaymentDetailView.vue +++ b/src/views/payments/PaymentDetailView.vue @@ -235,7 +235,7 @@ import DatePicker from 'vue3-persian-datetime-picker'; const route = useRoute(); const paymentId = route.params.id; -const { toPersianDigits, formatJalali } = usePersianDate(); +const { toPersianDigits, formatJalali, toJalaliPickerValue, toGregorianIso } = usePersianDate(); const { showSuccess, showError } = useToast(); const payment = ref(null); @@ -293,6 +293,8 @@ const fetchPayment = async () => { const handleRecordTransaction = async () => { if (!trxForm.amount) { showError('لطفا مبلغ را وارد کنید'); return; } if (!trxForm.dueDate) { showError('لطفا تاریخ سررسید را وارد کنید'); return; } + const dueDate = toGregorianIso(trxForm.dueDate); + if (!dueDate) { showError('تاریخ سررسید نامعتبر است'); return; } if (trxForm.status === 'paid' && !trxForm.receiptNumber) { showError('لطفا شماره فیش یا پیگیری را وارد کنید'); return; @@ -303,13 +305,14 @@ const handleRecordTransaction = async () => { const payload = { amount: trxForm.amount, status: trxForm.status, - dueDate: trxForm.dueDate, + dueDate, notes: trxForm.notes || undefined }; if (trxForm.status === 'paid') { payload.method = trxForm.method; payload.receiptNumber = trxForm.receiptNumber; - if (trxForm.date) payload.date = trxForm.date; + const paymentDate = toGregorianIso(trxForm.date); + if (paymentDate) payload.date = paymentDate; } const res = await paymentApi.recordTransaction(paymentId, payload); @@ -330,8 +333,8 @@ const openEditTransaction = (trx) => { editForm.status = trx.status || (trx.date ? 'paid' : 'pending'); editForm.method = trx.method || 'card'; editForm.receiptNumber = trx.receiptNumber || ''; - editForm.dueDate = trx.dueDate || ''; - editForm.date = trx.date || ''; + editForm.dueDate = toJalaliPickerValue(trx.dueDate); + editForm.date = toJalaliPickerValue(trx.date); editForm.notes = trx.notes || ''; showEditModal.value = true; }; @@ -345,19 +348,24 @@ const handleUpdateTransaction = async () => { showError('لطفا تاریخ سررسید را وارد کنید'); return; } + const dueDate = toGregorianIso(editForm.dueDate); + if (!dueDate) { + showError('تاریخ سررسید نامعتبر است'); + return; + } isSubmittingEdit.value = true; try { const payload = { amount: editForm.amount, status: editForm.status, - dueDate: editForm.dueDate, + dueDate, notes: editForm.notes }; if (editForm.status === 'paid') { payload.method = editForm.method; payload.receiptNumber = editForm.receiptNumber; - payload.date = editForm.date || undefined; + payload.date = toGregorianIso(editForm.date); } const res = await paymentApi.updateTransaction(editingTransactionId.value, payload); diff --git a/src/views/payments/PaymentListView.vue b/src/views/payments/PaymentListView.vue index dac5efe..f6f8804 100644 --- a/src/views/payments/PaymentListView.vue +++ b/src/views/payments/PaymentListView.vue @@ -198,7 +198,7 @@ import Checkbox from 'primevue/checkbox'; import Textarea from 'primevue/textarea'; import DatePicker from 'vue3-persian-datetime-picker'; -const { toPersianDigits, formatJalali } = usePersianDate(); +const { toPersianDigits, formatJalali, toGregorianIso } = usePersianDate(); const { showSuccess, showError } = useToast(); const { @@ -326,6 +326,8 @@ const handleCreatePayment = async () => { if (!createForm.user) { showError('لطفا کاربر را انتخاب کنید'); return; } if (!createForm.amount) { showError('لطفا مبلغ را وارد کنید'); return; } if (!createForm.dueDate) { showError('لطفا تاریخ سررسید را وارد کنید'); return; } + const dueDate = toGregorianIso(createForm.dueDate); + if (!dueDate) { showError('تاریخ سررسید نامعتبر است'); return; } if (hasDiscount.value && (createForm.discount || 0) > createForm.amount) { showError('مبلغ تخفیف نمی‌تواند بیشتر از مبلغ کل باشد'); @@ -336,6 +338,7 @@ const handleCreatePayment = async () => { try { await paymentApi.create({ ...createForm, + dueDate, discount: hasDiscount.value ? (createForm.discount || 0) : 0, notify: { ...createNotify } });