docs: cache revalidation in next.js storefront + storefront totals (#11887)

* initial changes

* generated sidebar
This commit is contained in:
Shahed Nasser authored and GitHub committed 2025-03-18 12:20:09 +02:00
1 parent ff3885500c
commit 2b2b65f5f7
18 files changed
+647 -83

No files matched your search

@@ -0,0 +1,248 @@
---
tags:
- order
- storefront
---
import { CodeTabs, CodeTab, Table } from "docs-ui"
export const metadata = {
title: `Order Confirmation in Storefront`,
}
# {metadata.title}
After the customer completes the checkout process and places an order, you can show an order confirmation page to display the order details.
In this guide, you'll learn how to show the different order details on the order confirmation page.
## Retrieve Order Details
To show the order details, you need to retrieve the order by sending a request to the [Get an Order API route](!api!store#orders_getordersid).
You need the order's ID to retrieve the order. You can pass it from the [complete cart step](../complete-cart/page.mdx) or store it in the `localStorage`.
The following example assumes you already have the order ID:
<CodeTabs group="store-request">
<CodeTab label="Fetch API" value="fetch">
```ts
// orderId is the order ID which you can get from the complete cart step
fetch(`http://localhost:9000/store/orders/${orderId}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
},
})
.then((res) => res.json())
.then(({ order }) => {
// use order...
console.log(order)
})
```
</CodeTab>
<CodeTab label="React" value="react">
```tsx
"use client" // include with Next.js 13+
import { HttpTypes } from "@medusajs/types"
import { useEffect } from "react"
import { useState } from "react"
export function OrderConfirmation({ id }: { id: string }) {
const [order, setOrder] = useState<HttpTypes.StoreOrder | undefined>()
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch(`http://localhost:9000/store/orders/${id}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
},
})
.then((res) => res.json())
.then(({ order: dataOrder }) => {
setOrder(dataOrder)
setLoading(false)
})
}, [id])
return (
<div>
{loading && <span>Loading...</span>}
{!loading && order && (
<div>
<h1>Order Confirmation</h1>
<p>Order ID: {order.id}</p>
<p>Order Date: {order.created_at.toLocaleString()}</p>
<p>Order Customer: {order.email}</p>
{/* TODO show more info */}
</div>
)}
</div>
)
}
```
</CodeTab>
</CodeTabs>
In the above example, you retrieve the order's details from the [Get an Order API route](!api!store#orders_getordersid). Then, in the React example, you show the order details like the order ID, order date, and customer email.
The rest of this guide will expand on the React example to show more order details.
<Note title="Tip">
Refer to the [Order schema in the API reference](!api!/store#orders_order_schema) for all the available order fields.
</Note>
---
## Show Order Items
An order has an `items` field that contains the order items. You can show the order items on the order confirmation page.
For example, add to the React component a `formatPrice` function to format prices with the order's currency:
```tsx
const formatPrice = (amount: number): string => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: order?.currency_code,
})
.format(amount)
}
```
Since this is the same function used to format the prices of products and cart totals, you can define the function in one place and re-use it where necessary. In that case, make sure to pass the currency code as a parameter.
Then, you can show the order items in a list:
```tsx
return (
<div>
{loading && <span>Loading...</span>}
{!loading && order && (
<div>
{/* ... */}
<p>
<span>Order Items</span>
<ul>
{order.items?.map((item) => (
<li key={item.id}>
{item.title} - {item.quantity} x {formatPrice(item.unit_price)}
</li>
))}
</ul>
</p>
{/* TODO show more details */}
</div>
)}
</div>
)
```
In the above example, you show the order items in a list, displaying the item's title, quantity, and unit price formatted with the `formatPrice` function.
---
## Show Order Totals
An order has various fields for the order totals, which you can check out in the [Order schema in the Store API reference](https://docs.medusajs.com/api/store#orders_order_schema). The most commonly used fields are:
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Field</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`subtotal`
</Table.Cell>
<Table.Cell>
The order's subtotal excluding taxes and shipping, and including discounts.
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`discount_total`
</Table.Cell>
<Table.Cell>
The total discounts or promotions applied to the order.
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`shipping_total`
</Table.Cell>
<Table.Cell>
The total shipping cost.
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`tax_total`
</Table.Cell>
<Table.Cell>
The total tax amount.
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`total`
</Table.Cell>
<Table.Cell>
The total amount of the order including all taxes, shipping, and discounts.
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
You can show these totals on the order confirmation page. For example:
```tsx
return (
<div>
{loading && <span>Loading...</span>}
{!loading && order && (
<div>
{/* ... */}
<div>
<span>Order Totals</span>
<ul>
<li>
<span>Subtotal (excl. shipping & taxes)</span>
<span>{formatPrice(order.subtotal ?? 0)}</span>
</li>
<li>
<span>Discounts</span>
<span>{formatPrice(order.discount_total ?? 0)}</span>
</li>
<li>
<span>Shipping</span>
<span>{formatPrice(order.shipping_total ?? 0)}</span>
</li>
<li>
<span>Taxes</span>
<span>{formatPrice(order.tax_total ?? 0)}</span>
</li>
<li>
<span>Total</span>
<span>{formatPrice(order.total ?? 0)}</span>
</li>
</ul>
</div>
</div>
)}
</div>
)
```
In the above example, you show the order totals in a list, displaying the subtotal, discounts, shipping, taxes, and total amount formatted with the [formatPrice function](#show-order-items).
@@ -1,5 +1,3 @@
import { ChildDocs } from "docs-ui"
export const metadata = {
title: `Checkout in Storefront`,
}
@@ -10,12 +8,16 @@ Once a customer finishes adding products to cart, they go through the checkout f
The checkout flow is composed of five steps:
1. **Email:** Enter customer email. For logged-in customer, you can pre-fill it.
2. **Address:** Enter shipping/billing address details.
3. **Shipping**: Choose a shipping method.
4. **Payment:** Choose a payment provider.
5. **Complete Cart:** Perform any payment action necessary (for example, enter card details), complete the cart, and place the order.
1. [Email](./email/page.mdx): Enter customer email. For logged-in customer, you can pre-fill it.
2. [Address](./address/page.mdx): Enter shipping/billing address details.
3. [Shipping](./shipping/page.mdx): Choose a shipping method.
4. [Payment](./payment/page.mdx): Choose a payment provider.
5. [Complete Cart](./complete-cart/page.mdx): Perform any payment action necessary (for example, enter card details), complete the cart, and place the order.
You can combine steps based on your desired checkout flow.
You can combine steps or change their order based on your desired checkout flow. Once the customer places the order, you can show them an [order confirmation page](./order-confirmation/page.mdx).
<ChildDocs type="item" onlyTopLevel={true} />
<Note title="Tip">
Refer to the [Express Checkout Tutorial](../guides/express-checkout/page.mdx) for a complete example of a different checkout flow.
</Note>