From 3c1a1c64c0a2bf31ebc80891b4e3ed4df6d0e257 Mon Sep 17 00:00:00 2001 From: lizozom Date: Tue, 29 Aug 2023 13:18:27 +0300 Subject: [PATCH 1/8] add checkout methods and types --- lib/medusa/index.ts | 35 +++++++++++++++++++++++++++ lib/medusa/types.ts | 59 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/lib/medusa/index.ts b/lib/medusa/index.ts index ee3181ef17..0fa06bb532 100644 --- a/lib/medusa/index.ts +++ b/lib/medusa/index.ts @@ -8,6 +8,7 @@ import { NextRequest, NextResponse } from 'next/server'; import { calculateVariantAmount, computeAmount, convertToDecimal } from './helpers'; import { Cart, + CartCompletion, CartItem, Image, MedusaCart, @@ -518,3 +519,37 @@ export async function revalidate(req: NextRequest): Promise { return NextResponse.json({ status: 200, revalidated: true, now: Date.now() }); } + +/** + * Checkout flow + */ + +export async function initPaymentSessions(cartId: string): Promise { + const paymentSessions = await medusaRequest({ + method: 'POST', + path: `/store/carts/${cartId}/payment-sessions`, + }); + + return reshapeCart(paymentSessions.body.cart); +} + +export async function selectPaymentSession(cartId: string, paymentProviderId: string): Promise { + const paymentSession = await medusaRequest({ + method: 'POST', + path: `/store/carts/${cartId}/payment-sessions`, + payload: { + provider_id: paymentProviderId, + }, + }); + + return reshapeCart(paymentSession.body.cart); +} + +export async function completeCart(cartId: string): Promise { + const response = await medusaRequest({ + method: 'POST', + path: `/store/carts/${cartId}/complete`, + }); + + return response.body as CartCompletion; +} \ No newline at end of file diff --git a/lib/medusa/types.ts b/lib/medusa/types.ts index 7f1d2e6ed1..fd6359a716 100644 --- a/lib/medusa/types.ts +++ b/lib/medusa/types.ts @@ -431,3 +431,62 @@ export type ProductVariantInfo = Pick; type ConvertDateToString = { [P in keyof T]: T[P] extends Date ? Date | string : T[P]; }; + +/** Checkout flow */ + +export enum CartStatus { + pending = "pending", + completed = "completed", + archived = "archived", + canceled = "canceled", + requires_action = "requires_action" +} + +export enum FullfillmentStatus { + not_fulfilled = "not_fulfilled", + partially_fulfilled = "partially_fulfilled", + fullfilled = "fullfilled", + partially_shipped = "partially_shipped", + shipped = "shipped", + partially_returned = "partially_returned", + returned = "returned", + canceled = "canceled", + requires_action = "requires_action" +} + +export enum PaymentStatus { + not_paid = "not_paid", + awaiting = "awaiting", + captured = "captured", + partially_refunded = "partially_refunded", + refunded = "refunded", + canceled = "canceled", + requires_action = "requires_action" +} + +export type CartCompletion = { + type: "order" | "cart" | "swap", + data: { + id: string, + status: CartStatus, + fulfillment_status: FullfillmentStatus, + payment_status: PaymentStatus, + display_id: number, + cart_id: string, + customer_id: string, + email: string, + billing_address_id: string, + shipping_address_id: string, + region_id: string, + currency_code: string, + tax_rate: number, + draft_order_id?: string | null, + canceled_at: string, + no_notification: boolean, + idempotency_key: string, + external_id: string | null, + created_at: string, + updated_at: string, + metadata?: Record | null, + } +} \ No newline at end of file From 42a8d09f79e32b6d698a6f2a49d8b5bba2854c84 Mon Sep 17 00:00:00 2001 From: lizozom Date: Tue, 29 Aug 2023 17:00:13 +0300 Subject: [PATCH 2/8] setup images tile design (50%) Header \ footer --- components/carousel.tsx | 1 - components/grid/three-items.tsx | 2 +- components/grid/tile.tsx | 11 ++++++++- components/layout/footer.tsx | 29 ++---------------------- components/layout/product-grid-items.tsx | 1 - components/logo-square.tsx | 10 ++++---- next.config.js | 4 ++++ 7 files changed, 22 insertions(+), 36 deletions(-) diff --git a/components/carousel.tsx b/components/carousel.tsx index 5c6b7c1a24..7a498334f5 100644 --- a/components/carousel.tsx +++ b/components/carousel.tsx @@ -28,7 +28,6 @@ export async function Carousel() { currencyCode: product.priceRange.maxVariantPrice.currencyCode }} src={product.featuredImage?.url} - fill sizes="(min-width: 1024px) 25vw, (min-width: 768px) 33vw, 50vw" /> diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index f9f7294221..5d9092f986 100644 --- a/components/grid/three-items.tsx +++ b/components/grid/three-items.tsx @@ -19,7 +19,7 @@ function ThreeItemGridItem({ ) : null} diff --git a/components/layout/footer.tsx b/components/layout/footer.tsx index 0f8f44bce0..f4cb8194d2 100644 --- a/components/layout/footer.tsx +++ b/components/layout/footer.tsx @@ -1,6 +1,5 @@ import Link from 'next/link'; -import MedusaIcon from 'components/icons/medusa'; import FooterMenu from 'components/layout/footer-menu'; import LogoSquare from 'components/logo-square'; import { getMenu } from 'lib/medusa'; @@ -17,10 +16,10 @@ export default async function Footer() { return (
-
+
- + {SITE_NAME}
@@ -38,17 +37,6 @@ export default async function Footer() { > -
@@ -57,19 +45,6 @@ export default async function Footer() { {copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved.


-

Designed in California

-

- Crafted by{' '} - - - -

diff --git a/components/layout/product-grid-items.tsx b/components/layout/product-grid-items.tsx index 38b11e9fed..6465235545 100644 --- a/components/layout/product-grid-items.tsx +++ b/components/layout/product-grid-items.tsx @@ -17,7 +17,6 @@ export default function ProductGridItems({ products }: { products: Product[] }) currencyCode: product.priceRange.maxVariantPrice.currencyCode }} src={product.featuredImage?.url} - fill sizes="(min-width: 768px) 33vw, (min-width: 640px) 50vw, 100vw" /> diff --git a/components/logo-square.tsx b/components/logo-square.tsx index eccf5cba76..79040bf054 100644 --- a/components/logo-square.tsx +++ b/components/logo-square.tsx @@ -1,23 +1,23 @@ import clsx from 'clsx'; -import LogoIcon from './icons/logo'; export default function LogoSquare({ size }: { size?: 'sm' | undefined }) { return (
- + /> */}
); } diff --git a/next.config.js b/next.config.js index 05b07e1e27..790d116bdb 100644 --- a/next.config.js +++ b/next.config.js @@ -19,6 +19,10 @@ module.exports = { protocol: 'https', hostname: 'medusa-server-testing.s3.amazonaws.com', pathname: '/**' + }, + { + protocol: 'http', + hostname: 'localhost', } ] } From d03e05af04a076a51944bbd17a454409d821ad3a Mon Sep 17 00:00:00 2001 From: lizozom Date: Tue, 29 Aug 2023 17:56:39 +0300 Subject: [PATCH 3/8] Checkout page setup --- .gitignore | 1 + app/[page]/page.tsx | 36 +++++++++++++++++------------------- app/checkout/page.tsx | 18 ++++++++++++++++++ lib/constants.ts | 9 --------- 4 files changed, 36 insertions(+), 28 deletions(-) create mode 100644 app/checkout/page.tsx diff --git a/.gitignore b/.gitignore index 0298027e4f..0a9db1c8a4 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts +.vscode diff --git a/app/[page]/page.tsx b/app/[page]/page.tsx index 638958ace3..f5a61cadc5 100644 --- a/app/[page]/page.tsx +++ b/app/[page]/page.tsx @@ -1,52 +1,50 @@ import type { Metadata } from 'next'; +import { PageProps } from '.next/types/app/page'; import Prose from 'components/prose'; -import { CHECKOUT_PAGE_PROPS } from 'lib/constants'; import { notFound } from 'next/navigation'; export const runtime = 'edge'; export const revalidate = 43200; // 12 hours -export async function generateMetadata({ - params -}: { - params: { page: string }; -}): Promise { - let page; - - params.page === 'checkout' && (page = CHECKOUT_PAGE_PROPS); +export async function generateMetadata(page: PageProps): Promise { + const params = page.params; if (!page) return notFound(); return { - title: page.title, + title: params.title, description: '', openGraph: { - publishedTime: page.createdAt, - modifiedTime: page.updatedAt, + publishedTime: params.createdAt || new Date(), + modifiedTime: params.updatedAt || new Date(), type: 'article' } }; } -export default async function Page({ params }: { params: { page: string } }) { - let page; - - params.page === 'checkout' && (page = CHECKOUT_PAGE_PROPS); +export default async function Page(page: PageProps) { + // params.page === 'checkout' && (page = CHECKOUT_PAGE_PROPS); + console.log(page) + const params = { + body: '', + updatedAt: new Date().toISOString(), + ...page.params + }; if (!page) return notFound(); return ( <> -

{page.title}

- +

{params.title}

+

{`This document was last updated on ${new Intl.DateTimeFormat(undefined, { year: 'numeric', month: 'long', day: 'numeric' - }).format(new Date(page.updatedAt))}.`} + }).format(new Date(params.updatedAt))}.`}

); diff --git a/app/checkout/page.tsx b/app/checkout/page.tsx new file mode 100644 index 0000000000..c09fc1fb32 --- /dev/null +++ b/app/checkout/page.tsx @@ -0,0 +1,18 @@ +import { Suspense } from 'react'; + +import Footer from 'components/layout/footer'; + +export default async function ProductPage({ params }: { params: { handle: string } }) { + + return ( + <> +
+ CHECK IT OUT + +
+ +