import type { CustomerAnalysisOverviewDto, CustomerAnalysisPeriodFilter, CustomerAnalysisSegmentCode, CustomerAnalysisSegmentListResultDto, CustomerDetailDto, CustomerMemberDetailDto, CustomerProfileDto, } from '#/api/customer'; import type { StoreListItemDto } from '#/api/store'; import { computed, onActivated, onMounted, reactive, ref, watch } from 'vue'; import { useRouter } from 'vue-router'; import { useAccessStore } from '@vben/stores'; import { createNavigationActions } from '#/views/customer/list/composables/customer-list-page/navigation-actions'; import { CUSTOMER_ANALYSIS_VIEW_PERMISSION, DEFAULT_PERIOD, DEFAULT_SEGMENT_CODE, EMPTY_OVERVIEW, } from './customer-analysis-page/constants'; import { createDataActions } from './customer-analysis-page/data-actions'; import { createDrawerActions } from './customer-analysis-page/drawer-actions'; import { createExportActions } from './customer-analysis-page/export-actions'; import { createMemberActions } from './customer-analysis-page/member-actions'; import { createSegmentActions } from './customer-analysis-page/segment-actions'; export function useCustomerAnalysisPage() { const accessStore = useAccessStore(); const router = useRouter(); const stores = ref([]); const selectedStoreId = ref(''); const isStoreLoading = ref(false); const period = ref(DEFAULT_PERIOD); const overview = ref({ ...EMPTY_OVERVIEW }); const isOverviewLoading = ref(false); const segmentResult = ref(null); const isSegmentDrawerOpen = ref(false); const isSegmentLoading = ref(false); const segmentKeyword = ref(''); const currentSegmentCode = ref(DEFAULT_SEGMENT_CODE); const segmentPagination = reactive({ page: 1, pageSize: 10, total: 0, }); const detail = ref(null); const isDetailDrawerOpen = ref(false); const isDetailLoading = ref(false); const profile = ref(null); const isProfileDrawerOpen = ref(false); const isProfileLoading = ref(false); const memberDetail = ref(null); const isMemberDrawerOpen = ref(false); const isMemberLoading = ref(false); const isExporting = ref(false); const storeOptions = computed(() => stores.value.map((item) => ({ label: item.name, value: item.id, })), ); const accessCodeSet = computed( () => new Set((accessStore.accessCodes ?? []).map(String)), ); const canExport = computed(() => accessCodeSet.value.has(CUSTOMER_ANALYSIS_VIEW_PERMISSION), ); const { loadStores, loadOverview, resetOverview } = createDataActions({ stores, selectedStoreId, period, overview, isStoreLoading, isOverviewLoading, }); const { openSegment, loadSegmentData, setSegmentDrawerOpen, setSegmentKeyword, handleSegmentSearch, handleSegmentPageChange, } = createSegmentActions({ selectedStoreId, period, currentSegmentCode, keyword: segmentKeyword, result: segmentResult, isSegmentDrawerOpen, isSegmentLoading, pagination: segmentPagination, }); const { openMember, setMemberDrawerOpen } = createMemberActions({ selectedStoreId, detail: memberDetail, isMemberDrawerOpen, isMemberLoading, }); const { openDetail, openProfile, setDetailDrawerOpen, setProfileDrawerOpen } = createDrawerActions({ selectedStoreId, detail, isDetailDrawerOpen, isDetailLoading, profile, isProfileDrawerOpen, isProfileLoading, }); const { openProfilePage } = createNavigationActions({ selectedStoreId, router, }); const { handleExport } = createExportActions({ selectedStoreId, period, isExporting, canExport, }); function setSelectedStoreId(value: string) { selectedStoreId.value = value; } function setPeriod(value: string) { const normalized = (value || DEFAULT_PERIOD) as CustomerAnalysisPeriodFilter; period.value = normalized; } async function openSegmentByCode(segmentCode: CustomerAnalysisSegmentCode) { await openSegment(segmentCode); } async function openTopCustomerDetail(customerKey: string) { await openDetail(customerKey); } async function openMemberFromDetail(customerKey: string) { await openMember(customerKey); } watch(selectedStoreId, async (storeId) => { if (!storeId) { resetOverview(); segmentResult.value = null; segmentPagination.total = 0; setDetailDrawerOpen(false); setProfileDrawerOpen(false); setMemberDrawerOpen(false); isSegmentDrawerOpen.value = false; return; } await loadOverview(); if (isSegmentDrawerOpen.value) { await loadSegmentData(); } }); watch(period, async () => { if (!selectedStoreId.value) { resetOverview(); return; } await loadOverview(); if (isSegmentDrawerOpen.value) { await loadSegmentData(); } }); onMounted(() => { void loadStores(); }); onActivated(() => { if (stores.value.length === 0 || !selectedStoreId.value) { void loadStores(); } }); return { canExport, currentSegmentCode, detail, handleExport, handleSegmentPageChange, handleSegmentSearch, isDetailDrawerOpen, isDetailLoading, isExporting, isMemberDrawerOpen, isMemberLoading, isOverviewLoading, isProfileDrawerOpen, isProfileLoading, isSegmentDrawerOpen, isSegmentLoading, isStoreLoading, memberDetail, openDetail, openMember, openMemberFromDetail, openProfile, openProfilePage, openSegmentByCode, openTopCustomerDetail, overview, period, profile, segmentKeyword, segmentPagination, segmentResult, selectedStoreId, setDetailDrawerOpen, setMemberDrawerOpen, setPeriod, setProfileDrawerOpen, setSegmentDrawerOpen, setSegmentKeyword, setSelectedStoreId, storeOptions, }; }