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,5 @@
import SkeletonCartPage from '~/medusa/modules/skeletons/templates/skeleton-cart-page';
export default function Loading() {
return <SkeletonCartPage />;
}

View File

@@ -0,0 +1,23 @@
import { PageBody, PageHeader } from '@/packages/ui/src/makerkit/page';
import { MontonioCheckoutCallback } from '../../../../_components/cart/montonio-checkout-callback';
import { createI18nServerInstance } from '@/lib/i18n/i18n.server';
import { Trans } from '@kit/ui/trans';
export async function generateMetadata() {
const { t } = await createI18nServerInstance();
return {
title: t('cart:montonioCallback.title'),
};
}
export default async function MontonioCheckoutCallbackPage() {
return (
<div className={'flex h-full flex-1 flex-col'}>
<PageHeader title={<Trans i18nKey="cart:montonioCallback.title" />} />
<PageBody>
<MontonioCheckoutCallback />
</PageBody>
</div>
);
}

View File

@@ -0,0 +1,47 @@
import { createI18nServerInstance } from '@/lib/i18n/i18n.server';
import { PageBody, PageHeader } from '@/packages/ui/src/makerkit/page';
import { notFound } from 'next/navigation';
import { retrieveCart } from '~/medusa/lib/data/cart';
import Cart from '../../_components/cart';
import { listCollections } from '@lib/data';
import CartTimer from '../../_components/cart/cart-timer';
import { Trans } from '@kit/ui/trans';
export async function generateMetadata() {
const { t } = await createI18nServerInstance();
return {
title: t('cart:title'),
};
}
export default async function CartPage() {
const cart = await retrieveCart().catch((error) => {
console.error(error);
return notFound();
});
const { collections } = await listCollections({
limit: "100",
});
const analysisPackagesCollection = collections.find(({ handle }) => handle === 'analysis-packages');
const analysisPackages = analysisPackagesCollection && cart?.items
? cart.items.filter((item) => item.product?.collection_id === analysisPackagesCollection.id)
: [];
const otherItems = cart?.items?.filter((item) => item.product?.collection_id !== analysisPackagesCollection?.id) ?? [];
const otherItemsSorted = otherItems.sort((a, b) => (a.updated_at ?? "") > (b.updated_at ?? "") ? -1 : 1);
const item = otherItemsSorted[0];
return (
<PageBody>
<PageHeader title={<Trans i18nKey="cart:title" />}>
{item && item.updated_at && <CartTimer cartItem={item} />}
</PageHeader>
<Cart cart={cart} analysisPackages={analysisPackages} otherItems={otherItems} />
</PageBody>
);
}

View File

@@ -17,6 +17,7 @@ import { HomeMenuNavigation } from '../_components/home-menu-navigation';
import { HomeMobileNavigation } from '../_components/home-mobile-navigation';
import { HomeSidebar } from '../_components/home-sidebar';
import { loadUserWorkspace } from '../_lib/server/load-user-workspace';
import { retrieveCart } from '@lib/data';
function UserHomeLayout({ children }: React.PropsWithChildren) {
const state = use(getLayoutState());
@@ -55,12 +56,13 @@ function SidebarLayout({ children }: React.PropsWithChildren) {
function HeaderLayout({ children }: React.PropsWithChildren) {
const workspace = use(loadUserWorkspace());
const cart = use(retrieveCart());
return (
<UserWorkspaceContextProvider value={workspace}>
<Page style={'header'}>
<PageNavigation>
<HomeMenuNavigation workspace={workspace} />
<HomeMenuNavigation workspace={workspace} cart={cart} />
</PageNavigation>
<PageMobileNavigation className={'flex items-center justify-between'}>

View File

@@ -8,6 +8,7 @@ import { PageBody } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans';
import ComparePackagesModal from '../../_components/compare-packages-modal';
import { loadAnalysisPackages } from '../../_lib/server/load-analysis-packages';
export const generateMetadata = async () => {
const i18n = await createI18nServerInstance();
@@ -19,6 +20,8 @@ export const generateMetadata = async () => {
};
async function OrderAnalysisPackagePage() {
const { analysisPackages, countryCode } = await loadAnalysisPackages();
return (
<PageBody>
<div className="space-y-3 text-center">
@@ -26,6 +29,7 @@ async function OrderAnalysisPackagePage() {
<Trans i18nKey={'marketing:selectPackage'} />
</h3>
<ComparePackagesModal
analysisPackages={analysisPackages}
triggerElement={
<Button variant="secondary" className="gap-2">
<Trans i18nKey={'marketing:comparePackages'} />
@@ -34,7 +38,7 @@ async function OrderAnalysisPackagePage() {
}
/>
</div>
<SelectAnalysisPackages />
<SelectAnalysisPackages analysisPackages={analysisPackages} countryCode={countryCode} />
</PageBody>
);
}

View File

@@ -0,0 +1,28 @@
import { notFound } from 'next/navigation';
import { retrieveOrder } from '~/medusa/lib/data/orders';
import { createI18nServerInstance } from '@/lib/i18n/i18n.server';
import OrderCompleted from '@/app/home/(user)/_components/order/order-completed';
type Props = {
params: Promise<{ orderId: string }>;
};
export async function generateMetadata() {
const { t } = await createI18nServerInstance();
return {
title: t('cart:orderConfirmed.title'),
};
}
export default async function OrderConfirmedPage(props: Props) {
const params = await props.params;
const order = await retrieveOrder(params.orderId).catch(() => null);
if (!order) {
return notFound();
}
return <OrderCompleted order={order} />;
}