Files

226 lines
11 KiB
Vue
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>