Files
TakeoutSaaS.TenantUI/apps/web-antd/src/views/customer/analysis/composables/useCustomerAnalysisPage.ts

245 lines
6.0 KiB
TypeScript

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<StoreListItemDto[]>([]);
const selectedStoreId = ref('');
const isStoreLoading = ref(false);
const period = ref<CustomerAnalysisPeriodFilter>(DEFAULT_PERIOD);
const overview = ref<CustomerAnalysisOverviewDto>({ ...EMPTY_OVERVIEW });
const isOverviewLoading = ref(false);
const segmentResult = ref<CustomerAnalysisSegmentListResultDto | null>(null);
const isSegmentDrawerOpen = ref(false);
const isSegmentLoading = ref(false);
const segmentKeyword = ref('');
const currentSegmentCode =
ref<CustomerAnalysisSegmentCode>(DEFAULT_SEGMENT_CODE);
const segmentPagination = reactive({
page: 1,
pageSize: 10,
total: 0,
});
const detail = ref<CustomerDetailDto | null>(null);
const isDetailDrawerOpen = ref(false);
const isDetailLoading = ref(false);
const profile = ref<CustomerProfileDto | null>(null);
const isProfileDrawerOpen = ref(false);
const isProfileLoading = ref(false);
const memberDetail = ref<CustomerMemberDetailDto | null>(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,
};
}