Files
medreport_mrb2b/app/home/(user)/_lib/server/load-analysis-packages.ts

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);