245 lines
6.0 KiB
TypeScript
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,
|
|
};
|
|
}
|