import { computed, inject, onMounted, provide, ref, type ComponentPublicInstance, type InjectionKey } from 'vue' import OtpInput from 'vue3-otp-input' import { usePrice, usePriceWithoutType } from '@/utils/usePrice' import { loading, loadingMore } from '@/utils' import router from '@/router' import { useWalletStore } from '@/store/walletStore' import type { Transaction } from '@/models/transaction' import { createCard, getActivatedCards, withdraw, confirmCode } from '@/api/wallet' import { useInfiniteScroll } from '@vueuse/core' import { message } from 'ant-design-vue' import type { Card } from '@/models/wallet' import { useUserStore } from '@/store/userStore' import { useSettingsStore } from '@/store/settingsStore' import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout' import type { TableEngineInput, TableOutput } from '@/models/table' import { getTransactionTable, getTransactionTable2 } from '@/api/transaction' import { formatWalletMinHint, parseWalletMinRial } from '@/utils/walletMinAmount' export interface WalletPageContext { isDeposit: ReturnType> walletStore: ReturnType showAddCard: ReturnType> chargeAccountModal: ReturnType> showConfirmCode: ReturnType> infoVisible: ReturnType> refOtpInput: ReturnType | null>> form: ReturnType> cardForm: ReturnType> disableButton: ReturnType> cardItems: ReturnType> depositItems: ReturnType> withdrawItems: ReturnType> mobileDepositScrollEl: ReturnType> desktopDepositScrollEl: ReturnType> minWithdrawHint: ReturnType> minDepositHint: ReturnType> usePriceWithoutType: typeof usePriceWithoutType usePrice: typeof usePrice setIsDeposit: (val: boolean) => void useStyle: () => string formatter: (value: number) => string percentChange: (val: number) => void ok: () => Promise addCard: () => Promise getCards: () => Promise handleOnComplete: (value: string) => Promise } export const WALLET_PAGE_CONTEXT_KEY: InjectionKey = Symbol('walletPageContext') export function useWalletPage() { const isDeposit = ref(true) const walletStore = useWalletStore() const userStore = useUserStore() const settingsStore = useSettingsStore() const isDesktop = useDesktopBreakpoint() const showAddCard = ref(false) const chargeAccountModal = ref(false) const showConfirmCode = ref(false) const infoVisible = ref(false) const refOtpInput = ref | null>(null) const mobileDepositScrollEl = ref(null) const desktopDepositScrollEl = ref(null) const form = ref({ value: undefined, percentWallet: 0, card_id: undefined, }) const cardForm = ref({ birth_date: 0, shaba_number: '', }) const cardItems = ref([]) const depositItems = ref([]) const withdrawItems = ref([]) const depositTableOutput = ref | null>(null) const withdrawTableOutput = ref | null>(null) const depositPagination = ref({ filters: [], limit: 6, page: 0 }) const withdrawPagination = ref({ filters: [{ field: 'type', cr: 'and', type: 'number', op: 'eq', value: 4 }], limit: 6, page: 0, }) const activeDepositScrollEl = computed(() => isDesktop.value ? desktopDepositScrollEl.value : mobileDepositScrollEl.value ) const unitCalculator = computed(() => (walletStore?.walletInfo?.cash ?? 0) / 100) const minWithdrawAmount = computed(() => parseWalletMinRial(settingsStore.getSettingByKey('min_withdraw')), ) const minDepositAmount = computed(() => parseWalletMinRial(settingsStore.getSettingByKey('min_deposit')), ) const minWithdrawHint = computed(() => formatWalletMinHint('withdraw', minWithdrawAmount.value), ) const minDepositHint = computed(() => formatWalletMinHint('deposit', minDepositAmount.value), ) const disableButton = computed(() => { if (loading.value) return true if (walletStore?.walletInfo?.cash && !isDeposit.value) { if (cardItems.value.length > 0) { return ( walletStore?.walletInfo?.cash <= 0 || walletStore?.walletInfo?.cash < parseInt(String(form.value?.value)) || isNaN(parseInt(String(form.value?.value))) || parseInt(String(form.value?.value)) < minWithdrawAmount.value ) } return true } if (isDeposit.value) { return ( isNaN(parseInt(String(form.value?.value))) || parseInt(String(form.value?.value)) < minDepositAmount.value ) } return false }) function setIsDeposit(val: boolean) { isDeposit.value = val form.value.value = undefined form.value.percentWallet = 0 } function useStyle() { if (isDeposit.value) return 'right: 2%;' return ' right: 98%; transform: translate(100%, 0);' } const formatter = (value: number) => `${value}%` function percentChange(val: number) { if (val !== 0) form.value.value = parseInt((unitCalculator.value * val).toFixed()) else form.value.value = undefined } function resetData() { form.value.value = undefined form.value.percentWallet = 0 } async function addCard() { try { loading.value = true await createCard(cardForm.value) await getCards() showAddCard.value = false cardForm.value = { birth_date: 0, shaba_number: '' } message.success('کارت وارد شده با موفقیت افزوده شد و پس از تایید نمایش داده خواهد شد.') } catch (e) { console.log(e) } finally { loading.value = false } } async function getCards() { try { cardItems.value = (await getActivatedCards()) ?? [] form.value.card_id = cardItems.value.length ? cardItems.value[0].id : undefined } catch (e) { console.log(e) } } async function ok() { try { if (form.value.value !== undefined) { loading.value = true if (!isDeposit.value) { await confirmCode({ value: form.value.value }) showConfirmCode.value = true } else { chargeAccountModal.value = true } } else { message.error('ابتدا مبلغ را وارد کنید') } } catch (e) { console.log(e) } finally { loading.value = false } } async function initDepositTable() { try { depositPagination.value.page === 0 ? (loading.value = true) : (loadingMore.value = true) depositTableOutput.value = await getTransactionTable2(depositPagination.value) depositItems.value.push(...depositTableOutput.value.rows) } catch (e) { console.log(e) } finally { loading.value = false loadingMore.value = false } } async function initWithdrawTable() { try { withdrawPagination.value.page === 0 ? (loading.value = true) : (loadingMore.value = true) withdrawTableOutput.value = await getTransactionTable(withdrawPagination.value) withdrawItems.value.push(...withdrawTableOutput.value.rows) } catch (e) { console.log(e) } finally { loading.value = false loadingMore.value = false } } async function handleOnComplete(value: string) { try { infoVisible.value = true showConfirmCode.value = false await withdraw({ ...form.value, otp: value }) await walletStore.getMyWallet() await message.success('عملیات با موفقیت انجام شد') resetData() } catch (e) { console.log(e) } infoVisible.value = false refOtpInput.value?.clearInput() } onMounted(async () => { if (router.currentRoute.value.query.state === 'deposit') { isDeposit.value = true } cardForm.value.birth_date = userStore.userInfo?.birth_date await walletStore.getMyWallet() await initWithdrawTable() await initDepositTable() await getCards() }) if (!userStore.isSingle) { useInfiniteScroll( activeDepositScrollEl, async () => { if (isDeposit.value) { if ( depositTableOutput.value && (depositPagination.value.page + 1) * depositPagination.value.limit < depositTableOutput.value.query.total ) { depositPagination.value.page++ await initDepositTable() } } else if ( withdrawTableOutput.value && (withdrawPagination.value.page + 1) * withdrawPagination.value.limit < withdrawTableOutput.value.query.total ) { withdrawPagination.value.page++ await initWithdrawTable() } }, { distance: 12 } ) } const context: WalletPageContext = { isDeposit, walletStore, showAddCard, chargeAccountModal, showConfirmCode, infoVisible, refOtpInput, form, cardForm, disableButton, cardItems, depositItems, withdrawItems, mobileDepositScrollEl, desktopDepositScrollEl, minWithdrawHint, minDepositHint, usePriceWithoutType, usePrice, setIsDeposit, useStyle, formatter, percentChange, ok, addCard, getCards, handleOnComplete, } provide(WALLET_PAGE_CONTEXT_KEY, context) return context } export function useWalletPageContext() { const context = inject(WALLET_PAGE_CONTEXT_KEY) if (!context) { throw new Error('useWalletPageContext must be used within useWalletPage') } return context }