diff --git a/app/home/(user)/(dashboard)/order-analysis-package/page.tsx b/app/home/(user)/(dashboard)/order-analysis-package/page.tsx index 81ef7e8..5c7db8b 100644 --- a/app/home/(user)/(dashboard)/order-analysis-package/page.tsx +++ b/app/home/(user)/(dashboard)/order-analysis-package/page.tsx @@ -20,7 +20,7 @@ export const generateMetadata = async () => { }; async function OrderAnalysisPackagePage() { - const { analysisPackages, countryCode } = await loadAnalysisPackages(); + const { analysisElements, analysisPackages, countryCode } = await loadAnalysisPackages(); return ( @@ -29,6 +29,7 @@ async function OrderAnalysisPackagePage() { diff --git a/app/home/(user)/_components/compare-packages-modal.tsx b/app/home/(user)/_components/compare-packages-modal.tsx index ca2e2db..247c6ca 100644 --- a/app/home/(user)/_components/compare-packages-modal.tsx +++ b/app/home/(user)/_components/compare-packages-modal.tsx @@ -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 ( {triggerElement} @@ -138,7 +81,7 @@ const ComparePackagesModal = async ({

{t('product:healthPackageComparison.description')}

-
+
@@ -165,37 +108,41 @@ const ComparePackagesModal = async ({ - {dummyRows.map( + {analysisElements.map( ( { - analysisNameKey, - tooltipContentKey, - includedInStandard, - includedInStandardPlus, - includedInPremium, + analysis_name_lab: analysisName, + analysis_id_original: analysisId, }, index, - ) => ( - - - {t(analysisNameKey)}{' '} - } - /> - - - {!!includedInStandard && } - - - {!!includedInStandardPlus && } - - - {!!includedInPremium && } - - - ), - )} + ) => { + if (!analysisName) { + return null; + } + const includedInStandard = standardPackageAnalyses.includes(analysisId); + const includedInStandardPlus = standardPlusPackageAnalyses.includes(analysisId); + const includedInPremium = premiumPackageAnalyses.includes(analysisId); + return ( + + + {analysisName}{' '} + {/* } + /> */} + + + {includedInStandard && } + + + {(includedInStandard || includedInStandardPlus) && } + + + {(includedInStandard || includedInStandardPlus || includedInPremium) && } + + + ); + })}
diff --git a/app/home/(user)/_lib/server/load-analysis-packages.ts b/app/home/(user)/_lib/server/load-analysis-packages.ts index 59da4ae..d46e8d1 100644 --- a/app/home/(user)/_lib/server/load-analysis-packages.ts +++ b/app/home/(user)/_lib/server/load-analysis-packages.ts @@ -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); diff --git a/app/select-package/page.tsx b/app/select-package/page.tsx index 3ebc34b..5549cc2 100644 --- a/app/select-package/page.tsx +++ b/app/select-package/page.tsx @@ -24,7 +24,7 @@ export const generateMetadata = async () => { }; async function SelectPackagePage() { - const { analysisPackages, countryCode } = await loadAnalysisPackages(); + const { analysisElements, analysisPackages, countryCode } = await loadAnalysisPackages(); return (
@@ -34,6 +34,7 @@ async function SelectPackagePage() { diff --git a/lib/services/analysis-element.service.ts b/lib/services/analysis-element.service.ts new file mode 100644 index 0000000..783a348 --- /dev/null +++ b/lib/services/analysis-element.service.ts @@ -0,0 +1,60 @@ +import { getSupabaseServerClient } from '@kit/supabase/server-client'; +import { Json, Tables } from '@kit/supabase/database'; +import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; +import type { IMaterialGroup, IUuringElement } from './medipost.types'; + +export type AnalysisElement = Tables<{ schema: 'medreport' }, 'analysis_elements'> & { + analysis_groups: Tables<{ schema: 'medreport' }, 'analysis_groups'>; +}; + +export async function getAnalysisElements({ + originalIds, +}: { + originalIds: string[] +}) { + const { data: analysisElements } = await getSupabaseServerClient() + .schema('medreport') + .from('analysis_elements') + .select(`*, analysis_groups(*)`) + .in('analysis_id_original', [...new Set(originalIds)]) + .order('order', { ascending: true }); + + return analysisElements ?? []; +} + +export async function createAnalysisElement({ + analysisElement, + analysisGroupId, + materialGroups, +}: { + analysisElement: IUuringElement; + analysisGroupId: number; + materialGroups: IMaterialGroup[]; +}) { + const { data: insertedAnalysisElement, error } = await getSupabaseServerAdminClient() + .schema('medreport') + .from('analysis_elements') + .upsert( + { + analysis_id_oid: analysisElement.UuringIdOID, + analysis_id_original: analysisElement.UuringId, + tehik_short_loinc: analysisElement.TLyhend, + tehik_loinc_name: analysisElement.KNimetus, + analysis_name_lab: analysisElement.UuringNimi, + order: analysisElement.Jarjekord, + parent_analysis_group_id: analysisGroupId, + material_groups: materialGroups as unknown as Json[], + }, + { onConflict: 'analysis_id_original', ignoreDuplicates: false }, + ) + .select('id'); + + const id = insertedAnalysisElement?.[0]?.id; + if (error || !id) { + throw new Error( + `Failed to insert analysis element (id: ${analysisElement.UuringId}), error: ${error?.message}`, + ); + } + + return id; +} diff --git a/lib/services/medipost.types.ts b/lib/services/medipost.types.ts new file mode 100644 index 0000000..3f14de8 --- /dev/null +++ b/lib/services/medipost.types.ts @@ -0,0 +1,85 @@ +export interface IUuringElement { + UuringIdOID: string; + UuringId: string; + TLyhend: string; + KNimetus: string; + UuringNimi: string; + Jarjekord: number; + Kood: { + HkKood: string; + HkKoodiKordaja: number; + Koefitsient: number; + Hind: number; + }[]; + UuringuElement: { + UuringIdOID: string; + UuringId: string; + TLyhend: string; + KNimetus: string; + UuringNimi: string; + Jarjekord: number; + Kood: { + HkKood: string; + HkKoodiKordaja: number; + Koefitsient: number; + Hind: number; + }[]; + }[]; +} + +export interface IMaterialGroup { + id: string; + name: string; + order: number; +} + +export interface IMedipostPublicMessageDataParsed { + ANSWER: { + CODE: number; + MESSAGE: string; + }; + Saadetis: { + Teenused: { + Teostaja: { + UuringuGrupp: { + UuringuGruppId: string; + UuringuGruppNimi: string; + UuringuGruppJarjekord: number; + Kood: { + HkKood: string; + HkKoodiKordaja: number; + Koefitsient: number; + Hind: number; + }[]; + Uuring: { + UuringId: string; + UuringNimi: string; + UuringJarjekord: number; + UuringuElement: { + UuringIdOID: string; + UuringId: string; + TLyhend: string; + KNimetus: string; + UuringNimi: string; + Jarjekord: number; + Kood: { + HkKood: string; + HkKoodiKordaja: number; + Koefitsient: number; + Hind: number; + }[]; + UuringuElement: IUuringElement; + }[]; + MaterjalideGrupp: IMaterialGroup[]; + Kood: { + HkKood: string; + HkKoodiKordaja: number; + Koefitsient: number; + Hind: number; + }[]; + }[]; + }[]; + }[]; + }; + }; +} diff --git a/packages/features/medusa-storefront/src/lib/data/products.ts b/packages/features/medusa-storefront/src/lib/data/products.ts index 810d205..2548058 100644 --- a/packages/features/medusa-storefront/src/lib/data/products.ts +++ b/packages/features/medusa-storefront/src/lib/data/products.ts @@ -85,6 +85,20 @@ export const listProducts = async ({ }) } +export const getAnalysisElementOriginalIds = async (products: HttpTypes.StoreProduct[]) => { + return products + .flatMap(({ metadata }) => { + const value = metadata?.analysisElementOriginalIds; + try { + return JSON.parse(value as string); + } catch (e) { + console.error("Failed to parse analysisElementOriginalIds from analysis package, possibly invalid format", e); + return []; + } + }) + .filter(Boolean) as string[]; +} + /** * This will fetch 100 products to the Next.js cache and sort them based on the sortBy parameter. * It will then return the paginated products based on the page and limit parameters.