189 lines
5.7 KiB
TypeScript
189 lines
5.7 KiB
TypeScript
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)
|
||
|
|
}
|