feat(MED-121): use age+sex specific analysis package variants
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import { cache } from 'react';
|
||||
import Isikukood, { Gender } from 'isikukood';
|
||||
|
||||
import { listProductTypes, listProducts } from "@lib/data/products";
|
||||
import { listRegions } from '@lib/data/regions';
|
||||
import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product';
|
||||
import type { StoreProduct } from '@medusajs/types';
|
||||
import { loadCurrentUserAccount } from './load-user-account';
|
||||
import { AnalysisPackageWithVariant } from '~/components/select-analysis-package';
|
||||
import { AccountWithParams } from '@/packages/features/accounts/src/server/api';
|
||||
|
||||
async function countryCodesLoader() {
|
||||
const countryCodes = await listRegions().then((regions) =>
|
||||
@@ -19,36 +23,153 @@ async function productTypesLoader() {
|
||||
}
|
||||
export const loadProductTypes = cache(productTypesLoader);
|
||||
|
||||
async function analysisPackagesLoader() {
|
||||
const [countryCodes, productTypes] = await Promise.all([loadCountryCodes(), loadProductTypes()]);
|
||||
const countryCode = countryCodes[0]!;
|
||||
function userSpecificVariantLoader({
|
||||
account,
|
||||
}: {
|
||||
account: AccountWithParams;
|
||||
}) {
|
||||
const { personal_code: personalCode } = account;
|
||||
if (!personalCode) {
|
||||
throw new Error('Personal code not found');
|
||||
}
|
||||
const parsed = new Isikukood(personalCode);
|
||||
const ageRange = (() => {
|
||||
const age = parsed.getAge();
|
||||
if (age >= 18 && age <= 29) {
|
||||
return '18-29';
|
||||
}
|
||||
if (age >= 30 && age <= 49) {
|
||||
return '30-49';
|
||||
}
|
||||
if (age >= 50 && age <= 59) {
|
||||
return '50-59';
|
||||
}
|
||||
if (age >= 60) {
|
||||
return '60';
|
||||
}
|
||||
throw new Error('Age range not supported');
|
||||
})();
|
||||
const gender = parsed.getGender() === Gender.MALE ? 'M' : 'F';
|
||||
|
||||
let analysisPackages: StoreProduct[] = [];
|
||||
let analysisPackageElements: StoreProduct[] = [];
|
||||
return ({
|
||||
product,
|
||||
}: {
|
||||
product: StoreProduct;
|
||||
}) => {
|
||||
const variants = product.variants;
|
||||
if (!variants) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const productType = productTypes.find(({ metadata }) => metadata?.handle === 'analysis-packages');
|
||||
if (!productType) {
|
||||
return { analysisPackageElements, analysisPackages, countryCode };
|
||||
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,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
}: {
|
||||
account: AccountWithParams;
|
||||
countryCode: string;
|
||||
}) {
|
||||
const productTypes = await loadProductTypes();
|
||||
const productType = productTypes.find(({ metadata }) => metadata?.handle === 'analysis-packages');
|
||||
if (!productType) {
|
||||
return null;
|
||||
}
|
||||
const analysisPackagesResponse = await listProducts({
|
||||
countryCode,
|
||||
queryParams: { limit: 100, "type_id[0]": productType.id },
|
||||
});
|
||||
analysisPackages = analysisPackagesResponse.response.products;
|
||||
|
||||
const analysisElementMedusaProductIds = getAnalysisElementMedusaProductIds(analysisPackages);
|
||||
if (analysisElementMedusaProductIds.length > 0) {
|
||||
const { response: { products } } = await listProducts({
|
||||
countryCode,
|
||||
queryParams: {
|
||||
id: analysisElementMedusaProductIds,
|
||||
limit: 100,
|
||||
},
|
||||
});
|
||||
analysisPackageElements = products;
|
||||
const getVariant = userSpecificVariantLoader({ account });
|
||||
const analysisPackagesWithVariant = analysisPackagesResponse.response.products
|
||||
.reduce((acc, product) => {
|
||||
const variant = getVariant({ product });
|
||||
if (!variant) {
|
||||
return acc;
|
||||
}
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
variantId: variant.id,
|
||||
nrOfAnalyses: getAnalysisElementMedusaProductIds([product]).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');
|
||||
}
|
||||
|
||||
return { analysisPackageElements, analysisPackages, countryCode };
|
||||
const countryCodes = await loadCountryCodes();
|
||||
const countryCode = countryCodes[0]!;
|
||||
|
||||
const analysisPackagesWithVariant = await analysisPackagesWithVariantLoader({ account, countryCode });
|
||||
if (!analysisPackagesWithVariant) {
|
||||
return { analysisPackageElements: [], analysisPackages: [], countryCode };
|
||||
}
|
||||
|
||||
const analysisPackageElements = await analysisPackageElementsLoader({ analysisPackagesWithVariant, countryCode });
|
||||
|
||||
return { analysisPackageElements, analysisPackages: analysisPackagesWithVariant, countryCode };
|
||||
}
|
||||
export const loadAnalysisPackages = cache(analysisPackagesLoader);
|
||||
|
||||
Reference in New Issue
Block a user