Merge pull request #94 from MR-medreport/develop

develop -> main
This commit is contained in:
2025-09-12 11:26:24 +00:00
committed by GitHub
16 changed files with 137 additions and 105 deletions

View File

@@ -6,11 +6,12 @@ type ProcessedMessage = {
hasPartialAnalysisResponse: boolean; hasPartialAnalysisResponse: boolean;
hasFullAnalysisResponse: boolean; hasFullAnalysisResponse: boolean;
medusaOrderId: string | undefined; medusaOrderId: string | undefined;
analysisOrderId: number | undefined;
}; };
type GroupedResults = { type GroupedResults = {
processed: Pick<ProcessedMessage, 'messageId' | 'medusaOrderId'>[]; processed: Pick<ProcessedMessage, 'messageId' | 'analysisOrderId'>[];
waitingForResults: Pick<ProcessedMessage, 'messageId' | 'medusaOrderId'>[]; waitingForResults: Pick<ProcessedMessage, 'messageId' | 'analysisOrderId'>[];
}; };
export default async function syncAnalysisResults() { export default async function syncAnalysisResults() {
@@ -37,14 +38,14 @@ export default async function syncAnalysisResults() {
} }
const groupedResults = processedMessages.reduce((acc, result) => { const groupedResults = processedMessages.reduce((acc, result) => {
if (result.medusaOrderId) { if (result.analysisOrderId) {
if (result.hasAnalysisResponse) { if (result.hasAnalysisResponse) {
if (!acc.processed) { if (!acc.processed) {
acc.processed = []; acc.processed = [];
} }
acc.processed.push({ acc.processed.push({
messageId: result.messageId, messageId: result.messageId,
medusaOrderId: result.medusaOrderId, analysisOrderId: result.analysisOrderId,
}); });
} else { } else {
if (!acc.waitingForResults) { if (!acc.waitingForResults) {
@@ -52,7 +53,7 @@ export default async function syncAnalysisResults() {
} }
acc.waitingForResults.push({ acc.waitingForResults.push({
messageId: result.messageId, messageId: result.messageId,
medusaOrderId: result.medusaOrderId, analysisOrderId: result.analysisOrderId,
}); });
} }
} }

View File

@@ -37,7 +37,7 @@ export async function POST(request: NextRequest) {
}, },
orderedAnalysisElementsIds: idsToSend.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[], orderedAnalysisElementsIds: idsToSend.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[],
orderedAnalysesIds: idsToSend.map(({ analysisId }) => analysisId).filter(Boolean) as number[], orderedAnalysesIds: idsToSend.map(({ analysisId }) => analysisId).filter(Boolean) as number[],
orderId: medusaOrderId, orderId: medreportOrder.id,
orderCreatedAt: new Date(medreportOrder.created_at), orderCreatedAt: new Date(medreportOrder.created_at),
}); });

View File

@@ -29,7 +29,7 @@ export async function POST(request: Request) {
}, },
orderedAnalysisElementsIds: orderedAnalysisElementsIds.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[], orderedAnalysisElementsIds: orderedAnalysisElementsIds.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[],
orderedAnalysesIds: orderedAnalysisElementsIds.map(({ analysisId }) => analysisId).filter(Boolean) as number[], orderedAnalysesIds: orderedAnalysisElementsIds.map(({ analysisId }) => analysisId).filter(Boolean) as number[],
orderId: medusaOrderId, orderId: analysisOrder.id,
orderCreatedAt: new Date(analysisOrder.created_at), orderCreatedAt: new Date(analysisOrder.created_at),
}); });

View File

