Files
boursecu_user/src/views/base/transactions/composables/useTransactionsPage.ts
T

189 lines
5.7 KiB
TypeScript
Raw Normal View History

import { computed, inject, onMounted, provide, ref, type ComponentPublicInstance, type InjectionKey } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
import { loading, loadingMore } from '@/utils'
import {
BOURSECU_TRANSACTION_TABS,
type BoursecuTradeSide,
type BoursecuTransactionTab,
type BoursecuTransactionTabId,
} from '../config/boursecuTabs'
import {
getActiveBoursecuTab,
initTransactionsPageData,
loadMoreTransactions,
reloadTransactionsTable,
resetTransactionsPagination,
transactionActiveTabId,
transactionDateFilter,
transactionItems,
transactionPagination,
transactionStatusFilter,
transactionTableOutput,
transactionTradeSide,
transactionsBoursecuMode,
} from './useTransactionsPageData'
export interface TransactionsPageContext {
pagination: typeof transactionPagination
items: typeof transactionItems
tableOutput: typeof transactionTableOutput
showFilter: ReturnType<typeof ref<boolean>>
dateFilter: typeof transactionDateFilter
statusFilter: typeof transactionStatusFilter
mobileObserverEl: ReturnType<typeof ref<HTMLElement | null>>
desktopObserverEl: ReturnType<typeof ref<HTMLElement | null>>
activeTabId: typeof transactionActiveTabId
tradeSide: typeof transactionTradeSide
activeTab: ReturnType<typeof computed<BoursecuTransactionTab>>
emptyText: ReturnType<typeof computed<string>>
resetPagination: typeof resetTransactionsPagination
initTable: () => Promise<void>
reloadTable: typeof reloadTransactionsTable
applyFilter: () => Promise<void>
setActiveTab: (tabId: BoursecuTransactionTabId) => Promise<void>
setTradeSide: (side: BoursecuTradeSide) => Promise<void>
applyInlineFilters: () => Promise<void>
bindMobileObserver: (el: Element | ComponentPublicInstance | null) => void
bindDesktopObserver: (el: Element | ComponentPublicInstance | null) => void
}
export const TRANSACTIONS_PAGE_KEY: InjectionKey<TransactionsPageContext> =
Symbol('transactionsPage')
export function useTransactionsPageProvider(options?: { boursecu?: boolean }) {
const isBoursecu = options?.boursecu ?? false
const isDesktop = useDesktopBreakpoint()
const showFilter = ref(false)
const mobileObserverEl = ref<HTMLElement | null>(null)
const desktopObserverEl = ref<HTMLElement | null>(null)
const activeObserverEl = computed(() =>
isDesktop.value ? desktopObserverEl.value : mobileObserverEl.value,
)
const activeTab = computed<BoursecuTransactionTab>(
() =>
BOURSECU_TRANSACTION_TABS.find((tab) => tab.id === transactionActiveTabId.value) ??
BOURSECU_TRANSACTION_TABS[0],
)
const emptyText = computed(() => {
if (!transactionsBoursecuMode.value) {
return 'تراکنشی موجود نیست'
}
if (activeTab.value.id === 'trades' && transactionTradeSide.value === 'sell') {
return 'معامله فروشی برای شما به ثبت نرسیده است'
}
return activeTab.value.emptyText
})
async function initTable() {
await reloadTransactionsTable()
}
async function applyFilter() {
await reloadTransactionsTable()
showFilter.value = false
}
async function setActiveTab(tabId: BoursecuTransactionTabId) {
if (transactionActiveTabId.value === tabId) {
return
}
transactionActiveTabId.value = tabId
await reloadTransactionsTable()
}
async function setTradeSide(side: BoursecuTradeSide) {
if (transactionTradeSide.value === side) {
return
}
transactionTradeSide.value = side
if (getActiveBoursecuTab().showTradeToggle) {
await reloadTransactionsTable()
}
}
async function applyInlineFilters() {
await reloadTransactionsTable()
}
function resolveObserverElement(el: Element | ComponentPublicInstance | null) {
if (!el) return null
if (el instanceof HTMLElement) return el
const root = (el as ComponentPublicInstance).$el
return root instanceof HTMLElement ? root : null
}
function bindMobileObserver(el: Element | ComponentPublicInstance | null) {
mobileObserverEl.value = resolveObserverElement(el)
}
function bindDesktopObserver(el: Element | ComponentPublicInstance | null) {
desktopObserverEl.value = resolveObserverElement(el)
}
useIntersectionObserver(
activeObserverEl,
async ([entry]) => {
if (entry?.isIntersecting) {
await loadMoreTransactions()
}
},
{
root: null,
rootMargin: '300px',
threshold: 0.01,
},
)
onMounted(async () => {
await initTransactionsPageData(isBoursecu)
})
const context: TransactionsPageContext = {
pagination: transactionPagination,
items: transactionItems,
tableOutput: transactionTableOutput,
showFilter,
dateFilter: transactionDateFilter,
statusFilter: transactionStatusFilter,
mobileObserverEl,
desktopObserverEl,
activeTabId: transactionActiveTabId,
tradeSide: transactionTradeSide,
activeTab,
emptyText,
resetPagination: resetTransactionsPagination,
initTable,
reloadTable: reloadTransactionsTable,
applyFilter,
setActiveTab,
setTradeSide,
applyInlineFilters,
bindMobileObserver,
bindDesktopObserver,
}
provide(TRANSACTIONS_PAGE_KEY, context)
return context
}
export function useTransactionsPageContext() {
const context = inject(TRANSACTIONS_PAGE_KEY)
if (!context) {
throw new Error('useTransactionsPageContext must be used within useTransactionsPageProvider')
}
return context
}
/** @deprecated Use useTransactionsPageProvider in index + useTransactionsPageContext in views. */
export function useTransactionsPage(options?: { boursecu?: boolean }) {
return useTransactionsPageProvider(options)
}