Files
TakeoutSaaS.TenantUI/apps/web-antd/src/views/customer/profile/composables/useCustomerProfilePage.ts

153 lines
3.8 KiB
TypeScript

import type { CustomerProfileDto } from '#/api/customer';
import type { StoreListItemDto } from '#/api/store';
import { computed, onActivated, onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { createDefaultListFilters } from './customer-profile-page/constants';
import { createDataActions } from './customer-profile-page/data-actions';
import {
buildRouteQuery,
parseRouteQueryValue,
} from './customer-profile-page/helpers';
export function useCustomerProfilePage() {
const route = useRoute();
const router = useRouter();
const PROFILE_ROUTE_PATH = '/customer/profile';
const stores = ref<StoreListItemDto[]>([]);
const selectedStoreId = ref('');
const activeCustomerKey = ref('');
const profile = ref<CustomerProfileDto | null>(null);
const isStoreLoading = ref(false);
const isProfileLoading = ref(false);
const filters = createDefaultListFilters();
const { loadStores, pickDefaultCustomerKey, loadProfile } = createDataActions(
{
stores,
profile,
filters,
isStoreLoading,
isProfileLoading,
},
);
const emptyDescription = computed(() => {
if (isStoreLoading.value || isProfileLoading.value) {
return '';
}
if (stores.value.length === 0) {
return '暂无门店,请先创建门店';
}
if (!activeCustomerKey.value) {
return '当前门店暂无客户';
}
return '暂无画像';
});
async function syncRouteQuery(storeId: string, customerKey: string) {
if (route.path !== PROFILE_ROUTE_PATH) {
return;
}
const currentStoreId = parseRouteQueryValue(route.query.storeId);
const currentCustomerKey = parseRouteQueryValue(route.query.customerKey);
if (currentStoreId === storeId && currentCustomerKey === customerKey) {
return;
}
await router.replace({
path: PROFILE_ROUTE_PATH,
query: buildRouteQuery(
route.query as Record<string, unknown>,
storeId,
customerKey,
),
});
}
function resolveStoreId(routeStoreId: string) {
if (!routeStoreId) {
return stores.value[0]?.id || '';
}
const matched = stores.value.find((item) => item.id === routeStoreId);
return matched?.id || stores.value[0]?.id || '';
}
async function loadProfileByRoute() {
if (route.path !== PROFILE_ROUTE_PATH) {
return;
}
if (stores.value.length === 0) {
await loadStores();
}
if (stores.value.length === 0) {
selectedStoreId.value = '';
activeCustomerKey.value = '';
profile.value = null;
return;
}
const routeStoreId = parseRouteQueryValue(route.query.storeId);
const routeCustomerKey = parseRouteQueryValue(route.query.customerKey);
const nextStoreId = resolveStoreId(routeStoreId);
selectedStoreId.value = nextStoreId;
let nextCustomerKey = routeCustomerKey;
if (!nextCustomerKey) {
nextCustomerKey = await pickDefaultCustomerKey(nextStoreId);
}
activeCustomerKey.value = nextCustomerKey;
if (!nextCustomerKey) {
profile.value = null;
await syncRouteQuery(nextStoreId, '');
return;
}
await loadProfile(nextStoreId, nextCustomerKey);
await syncRouteQuery(nextStoreId, nextCustomerKey);
}
watch(
() => route.fullPath,
() => {
if (route.path !== PROFILE_ROUTE_PATH) {
return;
}
void loadProfileByRoute();
},
);
onMounted(() => {
if (route.path === PROFILE_ROUTE_PATH) {
void loadProfileByRoute();
}
});
onActivated(() => {
if (route.path !== PROFILE_ROUTE_PATH) {
return;
}
if (stores.value.length === 0) {
void loadProfileByRoute();
}
});
return {
activeCustomerKey,
emptyDescription,
isProfileLoading,
isStoreLoading,
profile,
};
}