203 lines
5.6 KiB
TypeScript
203 lines
5.6 KiB
TypeScript
import { cache } from 'react';
|
|
|
|
import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product';
|
|
import { listProductTypes, listProducts } from '@lib/data/products';
|
|
import { listRegions } from '@lib/data/regions';
|
|
import type { StoreProduct, StoreProductType } from '@medusajs/types';
|
|
|
|
import type { AccountWithParams } from '@kit/accounts/types/accounts';
|
|
import type { AnalysisPackageWithVariant } from '@kit/shared/components/select-analysis-package';
|
|
|
|
import PersonalCode from '~/lib/utils';
|
|
|
|
import { loadCurrentUserAccount } from './load-user-account';
|
|
|
|
async function countryCodesLoader() {
|
|
const countryCodes = await listRegions().then((regions) =>
|
|
regions?.map((r) => r.countries?.map((c) => c.iso_2)).flat(),
|
|
);
|
|
return countryCodes ?? [];
|
|
}
|
|
export const loadCountryCodes = cache(countryCodesLoader);
|
|
|
|
async function productTypesLoader() {
|
|
const { productTypes } = await listProductTypes();
|
|
return productTypes ?? [];
|
|
}
|
|
export const loadProductTypes = cache(productTypesLoader);
|
|
|
|
function userSpecificVariantLoader({
|
|
account,
|
|
}: {
|
|
account: AccountWithParams;
|
|
}) {
|
|
const { personal_code: personalCode } = account;
|
|
if (!personalCode) {
|
|
throw new Error('Personal code not found');
|
|
}
|
|
|
|
const {
|
|
ageRange,
|
|
gender: { value: gender },
|
|
} = PersonalCode.parsePersonalCode(personalCode);
|
|
|
|
return ({ product }: { product: StoreProduct }) => {
|
|
const variants = product.variants;
|
|
if (!variants) {
|
|
return null;
|
|
}
|
|
|
|
const variant = variants.find((v) =>
|
|
v.options?.every((o) => [ageRange, gender].includes(o.value)),
|
|
);
|
|
if (!variant) {
|
|
return null;
|
|
}
|
|
return variant;
|
|
};
|
|
}
|
|
|
|
async function analysisPackageElementsLoader({
|
|
analysisPackagesWithVariant,
|
|
countryCode,
|
|
}: {
|
|
analysisPackagesWithVariant: AnalysisPackageWithVariant[];
|
|
countryCode: string;
|
|
}) {
|
|
const analysisElementMedusaProductIds = getAnalysisElementMedusaProductIds(
|
|
analysisPackagesWithVariant,
|
|
);
|
|
if (analysisElementMedusaProductIds.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
const {
|
|
response: { products },
|
|
} = await listProducts({
|
|
countryCode,
|
|
queryParams: {
|
|
id: analysisElementMedusaProductIds,
|
|
limit: 100,
|
|
order: 'title',
|
|
},
|
|
});
|
|
|
|
const standardPackage = analysisPackagesWithVariant.find(
|
|
({ isStandard }) => isStandard,
|
|
);
|
|
const standardPlusPackage = analysisPackagesWithVariant.find(
|
|
({ isStandardPlus }) => isStandardPlus,
|
|
);
|
|
const premiumPackage = analysisPackagesWithVariant.find(
|
|
({ isPremium }) => isPremium,
|
|
);
|
|
if (!standardPackage || !standardPlusPackage || !premiumPackage) {
|
|
return [];
|
|
}
|
|
|
|
const standardPackageAnalyses = getAnalysisElementMedusaProductIds([
|
|
standardPackage,
|
|
]);
|
|
const standardPlusPackageAnalyses = getAnalysisElementMedusaProductIds([
|
|
standardPlusPackage,
|
|
]);
|
|
const premiumPackageAnalyses = getAnalysisElementMedusaProductIds([
|
|
premiumPackage,
|
|
]);
|
|
|
|
return products.map(({ id, title, description }) => ({
|
|
id,
|
|
title,
|
|
description,
|
|
isIncludedInStandard: standardPackageAnalyses.includes(id),
|
|
isIncludedInStandardPlus: standardPlusPackageAnalyses.includes(id),
|
|
isIncludedInPremium: premiumPackageAnalyses.includes(id),
|
|
}));
|
|
}
|
|
|
|
async function analysisPackagesWithVariantLoader({
|
|
account,
|
|
countryCode,
|
|
productType,
|
|
}: {
|
|
account: AccountWithParams;
|
|
countryCode: string;
|
|
productType: StoreProductType;
|
|
}) {
|
|
const analysisPackagesResponse = await listProducts({
|
|
countryCode,
|
|
queryParams: { limit: 100, 'type_id[0]': productType.id },
|
|
});
|
|
|
|
const getVariant = userSpecificVariantLoader({ account });
|
|
const analysisPackagesWithVariant =
|
|
analysisPackagesResponse.response.products.reduce((acc, product) => {
|
|
const variant = getVariant({ product });
|
|
if (!variant) {
|
|
return acc;
|
|
}
|
|
return [
|
|
...acc,
|
|
{
|
|
variant,
|
|
variantId: variant.id,
|
|
nrOfAnalyses: getAnalysisElementMedusaProductIds([
|
|
{ ...product, variant },
|
|
]).length,
|
|
price: variant.calculated_price?.calculated_amount ?? 0,
|
|
title: product.title,
|
|
subtitle: product.subtitle,
|
|
description: product.description,
|
|
metadata: product.metadata,
|
|
isStandard: product.metadata?.analysisPackageTier === 'standard',
|
|
isStandardPlus:
|
|
product.metadata?.analysisPackageTier === 'standard-plus',
|
|
isPremium: product.metadata?.analysisPackageTier === 'premium',
|
|
},
|
|
];
|
|
}, [] as AnalysisPackageWithVariant[]);
|
|
|
|
return analysisPackagesWithVariant;
|
|
}
|
|
|
|
async function analysisPackagesLoader() {
|
|
const { account } = await loadCurrentUserAccount();
|
|
if (!account) {
|
|
throw new Error('Account not found');
|
|
}
|
|
|
|
const [countryCodes, productTypes] = await Promise.all([
|
|
loadCountryCodes(),
|
|
loadProductTypes(),
|
|
]);
|
|
const countryCode = countryCodes[0]!;
|
|
const productType = productTypes.find(
|
|
({ metadata }) => metadata?.handle === 'analysis-packages',
|
|
);
|
|
|
|
if (!productType) {
|
|
return { analysisPackageElements: [], analysisPackages: [], countryCode };
|
|
}
|
|
|
|
const analysisPackagesWithVariant = await analysisPackagesWithVariantLoader({
|
|
account,
|
|
countryCode,
|
|
productType,
|
|
});
|
|
if (!analysisPackagesWithVariant) {
|
|
return { analysisPackageElements: [], analysisPackages: [], countryCode };
|
|
}
|
|
|
|
const analysisPackageElements = await analysisPackageElementsLoader({
|
|
analysisPackagesWithVariant,
|
|
countryCode,
|
|
});
|
|
|
|
return {
|
|
analysisPackageElements,
|
|
analysisPackages: analysisPackagesWithVariant,
|
|
countryCode,
|
|
};
|
|
}
|
|
export const loadAnalysisPackages = cache(analysisPackagesLoader);
|