feat(MED-100): update cart checkout flow and views

This commit is contained in:
2025-07-17 10:16:52 +03:00
parent ea3fb22f1d
commit 6426e2a79b
33 changed files with 1505 additions and 138 deletions

View File

@@ -0,0 +1,99 @@
"use client";
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import Image from 'next/image';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
} from '@kit/ui/card';
import { Trans } from '@kit/ui/trans';
import { StoreProduct, StoreProductVariant } from '@medusajs/types';
import { Button } from '@medusajs/ui';
import { handleAddToCart } from '@/lib/services/medusaCart.service';
import { PackageHeader } from './package-header';
import { ButtonTooltip } from './ui/button-tooltip';
export interface IAnalysisPackage {
titleKey: string;
price: number;
nrOfAnalyses: number | string;
tagColor: string;
descriptionKey: string;
}
export default function SelectAnalysisPackage({
analysisPackage,
countryCode,
}: {
analysisPackage: StoreProduct
countryCode: string,
}) {
const { t, i18n: { language } } = useTranslation();
const [isAddingToCart, setIsAddingToCart] = useState(false);
const handleSelect = async (selectedVariant: StoreProductVariant) => {
if (!selectedVariant?.id) return null
setIsAddingToCart(true);
await handleAddToCart({
selectedVariant,
countryCode,
});
setIsAddingToCart(false);
}
const titleKey = analysisPackage.title;
const nrOfAnalyses = analysisPackage?.metadata?.nrOfAnalyses ?? 0;
const description = analysisPackage.description ?? '';
const subtitle = analysisPackage.subtitle ?? '';
const variant = analysisPackage.variants?.[0];
if (!variant) {
return null;
}
const price = variant.calculated_price?.calculated_amount ?? 0;
return (
<Card key={titleKey}>
<CardHeader className="relative">
{description && (
<ButtonTooltip
content={description}
className="absolute top-5 right-5 z-10"
/>
)}
<Image
src="/assets/card-image.png"
alt="background"
width={326}
height={195}
className="max-h-48 w-full opacity-10"
/>
</CardHeader>
<CardContent className="space-y-1 text-center">
<PackageHeader
title={t(titleKey)}
tagColor='bg-cyan'
analysesNr={t('product:nrOfAnalyses', { nr: nrOfAnalyses })}
language={language}
price={price}
/>
<CardDescription>
{subtitle}
</CardDescription>
</CardContent>
<CardFooter>
<Button className="w-full" onClick={() => handleSelect(variant)} isLoading={isAddingToCart}>
{!isAddingToCart && <Trans i18nKey='order-analysis-package:selectThisPackage' />}
</Button>
</CardFooter>
</Card>
);
}

View File

@@ -1,104 +1,15 @@
'use client';
import Image from 'next/image';
import { useTranslation } from 'react-i18next';
import { Button } from '@kit/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
} from '@kit/ui/card';
import { Trans } from '@kit/ui/trans';
import { StoreProduct } from '@medusajs/types';
import { PackageHeader } from './package-header';
import { ButtonTooltip } from './ui/button-tooltip';
export interface IAnalysisPackage {
titleKey: string;
price: number;
nrOfAnalyses: number | string;
tagColor: string;
descriptionKey: string;
}
const analysisPackages = [
{
titleKey: 'product:standard.label',
price: 40,
nrOfAnalyses: 4,
tagColor: 'bg-cyan',
descriptionKey: 'marketing:standard.description',
},
{
titleKey: 'product:standardPlus.label',
price: 85,
nrOfAnalyses: 10,
tagColor: 'bg-warning',
descriptionKey: 'product:standardPlus.description',
},
{
titleKey: 'product:premium.label',
price: 140,
nrOfAnalyses: '12+',
tagColor: 'bg-purple',
descriptionKey: 'product:premium.description',
},
] satisfies IAnalysisPackage[];
export default function SelectAnalysisPackages() {
const {
t,
i18n: { language },
} = useTranslation();
import SelectAnalysisPackage from './select-analysis-package';
export default function SelectAnalysisPackages({ analysisPackages, countryCode }: { analysisPackages: StoreProduct[], countryCode: string }) {
return (
<div className="grid grid-cols-3 gap-6">
{analysisPackages.length > 0 ? analysisPackages.map(
(
{ titleKey, price, nrOfAnalyses, tagColor, descriptionKey },
index,
) => {
return (
<Card key={index}>
<CardHeader className="relative">
<ButtonTooltip
content="Content pending"
className="absolute top-5 right-5 z-10"
/>
<Image
src="/assets/card-image.png"
alt="background"
width={326}
height={195}
className="max-h-48 w-full opacity-10"
/>
</CardHeader>
<CardContent className="space-y-1 text-center">
<PackageHeader
title={t(titleKey)}
tagColor={tagColor}
analysesNr={t('product:nrOfAnalyses', { nr: nrOfAnalyses })}
language={language}
price={price}
/>
<CardDescription>
<Trans i18nKey={descriptionKey} />
</CardDescription>
</CardContent>
<CardFooter>
<Button className="w-full">
<Trans i18nKey='order-analysis-package:selectThisPackage' />
</Button>
</CardFooter>
</Card>
);
},
) : (
(product) => (
<SelectAnalysisPackage key={product.title} analysisPackage={product} countryCode={countryCode} />
)) : (
<h4>
<Trans i18nKey='order-analysis-package:noPackagesAvailable' />
</h4>