feat(MED-131): show package analysis elements in comparison modal

This commit is contained in:
2025-08-04 11:51:38 +03:00
parent d7d089c11d
commit 8c4df731aa
7 changed files with 224 additions and 106 deletions

View File

@@ -20,7 +20,7 @@ export const generateMetadata = async () => {
};
async function OrderAnalysisPackagePage() {
const { analysisPackages, countryCode } = await loadAnalysisPackages();
const { analysisElements, analysisPackages, countryCode } = await loadAnalysisPackages();
return (
<PageBody>
@@ -29,6 +29,7 @@ async function OrderAnalysisPackagePage() {
<Trans i18nKey={'marketing:selectPackage'} />
</h3>
<ComparePackagesModal
analysisElements={analysisElements}
analysisPackages={analysisPackages}
triggerElement={
<Button variant="secondary" className="gap-2">

View File

@@ -23,79 +23,8 @@ import { withI18n } from '~/lib/i18n/with-i18n';
import { PackageHeader } from '@/components/package-header';
import { InfoTooltip } from '@/components/ui/info-tooltip';
import { StoreProduct } from '@medusajs/types';
const dummyCards = [
{
titleKey: 'product:standard.label',
price: 40,
nrOfAnalyses: 4,
tagColor: 'bg-cyan',
},
{
titleKey: 'product:standardPlus.label',
price: 85,
nrOfAnalyses: 10,
tagColor: 'bg-warning',
},
{
titleKey: 'product:premium.label',
price: 140,
nrOfAnalyses: '12+',
tagColor: 'bg-purple',
},
];
const dummyRows = [
{
analysisNameKey: 'product:clinicalBloodDraw.label',
tooltipContentKey: 'product:clinicalBloodDraw.description',
includedInStandard: 1,
includedInStandardPlus: 1,
includedInPremium: 1,
},
{
analysisNameKey: 'product:crp.label',
tooltipContentKey: 'product:crp.description',
includedInStandard: 1,
includedInStandardPlus: 1,
includedInPremium: 1,
},
{
analysisNameKey: 'product:ferritin.label',
tooltipContentKey: 'product:ferritin.description',
includedInStandard: 0,
includedInStandardPlus: 1,
includedInPremium: 1,
},
{
analysisNameKey: 'product:vitaminD.label',
tooltipContentKey: 'product:vitaminD.description',
includedInStandard: 0,
includedInStandardPlus: 1,
includedInPremium: 1,
},
{
analysisNameKey: 'product:glucose.label',
tooltipContentKey: 'product:glucose.description',
includedInStandard: 1,
includedInStandardPlus: 1,
includedInPremium: 1,
},
{
analysisNameKey: 'product:alat.label',
tooltipContentKey: 'product:alat.description',
includedInStandard: 1,
includedInStandardPlus: 1,
includedInPremium: 1,
},
{
analysisNameKey: 'product:ast.label',
tooltipContentKey: 'product:ast.description',
includedInStandard: 1,
includedInStandardPlus: 1,
includedInPremium: 1,
},
];
import type { AnalysisElement } from '~/lib/services/analysis-element.service';
import { getAnalysisElementOriginalIds } from '@lib/data/products';
const CheckWithBackground = () => {
return (
@@ -106,14 +35,28 @@ const CheckWithBackground = () => {
};
const ComparePackagesModal = async ({
analysisElements,
analysisPackages,
triggerElement,
}: {
analysisElements: AnalysisElement[];
analysisPackages: StoreProduct[];
triggerElement: JSX.Element;
}) => {
const { t, language } = await createI18nServerInstance();
const standardPackage = analysisPackages.find(({ metadata }) => metadata?.analysisPackageTier === 'standard')!;
const standardPlusPackage = analysisPackages.find(({ metadata }) => metadata?.analysisPackageTier === 'standard-plus')!;
const premiumPackage = analysisPackages.find(({ metadata }) => metadata?.analysisPackageTier === 'premium')!;
if (!standardPackage || !standardPlusPackage || !premiumPackage) {
return null;
}
const standardPackageAnalyses = await getAnalysisElementOriginalIds([standardPackage]);
const standardPlusPackageAnalyses = await getAnalysisElementOriginalIds([standardPlusPackage]);
const premiumPackageAnalyses = await getAnalysisElementOriginalIds([premiumPackage]);
return (
<Dialog>
<DialogTrigger asChild>{triggerElement}</DialogTrigger>
@@ -138,7 +81,7 @@ const ComparePackagesModal = async ({
<p className="text-muted-foreground mx-auto w-3/5 text-sm">
{t('product:healthPackageComparison.description')}
</p>
<div className="rounded-md border">
<div className="rounded-md border max-h-[80vh] overflow-y-auto">
<Table>
<TableHeader>
<TableRow>
@@ -165,37 +108,41 @@ const ComparePackagesModal = async ({
</TableRow>
</TableHeader>
<TableBody>
{dummyRows.map(
{analysisElements.map(
(
{
analysisNameKey,
tooltipContentKey,
includedInStandard,
includedInStandardPlus,
includedInPremium,
analysis_name_lab: analysisName,
analysis_id_original: analysisId,
},
index,
) => (
<TableRow key={index}>
<TableCell className="py-6">
{t(analysisNameKey)}{' '}
<InfoTooltip
content={t(tooltipContentKey)}
icon={<QuestionMarkCircledIcon />}
/>
</TableCell>
<TableCell align="center" className="py-6">
{!!includedInStandard && <CheckWithBackground />}
</TableCell>
<TableCell align="center" className="py-6">
{!!includedInStandardPlus && <CheckWithBackground />}
</TableCell>
<TableCell align="center" className="py-6">
{!!includedInPremium && <CheckWithBackground />}
</TableCell>
</TableRow>
),
)}
) => {
if (!analysisName) {
return null;
}
const includedInStandard = standardPackageAnalyses.includes(analysisId);
const includedInStandardPlus = standardPlusPackageAnalyses.includes(analysisId);
const includedInPremium = premiumPackageAnalyses.includes(analysisId);
return (
<TableRow key={index}>
<TableCell className="py-6">
{analysisName}{' '}
{/* <InfoTooltip
content={t(tooltipContentKey)}
icon={<QuestionMarkCircledIcon />}
/> */}
</TableCell>
<TableCell align="center" className="py-6">
{includedInStandard && <CheckWithBackground />}
</TableCell>
<TableCell align="center" className="py-6">
{(includedInStandard || includedInStandardPlus) && <CheckWithBackground />}
</TableCell>
<TableCell align="center" className="py-6">
{(includedInStandard || includedInStandardPlus || includedInPremium) && <CheckWithBackground />}
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>

View File

@@ -1,6 +1,8 @@
import { cache } from 'react';
import { listProductTypes, listProducts, listRegions } from "@lib/data";
import { getAnalysisElementOriginalIds, listProductTypes, listProducts } from "@lib/data/products";
import { listRegions } from '@lib/data/regions';
import { AnalysisElement, getAnalysisElements } from '~/lib/services/analysis-element.service';
async function countryCodesLoader() {
const countryCodes = await listRegions().then((regions) =>
@@ -22,13 +24,21 @@ async function analysisPackagesLoader() {
const productType = productTypes.find(({ metadata }) => metadata?.handle === 'analysis-packages');
if (!productType) {
return { analysisPackages: [], countryCode };
return { analysisElements: [], analysisPackages: [], countryCode };
}
const { response } = await listProducts({
countryCode,
queryParams: { limit: 100, "type_id[0]": productType.id },
});
return { analysisPackages: response.products, countryCode };
const analysisPackages = response.products;
let analysisElements: AnalysisElement[] = [];
const analysisElementOriginalIds = await getAnalysisElementOriginalIds(analysisPackages);
if (analysisElementOriginalIds.length) {
analysisElements = await getAnalysisElements({ originalIds: analysisElementOriginalIds });
}
return { analysisElements, analysisPackages, countryCode };
}
export const loadAnalysisPackages = cache(analysisPackagesLoader);

View File

@@ -24,7 +24,7 @@ export const generateMetadata = async () => {
};
async function SelectPackagePage() {
const { analysisPackages, countryCode } = await loadAnalysisPackages();
const { analysisElements, analysisPackages, countryCode } = await loadAnalysisPackages();
return (
<div className="container mx-auto my-24 flex flex-col items-center space-y-12">
@@ -34,6 +34,7 @@ async function SelectPackagePage() {
<Trans i18nKey={'marketing:selectPackage'} />
</h3>
<ComparePackagesModal
analysisElements={analysisElements}
analysisPackages={analysisPackages}
triggerElement={
<Button variant="secondary" className="gap-2">