feat: add withdraw request functionality and UI components

This commit is contained in:
2026-08-27 02:39:57 +03:30
parent aeef95339d
commit 4ce663c669
115 changed files with 4064 additions and 315 deletions
@@ -1,8 +1,12 @@
<script setup>
import { computed } from 'vue';
import { computed, ref } from 'vue';
import Dialog from 'primevue/dialog';
import { usePage } from '@inertiajs/inertia-vue3';
import { Inertia } from '@inertiajs/inertia';
import UiButton from '../../ui/UiButton.vue';
import { toast } from 'vue3-toastify';
import { modalityTitle } from '../../../data/fastRequestOptions';
import { formatPrice } from '../../../utils/numberUtils';
const visible = defineModel('visible');
@@ -10,31 +14,69 @@ const props = defineProps({
document: {
type: Object,
default: null
},
invoice: {
type: Object,
default: null
}
});
const formattedAmount = computed(() => {
return Number(props.document?.invoice?.amount || 0).toLocaleString('fa-IR');
});
const { props: pageProps } = usePage();
const handlePay = () => {
visible.value = false;
const paying = ref(false);
const payingWithWallet = ref(false);
const currentInvoice = computed(() => props.invoice ?? props.document?.invoice ?? null);
const formattedAmount = computed(() => formatPrice(currentInvoice.value?.amount || 0));
const walletBalance = computed(() => Number(pageProps.value.auth?.wallet_balance || 0));
const formattedWalletBalance = computed(() => formatPrice(walletBalance.value));
const hasEnoughBalance = computed(() => walletBalance.value >= Number(currentInvoice.value?.amount || 0));
const handlePay = async () => {
paying.value = true;
try {
const { data } = await window.axios.post('/dashboard/payments', { invoice_id: currentInvoice.value.id });
window.location.href = data.url;
} catch (error) {
paying.value = false;
toast.error(error.response?.data?.message || 'خطا در اتصال به درگاه پرداخت. لطفا دوباره تلاش کنید.');
}
}
const handleWalletPay = async () => {
payingWithWallet.value = true;
try {
await window.axios.post(`/dashboard/invoices/${currentInvoice.value.id}/pay-wallet`);
toast.success('فاکتور با موفقیت از کیف پول پرداخت شد.');
visible.value = false;
Inertia.reload();
} catch (error) {
toast.error(error.response?.data?.message || 'خطا در پرداخت از کیف پول. لطفا دوباره تلاش کنید.');
} finally {
payingWithWallet.value = false;
}
}
</script>
<template>
<Dialog v-model:visible="visible" :modal="true" :closable="true" :dismissableMask="false" :maximizable="false" :style="{ width: '1032px' }">
<Dialog v-model:visible="visible" :modal="true" :closable="true" :dismissableMask="false" :maximizable="false" :style="{ width: '688px' , minHeight: '376px' }" class="fast-request-dialog" :pt="{header : '!bg-client-primaryBlue'}">
<template #header>
<h2 class="text-[14px] font-[700] text-[#576989]">فاکتور پرداخت «{{ document?.invoice?.number }}»</h2>
<div class="w-full flex items-center justify-start">
<h2 class="text-[14px] font-[700] text-[#576989]">فاکتور پرداخت «{{ currentInvoice?.number }}»</h2>
</div>
</template>
<div v-if="document" class="w-full flex flex-col gap-4 border-t border-[#EBEBEB] pt-4">
<div class="w-full flex items-center gap-3 bg-[#EEF2F8] border border-[#DEE3EB] rounded-[12px] px-4 py-4">
<i class="fi-rr-info text-[20px] text-[#576989]"></i>
<p class="text-[13px] font-[400] text-[#3E4C63]">
<div v-if="currentInvoice" class="w-full flex flex-col gap-4 border-t border-[#EBEBEB] pt-4">
<div class="w-full flex items-center gap-3 bg-[#EEF2F8] border border-[#DEE3EB] rounded-[12px] px-4 py-3">
<i class="fi-rr-info text-[18px] text-[#576989]"></i>
<p class="text-[12px] font-[400] text-[#3E4C63] leading-6">
یک فاکتور به مبلغ « <span class="font-[700]">{{ formattedAmount }} تومان</span> » برای شما ایجاد شد. لطفا جهت ادامه مراحل درخواست نسبت به پرداخت اقدام نمایید.
</p>
</div>
<p class="text-[13px] font-[400] text-[#3E4C63] leading-7">
<p v-if="document" class="text-[13px] font-[400] text-[#3E4C63] leading-7">
این فاکتور جهت پردازش درخواست
<span class="font-[600] text-[#7A1419]">(({{ modalityTitle(document.modality) }}))</span>
به شناسه
@@ -48,9 +90,14 @@ const handlePay = () => {
<br>
بدیهیست که در صورت عدم تایید کارشناسان مبلغ مربوطه به کیف پول شما بازگردانده خواهد شد.
</p>
<p class="text-[12px] font-[400] text-[#576989]">
موجودی کیف پول شما: <span class="font-[700] text-[#3E4C63]">{{ formattedWalletBalance }} تومان</span>
<span v-if="!hasEnoughBalance" class="text-[#7A1419]"> (موجودی کیف پول کافی نیست)</span>
</p>
</div>
<div class="w-full pt-3 flex items-center justify-start border-t border-[#EBEBEB]">
<ui-button label="تایید و پرداخت" severity="success" size="small" @click="handlePay" />
<div class="w-full pt-3 flex items-center justify-start gap-2 border-t border-[#EBEBEB]">
<ui-button label="پرداخت با کیف پول" severity="primary" size="small" :loading="payingWithWallet" :disabled="payingWithWallet || paying || !hasEnoughBalance" @click="handleWalletPay" />
<ui-button label="پرداخت از طریق درگاه" severity="success" size="small" :loading="paying" :disabled="paying || payingWithWallet" @click="handlePay" />
</div>
</Dialog>
</template>