@@ -27,7 +27,7 @@ async function OrderConfirmedPage(props: {
}) { }) {
const params = await props.params; const params = await props.params;
const order = await getAnalysisOrder({ orderId: Number(params.orderId) }).catch(() => null); const order = await getAnalysisOrder({ analysisOrderId: Number(params.orderId) }).catch(() => null);
if (!order) { if (!order) {
redirect(pathsConfig.app.myOrders); redirect(pathsConfig.app.myOrders);
} }

View File

@@ -27,7 +27,7 @@ async function OrderConfirmedPage(props: {
}) { }) {
const params = await props.params; const params = await props.params;
const order = await getAnalysisOrder({ orderId: Number(params.orderId) }).catch(() => null); const order = await getAnalysisOrder({ analysisOrderId: Number(params.orderId) }).catch(() => null);
if (!order) { if (!order) {
redirect(pathsConfig.app.myOrders); redirect(pathsConfig.app.myOrders);
} }

View File

@@ -1,4 +1,5 @@
import Link from 'next/link'; import Link from 'next/link';
import { redirect } from 'next/navigation';
import { CaretRightIcon } from '@radix-ui/react-icons'; import { CaretRightIcon } from '@radix-ui/react-icons';
import { Scale } from 'lucide-react'; import { Scale } from 'lucide-react';
@@ -14,7 +15,6 @@ import { withI18n } from '~/lib/i18n/with-i18n';
import ComparePackagesModal from '../home/(user)/_components/compare-packages-modal'; import ComparePackagesModal from '../home/(user)/_components/compare-packages-modal';
import { loadAnalysisPackages } from '../home/(user)/_lib/server/load-analysis-packages'; import { loadAnalysisPackages } from '../home/(user)/_lib/server/load-analysis-packages';
import { redirect } from 'next/navigation';
export const generateMetadata = async () => { export const generateMetadata = async () => {
const { t } = await createI18nServerInstance(); const { t } = await createI18nServerInstance();

View File

@@ -194,12 +194,13 @@ export async function readPrivateMessageResponse({
excludedMessageIds, excludedMessageIds,
}: { }: {
excludedMessageIds: string[]; excludedMessageIds: string[];
}): Promise<{ messageId: string | null; hasAnalysisResponse: boolean; hasPartialAnalysisResponse: boolean; hasFullAnalysisResponse: boolean; medusaOrderId: string | undefined }> { }): Promise<{ messageId: string | null; hasAnalysisResponse: boolean; hasPartialAnalysisResponse: boolean; hasFullAnalysisResponse: boolean; medusaOrderId: string | undefined; analysisOrderId: number | undefined }> {
let messageId: string | null = null; let messageId: string | null = null;
let hasAnalysisResponse = false; let hasAnalysisResponse = false;
let hasPartialAnalysisResponse = false; let hasPartialAnalysisResponse = false;
let hasFullAnalysisResponse = false; let hasFullAnalysisResponse = false;
let medusaOrderId: string | undefined = undefined; let medusaOrderId: string | undefined = undefined;
let analysisOrderId: number | undefined = undefined;
try { try {
const privateMessage = await getLatestPrivateMessageListItem({ excludedMessageIds }); const privateMessage = await getLatestPrivateMessageListItem({ excludedMessageIds });
@@ -212,6 +213,7 @@ export async function readPrivateMessageResponse({
hasPartialAnalysisResponse: false, hasPartialAnalysisResponse: false,
hasFullAnalysisResponse: false, hasFullAnalysisResponse: false,
medusaOrderId: undefined, medusaOrderId: undefined,
analysisOrderId: undefined
}; };
} }
@@ -220,16 +222,15 @@ export async function readPrivateMessageResponse({
); );
const messageResponse = privateMessageContent?.Saadetis?.Vastus; const messageResponse = privateMessageContent?.Saadetis?.Vastus;
medusaOrderId = privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId || messageResponse?.ValisTellimuseId; analysisOrderId = Number(privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId || messageResponse?.ValisTellimuseId);
const hasInvalidOrderId = !medusaOrderId || !medusaOrderId.toString().startsWith('order_'); const hasInvalidOrderId = isNaN(analysisOrderId)
if (hasInvalidOrderId || !messageResponse) { if (hasInvalidOrderId || !messageResponse) {
await createMedipostActionLog({ await createMedipostActionLog({
action: 'sync_analysis_results_from_medipost', action: 'sync_analysis_results_from_medipost',
xml: privateMessageXml, xml: privateMessageXml,
hasAnalysisResults: false, hasAnalysisResults: false,
medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId,
}); });
return { return {
messageId, messageId,
@@ -237,9 +238,13 @@ export async function readPrivateMessageResponse({
hasPartialAnalysisResponse: false, hasPartialAnalysisResponse: false,
hasFullAnalysisResponse: false, hasFullAnalysisResponse: false,
medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId, medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId,
analysisOrderId: hasInvalidOrderId ? undefined : analysisOrderId
}; };
} }
const analysisOrder = await getAnalysisOrder({ analysisOrderId: analysisOrderId })
medusaOrderId = analysisOrder.medusa_order_id;
let order: Tables<{ schema: 'medreport' }, 'analysis_orders'>; let order: Tables<{ schema: 'medreport' }, 'analysis_orders'>;
try { try {
order = await getAnalysisOrder({ medusaOrderId }); order = await getAnalysisOrder({ medusaOrderId });
@@ -264,7 +269,7 @@ export async function readPrivateMessageResponse({
console.warn(`Failed to process private message id=${messageId}, message=${(e as Error).message}`); console.warn(`Failed to process private message id=${messageId}, message=${(e as Error).message}`);
} }
return { messageId, hasAnalysisResponse, hasPartialAnalysisResponse, hasFullAnalysisResponse, medusaOrderId }; return { messageId, hasAnalysisResponse, hasPartialAnalysisResponse, hasFullAnalysisResponse, medusaOrderId, analysisOrderId };
} }
async function saveAnalysisGroup( async function saveAnalysisGroup(
@@ -616,7 +621,7 @@ export async function sendOrderToMedipost({
lastName: account.last_name ?? '', lastName: account.last_name ?? '',
phone: account.phone ?? '', phone: account.phone ?? '',
}, },
orderId: medusaOrderId, orderId: medreportOrder.id,
orderCreatedAt: new Date(medreportOrder.created_at), orderCreatedAt: new Date(medreportOrder.created_at),
comment: '', comment: '',
}); });

View File

@@ -68,7 +68,7 @@ export async function composeOrderTestResponseXML({
}; };
orderedAnalysisElementsIds: number[]; orderedAnalysisElementsIds: number[];
orderedAnalysesIds: number[]; orderedAnalysesIds: number[];
orderId: string; orderId: number;
orderCreatedAt: Date; orderCreatedAt: Date;
}) { }) {
const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds }); const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds });

