Files
ghatreh_user/src/views/base/wallet/composables/useWalletPage.ts
T
2026-07-19 21:49:31 +03:30

316 lines
9.7 KiB
TypeScript

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<typeof ref<boolean>>
walletStore: ReturnType<typeof useWalletStore>
showAddCard: ReturnType<typeof ref<boolean>>
chargeAccountModal: ReturnType<typeof ref<boolean>>
showConfirmCode: ReturnType<typeof ref<boolean>>
infoVisible: ReturnType<typeof ref<boolean>>
refOtpInput: ReturnType<typeof ref<InstanceType<typeof OtpInput> | null>>
form: ReturnType<typeof ref<Transaction>>
cardForm: ReturnType<typeof ref<Card>>
disableButton: ReturnType<typeof computed<boolean>>
cardItems: ReturnType<typeof ref<Card[]>>
depositItems: ReturnType<typeof ref<Transaction[]>>
withdrawItems: ReturnType<typeof ref<Transaction[]>>
mobileDepositScrollEl: ReturnType<typeof ref<HTMLElement | null>>
desktopDepositScrollEl: ReturnType<typeof ref<HTMLElement | null>>
minWithdrawHint: ReturnType<typeof computed<string>>
minDepositHint: ReturnType<typeof computed<string>>
usePriceWithoutType: typeof usePriceWithoutType
usePrice: typeof usePrice
setIsDeposit: (val: boolean) => void
useStyle: () => string
formatter: (value: number) => string
percentChange: (val: number) => void
ok: () => Promise<void>
addCard: () => Promise<void>
getCards: () => Promise<void>
handleOnComplete: (value: string) => Promise<void>
}
export const WALLET_PAGE_CONTEXT_KEY: InjectionKey<WalletPageContext> = 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<InstanceType<typeof OtpInput> | null>(null)
const mobileDepositScrollEl = ref<HTMLElement | null>(null)
const desktopDepositScrollEl = ref<HTMLElement | null>(null)
const form = ref<Transaction>({
value: undefined,
percentWallet: 0,
card_id: undefined,
})
const cardForm = ref<Card>({
birth_date: 0,
shaba_number: '',
})
const cardItems = ref<Card[]>([])
const depositItems = ref<Transaction[]>([])
const withdrawItems = ref<Transaction[]>([])
const depositTableOutput = ref<TableOutput<Transaction> | null>(null)
const withdrawTableOutput = ref<TableOutput<Transaction> | null>(null)
const depositPagination = ref<TableEngineInput>({ filters: [], limit: 6, page: 0 })
const withdrawPagination = ref<TableEngineInput>({
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
}