226 lines
11 KiB
Vue
226 lines
11 KiB
Vue
<script setup>
|
||
import { computed, ref } from 'vue';
|
||
import { useForm, usePage } from '@inertiajs/inertia-vue3';
|
||
import { Inertia } from '@inertiajs/inertia';
|
||
import Dialog from 'primevue/dialog';
|
||
import { toast } from 'vue3-toastify';
|
||
import UiCard from '../../ui/UiCard.vue';
|
||
import UiInput from '../../ui/UiInput.vue';
|
||
import UiButton from '../../ui/UiButton.vue';
|
||
import { convertEnglishToPersian, convertPersianToEnglish, formatPrice } from '../../../utils/numberUtils';
|
||
|
||
const props = defineProps({
|
||
bankCards: {
|
||
type: Array,
|
||
required: true
|
||
}
|
||
});
|
||
|
||
const { props: pageProps } = usePage();
|
||
|
||
const walletBalance = computed(() => Number(pageProps.value.auth?.wallet_balance || 0));
|
||
|
||
const amount = ref('');
|
||
const selectedCardId = ref(props.bankCards[0]?.id ?? null);
|
||
|
||
const MIN_WITHDRAW_AMOUNT = 10000;
|
||
|
||
const numericAmount = computed(() => Number(convertPersianToEnglish(amount.value).replace(/\D/g, '')) || 0);
|
||
|
||
const selectedCard = computed(() => props.bankCards.find((card) => card.id === selectedCardId.value) ?? null);
|
||
|
||
const amountError = computed(() => {
|
||
if (!amount.value) return '';
|
||
if (numericAmount.value < MIN_WITHDRAW_AMOUNT) return `حداقل مبلغ برداشت ${formatPrice(MIN_WITHDRAW_AMOUNT)} تومان است.`;
|
||
if (numericAmount.value > walletBalance.value) return 'مبلغ برداشت از موجودی کیف پول بیشتر است.';
|
||
return '';
|
||
});
|
||
|
||
const canSubmit = computed(() => Boolean(selectedCard.value) && numericAmount.value >= MIN_WITHDRAW_AMOUNT && !amountError.value);
|
||
|
||
const formatCardNumber = (cardNumber) => convertEnglishToPersian(cardNumber.replace(/(\d{4})(?=\d)/g, '$1 - '));
|
||
|
||
const selectFullBalance = () => {
|
||
amount.value = String(walletBalance.value);
|
||
};
|
||
|
||
const withdrawForm = useForm({
|
||
amount: null,
|
||
bank_card_id: null,
|
||
});
|
||
|
||
const submitWithdraw = () => {
|
||
if (!canSubmit.value) return;
|
||
|
||
withdrawForm.amount = numericAmount.value;
|
||
withdrawForm.bank_card_id = selectedCardId.value;
|
||
|
||
withdrawForm.post('/dashboard/wallet/withdraw-requests', {
|
||
preserveScroll: true,
|
||
onSuccess: () => {
|
||
amount.value = '';
|
||
toast.success('درخواست برداشت شما ثبت شد و در انتظار بررسی است.');
|
||
},
|
||
onError: (errors) => toast.error(Object.values(errors)[0] || 'خطا در ثبت درخواست برداشت.'),
|
||
});
|
||
};
|
||
|
||
const cardModalVisible = ref(false);
|
||
|
||
const cardForm = useForm({
|
||
card_number: '',
|
||
holder_name: '',
|
||
});
|
||
|
||
const submitCard = () => {
|
||
cardForm.card_number = convertPersianToEnglish(cardForm.card_number).replace(/\D/g, '');
|
||
|
||
cardForm.post('/dashboard/wallet/bank-cards', {
|
||
preserveScroll: true,
|
||
onSuccess: () => {
|
||
cardForm.reset();
|
||
cardModalVisible.value = false;
|
||
toast.success('کارت بانکی با موفقیت ثبت شد.');
|
||
},
|
||
onError: (errors) => toast.error(Object.values(errors)[0] || 'خطا در ثبت کارت بانکی.'),
|
||
});
|
||
};
|
||
|
||
const deleteCard = (card) => {
|
||
Inertia.delete(`/dashboard/wallet/bank-cards/${card.id}`, {
|
||
preserveScroll: true,
|
||
onSuccess: () => {
|
||
if (selectedCardId.value === card.id) {
|
||
selectedCardId.value = null;
|
||
}
|
||
},
|
||
});
|
||
};
|
||
</script>
|
||
|
||
<template>
|
||
<UiCard title="درخواست برداشت" variant="default">
|
||
<div class="flex flex-col gap-5">
|
||
<div class="flex items-start justify-between gap-4 max-md:flex-col">
|
||
<p class="text-[11px] font-normal text-[#576989] leading-6 max-w-xl">
|
||
مبلغ مورد نظر پس از بررسی و تایید توسط کارشناسان، از کیف پول شما کسر و به کارت انتخابی واریز میشود.
|
||
</p>
|
||
<div class="flex items-center gap-2 bg-[#F5F7FA] border border-[#DEE3EB] rounded-lg px-3 py-2 shrink-0">
|
||
<span class="text-[11px] font-normal text-[#576989]">موجودی قابل برداشت:</span>
|
||
<span class="text-[12px] font-semibold text-[#3E4C63]">{{ formatPrice(walletBalance) }} تومان</span>
|
||
</div>
|
||
</div>
|
||
|
||
<section class="flex flex-col gap-3 border-t border-[#EBEBEB] pt-4">
|
||
<div class="flex items-center justify-between">
|
||
<h3 class="text-[12px] font-semibold text-[#3E4C63]">۱. کارت بانکی مقصد</h3>
|
||
<button v-if="bankCards.length" type="button" class="text-[11px] font-semibold text-[#365891]" @click="cardModalVisible = true">
|
||
+ افزودن کارت
|
||
</button>
|
||
</div>
|
||
<div v-if="!bankCards.length" class="flex flex-col items-center gap-3 bg-[#F8FAFC] border border-dashed border-[#C1D0E8] rounded-xl p-5">
|
||
<p class="text-[11px] font-normal text-[#576989] text-center leading-6">
|
||
هنوز کارتی ثبت نکردهاید. برای ثبت درخواست برداشت ابتدا یک کارت بانکی اضافه کنید.
|
||
</p>
|
||
<UiButton label="افزودن کارت بانکی" severity="secondary" size="small" @click="cardModalVisible = true" />
|
||
</div>
|
||
<div v-else class="grid grid-cols-2 max-lg:grid-cols-1 gap-3">
|
||
<label
|
||
v-for="card in bankCards"
|
||
:key="card.id"
|
||
class="flex items-center gap-3 border rounded-xl px-4 py-3 cursor-pointer transition-colors"
|
||
:class="selectedCardId === card.id ? 'border-[#365891] bg-[#EEF2F8]' : 'border-[#DEE3EB] bg-white hover:bg-[#F8FAFC]'"
|
||
>
|
||
<input
|
||
v-model="selectedCardId"
|
||
type="radio"
|
||
name="bank_card"
|
||
:value="card.id"
|
||
class="accent-[#365891]"
|
||
/>
|
||
<span class="flex flex-col gap-1 flex-1">
|
||
<span class="text-[12px] font-semibold text-[#3E4C63]" dir="ltr">{{ formatCardNumber(card.card_number) }}</span>
|
||
<span class="text-[11px] font-normal text-[#576989]">{{ card.holder_name }}</span>
|
||
</span>
|
||
<button type="button" class="text-[11px] font-semibold text-[#7A1419]" @click.prevent="deleteCard(card)">حذف</button>
|
||
</label>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="flex flex-col gap-3 border-t border-[#EBEBEB] pt-4">
|
||
<h3 class="text-[12px] font-semibold text-[#3E4C63]">۲. مبلغ برداشت</h3>
|
||
<div class="flex flex-col gap-2 max-w-md">
|
||
<UiInput
|
||
v-model="amount"
|
||
placeholder="مبلغ مورد نظر را به تومان وارد کنید"
|
||
prefixEnd="تومان"
|
||
prefixClasses="!border-dominant-50"
|
||
class="!w-full"
|
||
customClass="!border-dominant-50 !font-normal !text-[12px]"
|
||
:error="amountError"
|
||
/>
|
||
<div class="flex items-center justify-between gap-2 flex-wrap">
|
||
<span class="text-[11px] font-normal text-[#576989]">حداقل مبلغ برداشت {{ formatPrice(MIN_WITHDRAW_AMOUNT) }} تومان است.</span>
|
||
<button
|
||
type="button"
|
||
class="text-[11px] font-normal text-[#576989] bg-[#F5F7FA] border border-[#DEE3EB] rounded-lg px-3 py-1.5 hover:bg-[#EEF2F8] disabled:opacity-50 disabled:cursor-not-allowed"
|
||
:disabled="walletBalance < MIN_WITHDRAW_AMOUNT"
|
||
@click="selectFullBalance"
|
||
>
|
||
برداشت کل موجودی
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="flex items-center justify-between gap-4 max-md:flex-col max-md:items-stretch border-t border-[#EBEBEB] pt-4">
|
||
<p v-if="canSubmit" class="text-[11px] font-normal text-[#576989] leading-6">
|
||
<span class="font-[600] text-[#7A1419]">{{ formatPrice(numericAmount) }} تومان</span>
|
||
به کارت
|
||
<span class="font-[600] text-[#3E4C63]" dir="ltr">{{ formatCardNumber(selectedCard.card_number) }}</span>
|
||
واریز میشود.
|
||
</p>
|
||
<p v-else class="text-[11px] font-normal text-[#576989] leading-6">
|
||
برای ثبت درخواست، کارت مقصد را انتخاب و مبلغ را وارد کنید.
|
||
</p>
|
||
<UiButton
|
||
label="ثبت درخواست برداشت"
|
||
severity="success"
|
||
size="small"
|
||
class="shrink-0"
|
||
:loading="withdrawForm.processing"
|
||
:disabled="withdrawForm.processing || !canSubmit"
|
||
@click="submitWithdraw"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<Dialog v-model:visible="cardModalVisible" :modal="true" :closable="true" :dismissableMask="false" :style="{ width: '420px' }" class="fast-request-dialog" :pt="{ header: '!bg-client-primaryBlue' }">
|
||
<template #header>
|
||
<div class="w-full flex items-center justify-start">
|
||
<h2 class="text-[14px] font-[700] text-[#576989]">افزودن کارت بانکی</h2>
|
||
</div>
|
||
</template>
|
||
<div class="w-full flex flex-col gap-4 border-t border-[#EBEBEB] pt-4">
|
||
<UiInput
|
||
v-model="cardForm.card_number"
|
||
label="شماره کارت"
|
||
placeholder="شماره کارت ۱۶ رقمی"
|
||
maxlength="16"
|
||
customClass="!border-dominant-50 !font-normal !text-[12px]"
|
||
/>
|
||
<UiInput
|
||
v-model="cardForm.holder_name"
|
||
label="نام صاحب حساب"
|
||
placeholder="نام و نام خانوادگی صاحب کارت"
|
||
customClass="!border-dominant-50 !font-normal !text-[12px]"
|
||
/>
|
||
</div>
|
||
<div class="w-full pt-4 flex items-center justify-start gap-2 border-t border-[#EBEBEB] mt-4">
|
||
<UiButton label="ثبت کارت" severity="success" size="small" :loading="cardForm.processing" :disabled="cardForm.processing" @click="submitCard" />
|
||
<UiButton label="انصراف" severity="secondary" size="small" :disabled="cardForm.processing" @click="cardModalVisible = false" />
|
||
</div>
|
||
</Dialog>
|
||
</UiCard>
|
||
</template>
|