View File

@@ -45,7 +45,7 @@ export async function composeOrderXML({
lastName: string; lastName: string;
phone: string; phone: string;
}; };
orderId: string; orderId: number;
orderCreatedAt: Date; orderCreatedAt: Date;
comment?: string; comment?: string;
}) { }) {
@@ -76,42 +76,34 @@ export async function composeOrderXML({
// Collect all materials from all analysis groups // Collect all materials from all analysis groups
for (const currentGroup of analysisGroups) { for (const currentGroup of analysisGroups) {
let relatedAnalysisElement = analysisElements?.find( let relatedAnalysisElements = analysisElements?.filter(({ analysis_groups }) => analysis_groups.id === currentGroup.id);
(element) => element.analysis_groups.id === currentGroup.id,
);
const relatedAnalyses = analyses?.filter((analysis) => {
return analysis.analysis_elements.analysis_groups.id === currentGroup.id;
});
if (!relatedAnalysisElement) { if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) {
relatedAnalysisElement = relatedAnalyses?.find( relatedAnalysisElements = analyses
(relatedAnalysis) => .filter(({ analysis_elements }) => analysis_elements.analysis_groups.id === currentGroup.id)
relatedAnalysis.analysis_elements.analysis_groups.id === .flatMap(({ analysis_elements }) => analysis_elements);
currentGroup.id,
)?.analysis_elements;
} }
if (!relatedAnalysisElement || !relatedAnalysisElement.material_groups) { if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) {
throw new Error( throw new Error(
`Failed to find related analysis element for group ${currentGroup.name} (id: ${currentGroup.id})`, `Failed to find related analysis elements for group ${currentGroup.name} (id: ${currentGroup.id})`,
); );
} }
for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) { for (const analysisElement of relatedAnalysisElements) {
const materials = toArray(group.Materjal); for (const { Materjal } of analysisElement.material_groups as MaterjalideGrupp[]) {
for (const material of materials) { for (const material of toArray(Materjal)) {
const { MaterjaliNimi, MaterjaliTyyp, MaterjaliTyypOID, Konteiner } = material; const { MaterjaliTyyp } = material;
const containers = toArray(Konteiner);
for (const container of containers) { for (const container of toArray(material.Konteiner)) {
// Use MaterialTyyp as the key for deduplication if (uniqueMaterials.has(MaterjaliTyyp)) {
const materialKey = MaterjaliTyyp; continue;
}
if (!uniqueMaterials.has(materialKey)) { uniqueMaterials.set(MaterjaliTyyp, {
uniqueMaterials.set(materialKey, { MaterjaliTyypOID: material.MaterjaliTyypOID,
MaterjaliTyypOID, MaterjaliTyyp: material.MaterjaliTyyp,
MaterjaliTyyp, MaterjaliNimi: material.MaterjaliNimi,
MaterjaliNimi,
ProovinouKoodOID: container.ProovinouKoodOID, ProovinouKoodOID: container.ProovinouKoodOID,
ProovinouKood: container.ProovinouKood, ProovinouKood: container.ProovinouKood,
order: specimenOrder++, order: specimenOrder++,
@@ -137,47 +129,48 @@ export async function composeOrderXML({
// Generate analysis section with correct specimen references // Generate analysis section with correct specimen references
const analysisSection = []; const analysisSection = [];
for (const currentGroup of analysisGroups) { for (const currentGroup of analysisGroups) {
let relatedAnalysisElement = analysisElements?.find( let relatedAnalysisElements = analysisElements?.filter(
(element) => element.analysis_groups.id === currentGroup.id, (element) => element.analysis_groups.id === currentGroup.id,
); );
const relatedAnalyses = analyses?.filter((analysis) => {
return analysis.analysis_elements.analysis_groups.id === currentGroup.id;
});
if (!relatedAnalysisElement) { if (!relatedAnalysisElements) {
relatedAnalysisElement = relatedAnalyses?.find( relatedAnalysisElements = analyses
(relatedAnalysis) => .filter(({ analysis_elements }) => analysis_elements.analysis_groups.id === currentGroup.id)
relatedAnalysis.analysis_elements.analysis_groups.id === .flatMap(({ analysis_elements }) => analysis_elements);
currentGroup.id,
)?.analysis_elements;
} }
if (!relatedAnalysisElement || !relatedAnalysisElement.material_groups) { if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) {
throw new Error( throw new Error(
`Failed to find related analysis element for group ${currentGroup.name} (id: ${currentGroup.id})`, `Failed to find related analysis element for group ${currentGroup.name} (id: ${currentGroup.id})`,
); );
} }
// Find the specimen order number for this analysis group // Find the specimen order numbers for analysis elements
let specimenOrderNumber = 1; const uuringElementInputs: {
for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) { analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>,
const materials = toArray(group.Materjal); specimenOrderNr: number,
for (const material of materials) { }[] = [];
const materialKey = material.MaterjaliTyyp; for (const analysisElement of relatedAnalysisElements) {
const uniqueMaterial = uniqueMaterials.get(materialKey); for (const group of analysisElement.material_groups as MaterjalideGrupp[]) {
if (uniqueMaterial) { const materials = toArray(group.Materjal);
specimenOrderNumber = uniqueMaterial.order; for (const material of materials) {
break; // Use the first material's order number const uniqueMaterial = uniqueMaterials.get(material.MaterjaliTyyp);
if (!uniqueMaterial) {
continue;
}
uuringElementInputs.push({
analysisElement,
specimenOrderNr: uniqueMaterial.order,
});
break;
} }
} }
if (specimenOrderNumber > 1) break; // Found a specimen, use it
} }
const groupXml = getAnalysisGroup( const groupXml = getAnalysisGroup(
currentGroup.original_id, currentGroup.original_id,
currentGroup.name, currentGroup.name,
specimenOrderNumber, uuringElementInputs,
relatedAnalysisElement,
); );
analysisSection.push(groupXml); analysisSection.push(groupXml);
} }

View File

@@ -82,10 +82,10 @@ export async function updateAnalysisOrderStatus({
export async function getAnalysisOrder({ export async function getAnalysisOrder({
medusaOrderId, medusaOrderId,
orderId, analysisOrderId,
}: { }: {
medusaOrderId?: string; medusaOrderId?: string;
orderId?: number; analysisOrderId?: number;
}) { }) {
const query = getSupabaseServerAdminClient() const query = getSupabaseServerAdminClient()
.schema('medreport') .schema('medreport')
@@ -93,15 +93,15 @@ export async function getAnalysisOrder({
.select('*') .select('*')
if (medusaOrderId) { if (medusaOrderId) {
query.eq('medusa_order_id', medusaOrderId); query.eq('medusa_order_id', medusaOrderId);
} else if (orderId) { } else if (analysisOrderId) {
query.eq('id', orderId); query.eq('id', analysisOrderId);
} else { } else {
throw new Error('Either medusaOrderId or orderId must be provided'); throw new Error('Either medusaOrderId or orderId must be provided');
} }
const { data: order, error } = await query.single(); const { data: order, error } = await query.single();
if (error) { if (error) {
throw new Error(`Failed to get order by medusaOrderId=${medusaOrderId} or orderId=${orderId}, message=${error.message}, data=${JSON.stringify(order)}`); throw new Error(`Failed to get order by medusaOrderId=${medusaOrderId} or analysisOrderId=${analysisOrderId}, message=${error.message}, data=${JSON.stringify(order)}`);
} }
return order; return order;
} }

View File

@@ -8,8 +8,7 @@ const isProd = process.env.NODE_ENV === 'production';
export const getPais = ( export const getPais = (
sender: string, sender: string,
recipient: string, recipient: string,
createdAt: Date, orderId: number,
orderId: string,
packageName = "OL", packageName = "OL",
) => { ) => {
if (isProd) { if (isProd) {
@@ -152,14 +151,21 @@ export const getAnalysisElement = (
export const getAnalysisGroup = ( export const getAnalysisGroup = (
analysisGroupOriginalId: string, analysisGroupOriginalId: string,
analysisGroupName: string, analysisGroupName: string,
specimenOrderNr: number, uuringElementInputs: {
analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>, analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>,
) => specimenOrderNr: number,
`<UuringuGrupp> }[],
<UuringuGruppId>${analysisGroupOriginalId}</UuringuGruppId> ) => {
<UuringuGruppNimi>${analysisGroupName}</UuringuGruppNimi> const uuringElements = uuringElementInputs.map(({ analysisElement, specimenOrderNr }) =>
<Uuring> `<Uuring>
${getAnalysisElement(analysisElement.analysis_id_oid, analysisElement.analysis_id_original, analysisElement.tehik_short_loinc, analysisElement.tehik_loinc_name, analysisElement.id, analysisElement.analysis_name_lab)} ${getAnalysisElement(analysisElement.analysis_id_oid, analysisElement.analysis_id_original, analysisElement.tehik_short_loinc, analysisElement.tehik_loinc_name, analysisElement.id, analysisElement.analysis_name_lab)}
<ProoviJarjenumber>${specimenOrderNr}</ProoviJarjenumber> <ProoviJarjenumber>${specimenOrderNr}</ProoviJarjenumber>
</Uuring> </Uuring>`
).join('');
return `<UuringuGrupp>
<UuringuGruppId>${analysisGroupOriginalId}</UuringuGruppId>
<UuringuGruppNimi>${analysisGroupName}</UuringuGruppNimi>
${uuringElements}
</UuringuGrupp>`; </UuringuGrupp>`;
};

View File

@@ -54,7 +54,6 @@ export const listOrders = async (
}, },
headers, headers,
next, next,
cache: "force-cache",
}) })
.then(({ orders }) => orders) .then(({ orders }) => orders)
.catch((err) => medusaError(err)) .catch((err) => medusaError(err))

View File

@@ -73,7 +73,6 @@ export const listProducts = async ({
}, },
headers, headers,
next, next,
cache: "force-cache",
} }
) )
.then(({ products, count }) => { .then(({ products, count }) => {

View File

@@ -6,11 +6,9 @@ import Image from 'next/image';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import type { AdminProductVariant, StoreProduct } from '@medusajs/types'; import type { AdminProductVariant, StoreProduct } from '@medusajs/types';
import { Button } from '@medusajs/ui';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { handleAddToCart } from '../../../../lib/services/medusaCart.service';
import { toast } from '@kit/ui/sonner';
import { Button } from '@kit/ui/button';
import { import {
Card, Card,
CardContent, CardContent,
@@ -18,12 +16,20 @@ import {
CardFooter, CardFooter,
CardHeader, CardHeader,
} from '@kit/ui/card'; } from '@kit/ui/card';
import { toast } from '@kit/ui/sonner';
import { Spinner } from '@kit/ui/spinner';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import { ButtonTooltip } from './ui/button-tooltip';
import { PackageHeader } from './package-header';
import { pathsConfig } from '../config';
export type AnalysisPackageWithVariant = Pick<StoreProduct, 'title' | 'description' | 'subtitle' | 'metadata'> & { import { handleAddToCart } from '~/lib/services/medusaCart.service';
import { pathsConfig } from '../config';
import { PackageHeader } from './package-header';
import { ButtonTooltip } from './ui/button-tooltip';
export type AnalysisPackageWithVariant = Pick<
StoreProduct,
'title' | 'description' | 'subtitle' | 'metadata'
> & {
variantId: string; variantId: string;
nrOfAnalyses: number; nrOfAnalyses: number;
price: number; price: number;
@@ -38,7 +44,7 @@ export default function SelectAnalysisPackage({
countryCode, countryCode,
}: { }: {
analysisPackage: AnalysisPackageWithVariant; analysisPackage: AnalysisPackageWithVariant;
countryCode: string, countryCode: string;
}) { }) {
const router = useRouter(); const router = useRouter();
const { const {
@@ -48,7 +54,14 @@ export default function SelectAnalysisPackage({
const [isAddingToCart, setIsAddingToCart] = useState(false); const [isAddingToCart, setIsAddingToCart] = useState(false);
const { nrOfAnalyses, variantId, title, subtitle = '', description = '', price } = analysisPackage; const {
nrOfAnalyses,
variantId,
title,
subtitle = '',
description = '',
price,
} = analysisPackage;
const handleSelect = async () => { const handleSelect = async () => {
setIsAddingToCart(true); setIsAddingToCart(true);
@@ -58,10 +71,16 @@ export default function SelectAnalysisPackage({
countryCode, countryCode,
}); });
setIsAddingToCart(false); setIsAddingToCart(false);
toast.success(<Trans i18nKey={'order-analysis-package:analysisPackageAddedToCart'} />); toast.success(
<Trans i18nKey={'order-analysis-package:analysisPackageAddedToCart'} />,
);
router.push(pathsConfig.app.cart); router.push(pathsConfig.app.cart);
} catch (e) { } catch (e) {
toast.error(<Trans i18nKey={'order-analysis-package:analysisPackageAddToCartError'} />); toast.error(
<Trans
i18nKey={'order-analysis-package:analysisPackageAddToCartError'}
/>,
);
setIsAddingToCart(false); setIsAddingToCart(false);
console.error(e); console.error(e);
} }
@@ -87,7 +106,7 @@ export default function SelectAnalysisPackage({
<CardContent className="space-y-1 text-center"> <CardContent className="space-y-1 text-center">
<PackageHeader <PackageHeader
title={title} title={title}
tagColor='bg-cyan' tagColor="bg-cyan"
analysesNr={t('product:nrOfAnalyses', { nr: nrOfAnalyses })} analysesNr={t('product:nrOfAnalyses', { nr: nrOfAnalyses })}
language={language} language={language}
price={price} price={price}
@@ -95,8 +114,15 @@ export default function SelectAnalysisPackage({
<CardDescription>{subtitle}</CardDescription> <CardDescription>{subtitle}</CardDescription>
</CardContent> </CardContent>
<CardFooter> <CardFooter>
<Button className="w-full text-[10px] sm:text-sm" onClick={handleSelect} isLoading={isAddingToCart}> <Button
{!isAddingToCart && <Trans i18nKey='order-analysis-package:selectThisPackage' />} className="w-full text-[10px] sm:text-sm"
onClick={handleSelect}
>
{isAddingToCart ? (
<Spinner />
) : (
<Trans i18nKey="order-analysis-package:selectThisPackage" />
)}
</Button> </Button>
</CardFooter> </CardFooter>
</Card> </Card>

View File

@@ -1,7 +1,10 @@
{ {
"extends": "@kit/tsconfig/base.json", "extends": "@kit/tsconfig/base.json",
"compilerOptions": { "compilerOptions": {
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json" "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
"paths": {
"~/lib/*": ["../../lib/*"]
}
}, },
"include": ["*.ts", "src"], "include": ["*.ts", "src"],
"exclude": ["node_modules"] "exclude": ["node_modules"]

View File

@@ -46,7 +46,7 @@
"skip": "Jäta vahele", "skip": "Jäta vahele",
"signedInAs": "Sisselogitud kasutajana", "signedInAs": "Sisselogitud kasutajana",
"pageOfPages": "Leht {{page}} / {{total}}", "pageOfPages": "Leht {{page}} / {{total}}",
"noData": "Andmeid puudub", "noData": "Andmed puuduvad",
"pageNotFoundHeading": "Ups! :|", "pageNotFoundHeading": "Ups! :|",
"errorPageHeading": "Ups! :|", "errorPageHeading": "Ups! :|",
"notifications": "Teavitused", "notifications": "Teavitused",