docs: update storefront development guides to use JS SDK [1] (#11991)
* docs: update storefront development guides to use JS SDK [1] * build and lint fixes * fix links * fix links
This commit is contained in:
+11886
-12635
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,12 @@ Learn more about Medusa's architecture in [this documentation](!docs!/learn/intr
|
||||
|
||||
You can build your storefront from scratch, or build it on top of the [Next.js Starter storefront](../nextjs-starter/page.mdx). This section of the documentation provides guides to help you build a storefront from scratch for your Medusa application.
|
||||
|
||||
## Using the JS SDK
|
||||
|
||||
All guides under this documentation section use the JS SDK to interact with the Medusa application's Store API Routes. The JS SDK is a NPM package that facilitates interacting with the backend's REST APIs. You can use it in any JavaScript framework, such as Next.js, React, Vue, or Angular.
|
||||
|
||||
To install and set up the JS SDK, refer to the [JS SDK documentation](../js-sdk/page.mdx).
|
||||
|
||||
<ChildDocs showItems={["General"]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -7,45 +7,28 @@ tags:
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `List Products in Storefront`,
|
||||
title: `Show Products in Storefront`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, learn how to list, paginate, and filter products in the storefront.
|
||||
In this guide, you'll learn how to list, paginate, and filter products in your storefront.
|
||||
|
||||
## List Products
|
||||
|
||||
To list products, send a request to the [List Products API route](!api!/store#products_getproducts):
|
||||
To retrieve a list products, send a request to the [List Products API route](!api!/store#products_getproducts):
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="Fetch API" value="fetch">
|
||||
|
||||
export const fetchHighlights = [
|
||||
["4", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
]
|
||||
|
||||
```ts highlights={fetchHighlights}
|
||||
fetch(`http://localhost:9000/store/products`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
// use products...
|
||||
console.log(data.products)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["17"], ["18"], ["19"],
|
||||
["20", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["21"], ["22"], ["23"], ["24"], ["25"], ["26"], ["27"]
|
||||
["17"], ["18"], ["19"], ["20"], ["21"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -65,15 +48,9 @@ export const highlights = [
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`http://localhost:9000/store/products`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setProducts(data.products)
|
||||
sdk.store.product.list()
|
||||
.then(({ products: dataProducts }) => {
|
||||
setProducts(dataProducts)
|
||||
setLoading(false)
|
||||
})
|
||||
}, [loading])
|
||||
@@ -94,6 +71,17 @@ export const highlights = [
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="JS SDK" value="js-sdk">
|
||||
|
||||
```ts
|
||||
sdk.store.product.list()
|
||||
.then(({ products: dataProducts }) => {
|
||||
setProducts(dataProducts)
|
||||
setLoading(false)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
@@ -125,6 +113,7 @@ export const paginateHighlights = [
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "../../lib/sdk"
|
||||
|
||||
export default function Products() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -142,18 +131,10 @@ export default function Products() {
|
||||
|
||||
const offset = (currentPage - 1) * limit
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
limit: `${limit}`,
|
||||
offset: `${offset}`,
|
||||
sdk.store.product.list({
|
||||
limit,
|
||||
offset,
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ products: dataProducts, count }) => {
|
||||
setProducts((prev) => {
|
||||
if (prev.length > offset) {
|
||||
@@ -197,30 +178,48 @@ export default function Products() {
|
||||
}
|
||||
```
|
||||
|
||||
In the example above, you add a `useEffect` hook that runs whenever the `loading` state changes. This hook fetches the products, passing the `limit` and `offset` parameters to retrieve the paginated products.
|
||||
|
||||
You then show a button to load more products if there are more pages.
|
||||
|
||||
---
|
||||
|
||||
## Filter Products
|
||||
|
||||
The List Products API route accepts query parameters to filter products by title, category, whether they're a gift card, and more.
|
||||
The List Products API route accepts query parameters to filter products by title, category, handle, and more.
|
||||
|
||||
Refer to the [API reference](!api!/store#products_getproducts) for the list of accepted query parameters.
|
||||
Refer to the [API reference](!api!/store#products_getproducts) for the full list of accepted query parameters.
|
||||
|
||||
For example, to run a query on the products:
|
||||
For example, to filter products by a keyword:
|
||||
|
||||
```ts
|
||||
const searchParams = new URLSearchParams({
|
||||
// other params...
|
||||
sdk.store.product.list({
|
||||
q: "Shirt",
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ products: dataProducts, count }) => {
|
||||
// TODO set products...
|
||||
})
|
||||
```
|
||||
|
||||
The `q` parameter is used to filter a product's searchable fields, such as its title or description, by a keyword.
|
||||
|
||||
The result will be products that match the keyword in their title or description.
|
||||
|
||||
---
|
||||
|
||||
## Sort Products
|
||||
|
||||
To sort products by a field, use the `order` query parameter. Its value is a comma-separated list of fields to sort by, and each field is optionally prefixed by `-` to indicate descending order.
|
||||
|
||||
For example, to sort products by title in descending order:
|
||||
|
||||
```ts
|
||||
sdk.store.product.list({
|
||||
order: "-title",
|
||||
})
|
||||
.then(({ products: dataProducts, count }) => {
|
||||
// TODO set products...
|
||||
})
|
||||
```
|
||||
|
||||
The result will be products sorted by title in descending order.
|
||||
|
||||
+46
-20
@@ -13,27 +13,41 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how to display a product variant's sale price, with a full React example.
|
||||
In this guide, you'll learn how to display a product variant's sale price, with a full React example.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Refer to the [Show Product Variant's Price](../show-price/page.mdx) guide to learn how to display a product variant's regular price.
|
||||
|
||||
</Note>
|
||||
|
||||
## Check if a Price is a Sale
|
||||
|
||||
A product variant's price can be a sale price or a regular price. The sale price is set by the merchant in a price list.
|
||||
|
||||
To check if a product variant's price is a sale price, check whether the variant's `calculated_price.calculated_price.price_list_type` field is equal to `sale`:
|
||||
|
||||
```ts
|
||||
const isSale = selectedVariantPrice.calculated_price.calculated_price.price_list_type === "sale"
|
||||
```
|
||||
|
||||
Where `selectedVariantPrice` is either the variant the customer selected or the cheapest variant.
|
||||
Where `selectedVariantPrice` is either the variant the customer selected or the cheapest variant. Learn more about how to set the selected variant for pricing in the [Show Product Variant's Price](../show-price/page.mdx) guide.
|
||||
|
||||
<Note title="Good to know">
|
||||
|
||||
The sale price may be available for all customers, or only for some customers. If you send requests as an authenticated customer, the price list is automatically applied based on the customer's group.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Display Original and Discount Amounts
|
||||
|
||||
If the price is a sale price, the original price is in the variant's `calculated_price.original_amount` field:
|
||||
If the price is a sale price, the original price is available in the variant's `calculated_price.original_amount` field:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Find the implementation of the `formatPrice` function in [this guide](../show-price/page.mdx#price-formatting).
|
||||
Find the implementation of the `formatPrice` function in the [Show Product Variant's Price](../show-price/page.mdx#price-formatting) guide.
|
||||
|
||||
</Note>
|
||||
|
||||
@@ -46,26 +60,39 @@ const discountedAmount = formatPrice(
|
||||
)
|
||||
```
|
||||
|
||||
You define three variables:
|
||||
|
||||
- `salePrice`: The sale price of the variant.
|
||||
- `originalPrice`: The original price of the variant.
|
||||
- `discountedAmount`: The difference between the original and sale prices.
|
||||
|
||||
You can use the original price either to display it or calculate and display the discounted amount.
|
||||
|
||||
---
|
||||
|
||||
## Full React Example
|
||||
|
||||
For example, in a React-based storefront:
|
||||
For example, to display the sale price and the original price in a React-based storefront:
|
||||
|
||||
<Note>
|
||||
<Note title="Tip">
|
||||
|
||||
The example only passes the `region_id` query parameter for pricing. Learn how to store and retrieve the customer's region in the [Regions guides](../../../../regions/context/page.mdx).
|
||||
- This example uses the `useRegion` hook defined in the [Region React Context guide](../../../../regions/context/page.mdx) to retrieve the selected region's currency code.
|
||||
- Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
export const saleHighlights = [
|
||||
["5", "useRegion", "The `useRegion` hook is implemented in the Region React Context guide."],
|
||||
["17", "region", "Access the region using the `useRegion` hook."],
|
||||
["86", "isSale", "Determine whether the price is a sale price based on the value of the variant's `calculated_price.calculated_price.price_list_type` field."],
|
||||
["95", "originalPrice", "Retrieve the original price from the variant's `calculated_price.original_amount` field if the price is a sale price."],
|
||||
["141", "", "If the price is a sale price, show that to the customer along with the original price."]
|
||||
["18", "region", "Access the region using the `useRegion` hook."],
|
||||
["25", "retrieve", "Retrieve the product with the pricing query parameters."],
|
||||
["35", "selectedVariant", "Find the selected variant."],
|
||||
["49", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["57", "selectedVariantPrice", "Set the variant to compute and show its price, which is either the selected or cheapest variant."],
|
||||
["62", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["70", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["79", "isSale", "Determine whether the price is a sale price based on the value of the variant's `calculated_price.calculated_price.price_list_type` field."],
|
||||
["88", "originalPrice", "Retrieve the original price from the variant's `calculated_price.original_amount` field if the price is a sale price."],
|
||||
["134", "", "If the price is a sale price, show that to the customer along with the original price."]
|
||||
]
|
||||
|
||||
```tsx highlights={saleHighlights}
|
||||
@@ -74,6 +101,7 @@ export const saleHighlights = [
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useRegion } from "../providers/region"
|
||||
import { sdk } from "../../lib/sdk"
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
@@ -92,18 +120,10 @@ export default function Product({ id }: Props) {
|
||||
return
|
||||
}
|
||||
|
||||
const queryParams = new URLSearchParams({
|
||||
sdk.store.product.retrieve(id, {
|
||||
fields: `*variants.calculated_price`,
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ product: dataProduct }) => {
|
||||
setProduct(dataProduct)
|
||||
setLoading(false)
|
||||
@@ -224,6 +244,12 @@ export default function Product({ id }: Props) {
|
||||
|
||||
In this example, you:
|
||||
|
||||
- Use the `useRegion` hook defined in the previous [Region React Context guide](../../../../regions/context/page.mdx) to retrieve the selected region's currency code. This is necessary to format the variant's price.
|
||||
- Pass the pricing query parameters to the request retrieving the product. This retrieves for every variant a new `calculated_price` field holding details about the variant's price.
|
||||
- You can pass other pricing query parameters for more accurate pricing. Refer to the [Retrieve Product Variant's Prices](../../page.mdx#pricing-query-parameters) guide for more information.
|
||||
- Choose the variant to show its price:
|
||||
- If there's a selected variant, choose it.
|
||||
- If there isn't a selected variant, retrieve and choose the variant with the cheapest price.
|
||||
- Define an `isSale` memo variable that determines whether the chosen variant's price is a sale price. You do that by checking if the value of the variant's `calculated_price.calculated_price.price_list_type` field is `sale`.
|
||||
- Define an `originalPrice` memo variable that, if `isSale` is enabled, has the formatted original price of the chosen variant. The variant's original price is in the `calculated_price.original_amount` field.
|
||||
- If `isSale` is enabled, show a message to the customer indicating that this product is on sale along with the original price.
|
||||
|
||||
+44
-26
@@ -13,11 +13,26 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how to display a product variant's price with a full React example.
|
||||
In this guide, you'll learn how to display a product variant's price with a full React example.
|
||||
|
||||
<Note title="Tip" forceMultiline>
|
||||
|
||||
This guide doesn't take into account sale or tax prices. Refer to the following guides to learn how to show them:
|
||||
|
||||
- [Show Product Variant's Sale Price](../sale-price/page.mdx)
|
||||
- [Show Product Variant's Tax Price](../tax-price/page.mdx)
|
||||
|
||||
</Note>
|
||||
|
||||
## Price Formatting
|
||||
|
||||
To format the price, use JavaScript's [NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) utility. You pass it the amount and the currency code (which you retrieve from the selected region):
|
||||
To format a price, use JavaScript's [NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) utility. You pass it the amount and the currency code (which you retrieve from the selected region):
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Refer to the [Store Selected Region](../../../../regions/store-retrieve-region/page.mdx) guide to learn how to store and retrieve the selected region's currency code.
|
||||
|
||||
</Note>
|
||||
|
||||
```ts
|
||||
const formatPrice = (amount: number): string => {
|
||||
@@ -29,11 +44,13 @@ const formatPrice = (amount: number): string => {
|
||||
}
|
||||
```
|
||||
|
||||
You'll use this function to format prices in your storefront, including the selected variant's price.
|
||||
|
||||
---
|
||||
|
||||
## Display Selected Variant Price
|
||||
|
||||
Once the customer selects a variant, use its `calculated_price.calculated_amount` property to display its price:
|
||||
Once the customer selects a variant (as explained in the [Select Product Variants](../../../../products/variants/page.mdx) guide), use its `calculated_price.calculated_amount` property to display its price:
|
||||
|
||||
```ts
|
||||
const price = formatPrice(
|
||||
@@ -41,7 +58,13 @@ const price = formatPrice(
|
||||
)
|
||||
```
|
||||
|
||||
You'll learn about the `formatPrice` function in the next section.
|
||||
The `price` variable holds the formatted price of the selected variant with the currency of the selected region.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn about the `calculated_price` field in the [Retrieve Product Variant's Prices](../../page.mdx#product-variant-s-price-properties) section.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
@@ -49,24 +72,25 @@ You'll learn about the `formatPrice` function in the next section.
|
||||
|
||||
The following React-based storefront example retrieves the product's price based on the selected variant:
|
||||
|
||||
<Note>
|
||||
<Note title="Tip">
|
||||
|
||||
The example only passes the `region_id` query parameter for pricing. Learn how to store and retrieve the customer's region in the [Regions guides](../../../../regions/context/page.mdx).
|
||||
- This example uses the `useRegion` hook defined in the [Region React Context guide](../../../../regions/context/page.mdx) to retrieve the selected region's currency code.
|
||||
- Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
export const priceHighlights = [
|
||||
["5", "useRegion", "The `useRegion` hook is implemented in the Region React Context guide."],
|
||||
["17", "region", "Access the region using the `useRegion` hook."],
|
||||
["24", "queryParams", "Build the pricing query parameters."],
|
||||
["56", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["57", `"en-US"`, "If you use a different locale change it here."],
|
||||
["64", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["66", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["69", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["77", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["121", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["122", "price", "Display the computed price."]
|
||||
["18", "region", "Access the region using the `useRegion` hook."],
|
||||
["25", "retrieve", "Retrieve the product with the pricing query parameters."],
|
||||
["35", "selectedVariant", "Find the selected variant."],
|
||||
["49", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["50", `"en-US"`, "If you use a different locale change it here."],
|
||||
["57", "selectedVariantPrice", "Set the variant to compute and show its price, which is either the selected or cheapest variant."],
|
||||
["62", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["70", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["114", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["115", "price", "Display the computed price."]
|
||||
]
|
||||
|
||||
```tsx highlights={priceHighlights}
|
||||
@@ -75,6 +99,7 @@ export const priceHighlights = [
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useRegion } from "../providers/region"
|
||||
import { sdk } from "../../lib/sdk"
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
@@ -93,18 +118,10 @@ export default function Product({ id }: Props) {
|
||||
return
|
||||
}
|
||||
|
||||
const queryParams = new URLSearchParams({
|
||||
sdk.store.product.retrieve(id, {
|
||||
fields: `*variants.calculated_price`,
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ product: dataProduct }) => {
|
||||
setProduct(dataProduct)
|
||||
setLoading(false)
|
||||
@@ -206,8 +223,9 @@ export default function Product({ id }: Props) {
|
||||
|
||||
In the example above, you:
|
||||
|
||||
- Use the `useRegion` hook defined in the previous [Region React Context guide](../../../../regions/context/page.mdx).
|
||||
- Use the `useRegion` hook defined in the previous [Region React Context guide](../../../../regions/context/page.mdx) to retrieve the selected region's currency code. This is necessary to format the variant's price.
|
||||
- Pass the pricing query parameters to the request retrieving the product. This retrieves for every variant a new `calculated_price` field holding details about the variant's price.
|
||||
- You can pass other pricing query parameters for more accurate pricing. Refer to the [Retrieve Product Variant's Prices](../../page.mdx#pricing-query-parameters) guide for more information.
|
||||
- Choose the variant to show its price:
|
||||
- If there's a selected variant, choose it.
|
||||
- If there isn't a selected variant, retrieve and choose the variant with the cheapest price.
|
||||
|
||||
+51
-45
@@ -14,12 +14,24 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how to show a product variant's price with taxes, with a full React example.
|
||||
In this guide, you'll learn how to show a product variant's price with taxes, with a full React example.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Refer to the [Show Product Variant's Price](../show-price/page.mdx) guide to learn about the general approach to display a product variant's price.
|
||||
|
||||
</Note>
|
||||
|
||||
## Retrieve Variant's Price with Tax
|
||||
|
||||
To retrieve a product variant's price with taxes, you must pass the `region_id` and `country_code` query parameters:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
export const fetchHighlights = [
|
||||
["3", "region_id", "Pass the region ID as a query parameter."],
|
||||
["4", "country_code", "Pass the ISO 2 country code as a parameter."],
|
||||
@@ -27,19 +39,11 @@ export const fetchHighlights = [
|
||||
]
|
||||
|
||||
```ts highlights={fetchHighlights}
|
||||
const queryParams = new URLSearchParams({
|
||||
sdk.store.product.retrieve(id, {
|
||||
fields: `*variants.calculated_price`,
|
||||
region_id: region.id,
|
||||
country_code: region.countries[0].iso_2,
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ product }) => {
|
||||
// TODO use product
|
||||
console.log(product)
|
||||
@@ -50,7 +54,7 @@ You pass the selected region's ID and the code of its first country as query par
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
You can instead allow the customer to choose their country.
|
||||
You can also allow the customer to choose their country by showing them the countries in `region.countries` in a select input, and storing the selected country's code in the local storage.
|
||||
|
||||
</Note>
|
||||
|
||||
@@ -62,7 +66,7 @@ After passing the `region_id` and `country_code` as query parameters when retrie
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Find the implementation of the `formatPrice` function in [this guide](../show-price/page.mdx#price-formatting).
|
||||
Find the implementation of the `formatPrice` function in the [Show Product Variant's Price](../show-price/page.mdx#price-formatting) guide.
|
||||
|
||||
</Note>
|
||||
|
||||
@@ -70,44 +74,49 @@ Find the implementation of the `formatPrice` function in [this guide](../show-pr
|
||||
const price = formatPrice(selectedVariantPrice.calculated_price.calculated_amount_with_tax)
|
||||
```
|
||||
|
||||
Where `selectedVariantPrice` is either the variant the customer selected or the cheapest variant.
|
||||
Where `selectedVariantPrice` is either the variant the customer selected or the cheapest variant. Learn more about how to set the selected variant for pricing in the [Show Product Variant's Price](../show-price/page.mdx) guide.
|
||||
|
||||
---
|
||||
|
||||
## Tax Price Properties
|
||||
## Tax-Related Properties in Calculated Price
|
||||
|
||||
Aside from the `calculated_amount_with_tax` property, a variant's `calculated_price` object has the following properties related to taxes:
|
||||
|
||||
1. `calculated_amount_without_tax`: The calculated amount without taxes.
|
||||
2. `is_calculated_price_tax_inclusive`: Whether the `calculated_amount` property includes taxes. If enabled, you can display it instead of `calculated_amount_with_tax`.
|
||||
1. `calculated_amount_without_tax`: The calculated amount without taxes. This may be useful if you want to show the customer the price without taxes, and show the applied taxes separately. In that case, you can subtract `calculated_amount_without_tax` from `calculated_amount_with_tax` to get the tax amount.
|
||||
2. `is_calculated_price_tax_inclusive`: Whether the `calculated_amount` property includes taxes. If enabled, you can display the `calculated_amount` property instead of `calculated_amount_with_tax`.
|
||||
|
||||
Learn more about the `calculated_price` object in the [Retrieve Product Variant's Prices](../../page.mdx#product-variant-s-price-properties) guide.
|
||||
|
||||
---
|
||||
|
||||
## Full React Example
|
||||
|
||||
For example, in a React-based storefront:
|
||||
For example, to display the price with taxes in a React-based storefront:
|
||||
|
||||
<Note>
|
||||
<Note title="Tip">
|
||||
|
||||
The example passes the `region_id` query parameter for pricing. Learn how to store and retrieve the customer's region in the [Regions guides](../../../../regions/context/page.mdx).
|
||||
- This example uses the `useRegion` hook defined in the [Region React Context guide](../../../../regions/context/page.mdx) to retrieve the selected region's currency code.
|
||||
- Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
export const taxHighlight = [
|
||||
["5", "useRegion", "The `useRegion` hook is implemented in the Region React Context guide."],
|
||||
["17", "region", "Access the region using the `useRegion` hook."],
|
||||
["26", "region_id", "Pass the region ID as a query parameter."],
|
||||
["27", "country_code", "Pass the ISO 2 country code as a parameter."],
|
||||
["27", "region.countries[0].iso_2", "You can instead allow the customer to select a specific country."],
|
||||
["57", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["58", `"en-US"`, "If you use a different locale change it here."],
|
||||
["65", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["67", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["70", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["78", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["85", "calculated_amount_with_tax", "Use the variant price's `calculated_amount_with_tax` property to display the price."],
|
||||
["124", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["125", "price", "Display the computed price."]
|
||||
["18", "region", "Access the region using the `useRegion` hook."],
|
||||
["25", "retrieve", "Retrieve the product with the pricing query parameters."],
|
||||
["27", "region_id", "Pass the region ID as a query parameter."],
|
||||
["28", "country_code", "Pass the ISO 2 country code as a parameter."],
|
||||
["28", "region.countries[0].iso_2", "You can instead allow the customer to select a specific country."],
|
||||
["36", "selectedVariant", "Find the selected variant."],
|
||||
["50", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["51", `"en-US"`, "If you use a different locale change it here."],
|
||||
["58", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["60", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["63", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["71", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["78", "calculated_amount_with_tax", "Use the variant price's `calculated_amount_with_tax` property to display the price."],
|
||||
["117", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["118", "price", "Display the computed price."]
|
||||
]
|
||||
|
||||
```tsx highlights={taxHighlight}
|
||||
@@ -116,6 +125,7 @@ export const taxHighlight = [
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useRegion } from "../providers/region"
|
||||
import { sdk } from "../../lib/sdk"
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
@@ -134,19 +144,11 @@ export default function Product({ id }: Props) {
|
||||
return
|
||||
}
|
||||
|
||||
const queryParams = new URLSearchParams({
|
||||
sdk.store.product.retrieve(id, {
|
||||
fields: `*variants.calculated_price`,
|
||||
region_id: region.id,
|
||||
country_code: region.countries[0].iso_2,
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ product: dataProduct }) => {
|
||||
setProduct(dataProduct)
|
||||
setLoading(false)
|
||||
@@ -195,7 +197,7 @@ export default function Product({ id }: Props) {
|
||||
|
||||
// @ts-ignore
|
||||
return formatPrice(
|
||||
selectedVariantPrice.calculated_price.calculated_amount_with_tax
|
||||
selectedVariantPrice.calculated_price?.calculated_amount_with_tax || 0
|
||||
)
|
||||
}, [selectedVariantPrice])
|
||||
|
||||
@@ -250,6 +252,10 @@ export default function Product({ id }: Props) {
|
||||
|
||||
In this example, you:
|
||||
|
||||
- Pass the selected region's ID and the code of its first country as query parameters to the [Get Product API route](!api!/store#products_getproductsid).
|
||||
- You can instead allow the customer to choose their country.
|
||||
- Display the selected variant's price by formatting its price's `calculated_amount_with_tax` property.
|
||||
- Use the `useRegion` hook defined in the previous [Region React Context guide](../../../../regions/context/page.mdx) to retrieve the selected region's currency code. This is necessary to format the variant's price.
|
||||
- Pass the pricing query parameters, including the selected region's ID and the code of its first country, to the request retrieving the product. This retrieves for every variant a new `calculated_price` field holding details about the variant's price and taxes.
|
||||
- You can pass other pricing query parameters for more accurate pricing. Refer to the [Retrieve Product Variant's Prices](../../page.mdx#pricing-query-parameters) guide for more information.
|
||||
- Choose the variant to show its price:
|
||||
- If there's a selected variant, choose it.
|
||||
- If there isn't a selected variant, retrieve and choose the variant with the cheapest price.
|
||||
- Display the selected variant's price with taxes by formatting its price's `calculated_amount_with_tax` property.
|
||||
|
||||
@@ -13,35 +13,77 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how to show a product's variants' prices in the storefront, including handling sale prices.
|
||||
In this guide, you'll learn how to retrieve product variants' prices in the storefront, including sale prices.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
For code examples on how to show product variants' prices in your storefront, refer to the [Full Code Examples](#full-code-examples) section.
|
||||
|
||||
</Note>
|
||||
|
||||
## Pricing Query Parameters
|
||||
|
||||
When you retrieve products either with the [List Products](!api!/store#products_getproducts) or [Retrieve Products](!api!/store#products_getproductsid) API routes, you must include in the beginning of the `fields` query parameter the value `*variants.calculated_price`.
|
||||
When you retrieve products either with the [List Products](!api!/store#products_getproducts) or [Retrieve Products](!api!/store#products_getproductsid) API routes, you must include in the beginning of the `fields` query parameter the value `*variants.calculated_price` to retrieve the product variants' prices.
|
||||
|
||||
You also must pass at least one of the following query parameters to retrieve the correct product variant price:
|
||||
You also must pass at least one of the following query parameters to retrieve an accurate product variant price:
|
||||
|
||||
- `region_id`: The ID of the customer's region. This parameter must be included if you want to apply taxes on the product variant's price.
|
||||
- `country_code`: The customer's country code. This parameter must be included if you want to apply taxes on the product variant's price.
|
||||
- `province`: The province, which can be taken from a customer's address. This parameter helps further narrowing down the taxes applied on a the product variant's prices.
|
||||
- `cart_id`: The ID of the customer's cart, if available. If set, the cart's region and shipping address's country code and province are used instead of the `region_id`, `country_code`, and `province` parameters.
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>Parameter</Table.HeaderCell>
|
||||
<Table.HeaderCell>Description</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
`region_id`
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
The ID of the customer's region. This parameter must be included if you want to apply taxes on the product variant's price.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
`country_code`
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
The customer's country code. This parameter must be included if you want to apply taxes on the product variant's price.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
`province`
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
The province, which can be taken from a customer's address. This parameter helps further narrowing down the taxes applied on a the product variant's prices.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
`cart_id`
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
The ID of the customer's cart, if available. If set, the cart's region and shipping address's country code and province are used instead of the `region_id`, `country_code`, and `province` parameters.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
|
||||
For example:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
```ts
|
||||
const queryParams = new URLSearchParams({
|
||||
sdk.store.product.retrieve(id, {
|
||||
fields: `*variants.calculated_price`,
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ product }) => {
|
||||
.then(({ product: dataProduct }) => {
|
||||
// TODO use product
|
||||
console.log(product)
|
||||
})
|
||||
@@ -51,9 +93,9 @@ In this example, you pass the selected region's ID as a query parameter with the
|
||||
|
||||
### Prices for Authenticated Customer
|
||||
|
||||
If you pass the customer's authentication token / session in the request, the customer and their group, if available, are used to retrieve more accurate prices.
|
||||
If you pass the customer's authentication token / session in the request, the customer and their group, if available, are automatically used to retrieve prices specific to the customer.
|
||||
|
||||
For example, if a promotion applies to the customer's group, the promotion's prices are used.
|
||||
For example, if there's a promotion that applies to the authenticated customer's group, the promotion's prices are used instead of the default prices.
|
||||
|
||||
---
|
||||
|
||||
@@ -117,7 +159,9 @@ If you pass the parameters mentioned above, each variant has a `calculated_price
|
||||
</Table.Body>
|
||||
</Table>
|
||||
|
||||
## Examples
|
||||
---
|
||||
|
||||
## Full Code Examples
|
||||
|
||||
- [Example: Show Product Variant's Price](./examples/show-price/page.mdx).
|
||||
- [Example: Show Product Variant's Sale Price](./examples/sale-price/page.mdx).
|
||||
|
||||
@@ -12,40 +12,24 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, learn how to retrieve a product and its details in the storefront.
|
||||
In this guide, you'll learn how to retrieve a product and its details in the storefront.
|
||||
|
||||
There are two ways to retrieve a product:
|
||||
|
||||
- Retrieve a product by its ID.
|
||||
- Retrieve a product by its ID. This method is straightforward and useful when you only have access to the product's ID.
|
||||
- Retrieve a product by its `handle` field. This is useful if you're creating human-readable URLs in your storefront.
|
||||
|
||||
## Retrieve a Product by ID
|
||||
|
||||
To retrieve a product by its ID, send a request to the [Retrieve Product API route](!api!/store#products_getproductsid):
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="Fetch API" value="fetch">
|
||||
|
||||
export const fetchHighlights = [
|
||||
["1", "id", "The product's ID."],
|
||||
["4", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
]
|
||||
|
||||
```ts highlights={fetchHighlights}
|
||||
fetch(`http://localhost:9000/store/products/${id}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ product }) => {
|
||||
// use the product...
|
||||
console.log(product)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
@@ -59,6 +43,7 @@ export const highlights = [
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "../../lib/sdk"
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
@@ -75,13 +60,7 @@ export const highlights = [
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
sdk.store.product.retrieve(id)
|
||||
.then(({ product: dataProduct }) => {
|
||||
setProduct(dataProduct)
|
||||
setLoading(false)
|
||||
@@ -118,11 +97,32 @@ export const highlights = [
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="JS SDK" value="js-sdk">
|
||||
|
||||
export const fetchHighlights = [
|
||||
["1", "id", "The product's ID."],
|
||||
]
|
||||
|
||||
```ts highlights={fetchHighlights}
|
||||
sdk.store.product.retrieve(id)
|
||||
.then(({ product: dataProduct }) => {
|
||||
// TODO use the product...
|
||||
console.log(dataProduct)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The response has a `product` field, which is a [product object](!api!/store#products_product_schema).
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Refer to the [Features in Product Details Page](#features-in-product-details-page) section to learn about other features you can add to a product details page.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Retrieve a Product by Handle
|
||||
@@ -130,38 +130,10 @@ The response has a `product` field, which is a [product object](!api!/store#prod
|
||||
To retrieve a product by its handle, send a request to the [List Products API route](!api!/store#products_getproducts) passing it the `handle` query parameter:
|
||||
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="Fetch API" value="fetch">
|
||||
|
||||
export const handleFetchHighlights = [
|
||||
["1", "id", "The product's ID."],
|
||||
["4", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
]
|
||||
|
||||
```ts highlights={handleFetchHighlights}
|
||||
fetch(`http://localhost:9000/store/products?handle=${handle}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ products }) => {
|
||||
if (!products.length) {
|
||||
// product with the specified handle doesn't exist
|
||||
return
|
||||
}
|
||||
// use the product...
|
||||
console.log(products[0])
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["21"], ["22"], ["23"],
|
||||
["24", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"]
|
||||
["24"], ["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"], ["32"]
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
@@ -169,12 +141,15 @@ export const handleHighlights = [
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "../../../lib/sdk"
|
||||
|
||||
type Props = {
|
||||
handle: string
|
||||
type Params = {
|
||||
params: {
|
||||
handle: string
|
||||
}
|
||||
}
|
||||
|
||||
export default function Product({ handle }: Props) {
|
||||
export default function Product({ params: { handle } }: Params) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
@@ -185,13 +160,9 @@ export const handleHighlights = [
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`http://localhost:9000/store/products?handle=${handle}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
sdk.store.product.list({
|
||||
handle,
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ products }) => {
|
||||
if (products.length) {
|
||||
setProduct(products[0])
|
||||
@@ -214,7 +185,7 @@ export const handleHighlights = [
|
||||
{option.title}
|
||||
<ul>
|
||||
{option.values?.map((optionValue) => (
|
||||
<li key={optionValue.id}>{optionValue.value}</li>
|
||||
<li id={optionValue.id}>{optionValue.value}</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
@@ -231,6 +202,27 @@ export const handleHighlights = [
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="JS SDK" value="js-sdk">
|
||||
|
||||
export const handleFetchHighlights = [
|
||||
["1", "handle", "The product's handle."],
|
||||
]
|
||||
|
||||
```ts highlights={handleFetchHighlights}
|
||||
sdk.store.product.list({
|
||||
handle,
|
||||
})
|
||||
.then(({ products }) => {
|
||||
if (!products.length) {
|
||||
// product with the specified handle doesn't exist
|
||||
return
|
||||
}
|
||||
// use the product...
|
||||
console.log(products[0])
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
@@ -238,7 +230,9 @@ export const handleHighlights = [
|
||||
|
||||
## Features in Product Details Page
|
||||
|
||||
In a product's details page, you want to allow the customer to choose a variant, see its price, and add it to the cart. The following guides will help you add these features into your storefront:
|
||||
In a product's details page, you want to allow the customer to choose a variant, see its price, and add it to the cart.
|
||||
|
||||
The following guides will help you add these features into your storefront:
|
||||
|
||||
- [Select a variant](../variants/page.mdx)
|
||||
- [Show variant price](../price/page.mdx)
|
||||
|
||||
@@ -12,25 +12,41 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how to select a product variant to be added to the cart in the storefront.
|
||||
In this guide, you'll learn how to select a product variant to be added to the cart in the storefront.
|
||||
|
||||
## Overview
|
||||
|
||||
Before a customer can add a product to the cart, they have to select from the product's available options.
|
||||
|
||||
Then, since a variant is a combination of the product options' values (for example, size `S` and color `Blue`), you must find the product variant that matches the chosen option values.
|
||||
|
||||
Finally, when the customer adds the product to the cart, you must add the selected variant to the cart.
|
||||
|
||||
In this guide, you'll learn how to show the product options and find the selected variant in a React-based storefront.
|
||||
|
||||
<Note>
|
||||
|
||||
The add-to-cart functionality is explained in the [Cart's guides](../../cart/page.mdx).
|
||||
Refer to the [Manage Cart's Items](../../cart/manage-items/page.mdx) guide to learn how to add a product variant to the cart.
|
||||
|
||||
</Note>
|
||||
|
||||
If a product has different options and variants for those options, the customer has to choose the options when adding the product to the cart.
|
||||
---
|
||||
|
||||
Since a variant is a combination of the product options' values (for example, size `S` and color `Blue`), you find the variant based on the chosen option values.
|
||||
## Example: React-Based Storefront
|
||||
|
||||
For example, in a React-based storefront:
|
||||
Here's an example of a React component that shows the product options and allows the customer to select a variant:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
export const highlights = [
|
||||
["15", "selectedOptions", "Store the options the customer selects."],
|
||||
["35", "selectedVariant", "Compute the selected variant based on the chosen option values combinations."],
|
||||
["64", "setSelectedOptions", "When an option's value is selected, add it to the selected options, which re-computes the selected variant."],
|
||||
["79", "selectedVariant", "Show the selected variant's ID, if computed."]
|
||||
["16", "selectedOptions", "Store the options the customer selects."],
|
||||
["30", "selectedVariant", "Compute the selected variant based on the chosen option values combinations."],
|
||||
["59", "setSelectedOptions", "When an option's value is selected, add it to the selected options, which re-computes the selected variant."],
|
||||
["74", "selectedVariant", "Show the selected variant's ID, if computed."]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -38,6 +54,7 @@ export const highlights = [
|
||||
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "../../../lib/sdk"
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
@@ -55,13 +72,7 @@ export default function Product({ id }: Props) {
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`http://localhost:9000/store/products/${id}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
sdk.store.product.retrieve(id)
|
||||
.then(({ product: dataProduct }) => {
|
||||
setProduct(dataProduct)
|
||||
setLoading(false)
|
||||
@@ -113,7 +124,10 @@ export default function Product({ id }: Props) {
|
||||
</ul>
|
||||
)}
|
||||
{selectedVariant && (
|
||||
<span>Selected Variant: {selectedVariant.id}</span>
|
||||
<>
|
||||
<span>Selected Variant: {selectedVariant.id}</span>
|
||||
{/* TODO: Show add to cart button */}
|
||||
</>
|
||||
)}
|
||||
{product.images?.map((image) => (
|
||||
<img src={image.url} key={image.id} />
|
||||
@@ -127,7 +141,11 @@ export default function Product({ id }: Props) {
|
||||
|
||||
In this example, you:
|
||||
|
||||
- Retrieve the product details from Medusa.
|
||||
- Show the product's options and allow the customer to select an option value.
|
||||
- Store the selected options in the `selectedOptions` state variable. It's an object whose keys are options' ID, and values are the selected value of that option.
|
||||
- Compute the selected variable whenever the selected option is changed. When the customer chooses a value for all options, you find a product variant that has the same chosen option-value combinations.
|
||||
- Change the `selectedOptions`'s value whenever the customer clicks on an option value.
|
||||
- Show the ID of the selected variant when it's found.
|
||||
|
||||
In your storefront, you should show the add-to-cart button instead of the variant ID. Refer to the [Manage Cart's Items](../../cart/manage-items/page.mdx) guide to learn how to add a product variant to the cart.
|
||||
|
||||
|
||||
@@ -12,10 +12,12 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
When sending requests to the `/store` API routes, you must pass the publishable API key in the header of your request.
|
||||
In this guide, you'll learn how to create and use the publishable API key in your storefront to interact with the Medusa application's Store API routes.
|
||||
|
||||
## What is a Publishable API Key?
|
||||
|
||||
When sending requests to the `/store` API routes, you must pass a publishable API key in the header of your request.
|
||||
|
||||
Publishable API keys specify the scope of a request. Admin users create them, and they can only be used on the client-side, such as in a storefront.
|
||||
|
||||
Publishable API keys are associated with sales channels. Then, when the publishable API key is passed in the header of a request, the Medusa application automatically infers what sales channel is being used.
|
||||
@@ -44,7 +46,9 @@ Learn how to send authenticated admin requests in the [Admin API reference](!api
|
||||
|
||||
</Note>
|
||||
|
||||
To add sales channels to the publishable API key's scope, use the [Manage Sales Channels API route](!api!/admin#api-keys_postapikeysidsaleschannels):
|
||||
### Add Sales Channels to the Publishable API Key's Scope
|
||||
|
||||
To add sales channels to the publishable API key's scope, you can either use the [Medusa Admin](!user-guide!/settings/developer/publishable-api-keys#manage-publishable-api-keys-sales-channels), or send a request to the [Manage Sales Channels API route](!api!/admin#api-keys_postapikeysidsaleschannels):
|
||||
|
||||
```bash
|
||||
curl -X POST 'http://localhost:9000/admin/api-keys/apk_123/sales-channels' \
|
||||
@@ -63,24 +67,30 @@ Make sure to replace `apk_123` with the ID of the publishable API key, and `sc_1
|
||||
|
||||
In your storefront, pass the `x-publishable-api-key` in the header of all your requests to the Medusa application.
|
||||
|
||||
When using the JS SDK, set the publishable API key as an environment variable and pass it to the JS SDK's configurations.
|
||||
|
||||
For example:
|
||||
|
||||
export const highlights = [
|
||||
["4", "NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "An environment variable that holds the publishable API key's token."]
|
||||
["12", "NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "An environment variable that holds the publishable API key's token."]
|
||||
]
|
||||
|
||||
```ts
|
||||
fetch(`http://localhost:9000/store/products`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
// use products...
|
||||
console.log(data.products)
|
||||
import Medusa from "@medusajs/js-sdk"
|
||||
|
||||
let MEDUSA_BACKEND_URL = "http://localhost:9000"
|
||||
|
||||
if (process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL) {
|
||||
MEDUSA_BACKEND_URL = process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL
|
||||
}
|
||||
|
||||
export const sdk = new Medusa({
|
||||
baseUrl: MEDUSA_BACKEND_URL,
|
||||
debug: process.env.NODE_ENV === "development",
|
||||
publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
|
||||
})
|
||||
```
|
||||
|
||||
Where `NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY` is an environment variable that holds your publishable API key's token.
|
||||
|
||||
The JS SDK will now take care of passing the publishable API key in the header of all requests to the Medusa application.
|
||||
@@ -7,12 +7,20 @@ tags:
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Region Context in Storefront`,
|
||||
title: `Region React Context in Storefront`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
Throughout your storefront, you'll need to access the selected region to perform different actions, such as retrieve product's prices in the selected region.
|
||||
In this guide, you'll learn how to create a region context in your React storefront.
|
||||
|
||||
Throughout your storefront, you'll need to access the customer's selected region to perform different actions, such as retrieve product's prices in the selected region.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
To learn how to allow customers to select their region, refer to the [Store Selected Region in Storefront](../store-retrieve-region/page.mdx) guide.
|
||||
|
||||
</Note>
|
||||
|
||||
So, if your storefront is React-based, create a region context and add it at the top of your components tree. Then, you can access the selected region anywhere in your storefront.
|
||||
|
||||
@@ -20,15 +28,21 @@ So, if your storefront is React-based, create a region context and add it at the
|
||||
|
||||
For example, create the following file that exports a `RegionProvider` component and a `useRegion` hook:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
export const highlights = [
|
||||
["12", "region", "Expose region to children of the context provider."],
|
||||
["13", "setRegion", "Allow the context provider's children to change the selected region."],
|
||||
["24", "RegionProvider", "The provider component to use in your component tree."],
|
||||
["32", "", "If a region is set, set its ID in the local storage again in case it changed."],
|
||||
["39", "regionId", "Retrieve the selected region from the `localStorage`."],
|
||||
["42", "fetch", "If no region is selected, retrieve the list of regions from the Medusa application and select the first one."],
|
||||
["54", "fetch", "If a region is selected, retrieve it from the Medusa application."],
|
||||
["77", "useRegion", "The hook that child components of the provider use to access the region."]
|
||||
["13", "region", "Expose region to children of the context provider."],
|
||||
["14", "setRegion", "Allow the context provider's children to change the selected region."],
|
||||
["25", "RegionProvider", "The provider component to use in your component tree."],
|
||||
["31", "", "If a region is set, set its ID in the local storage again in case it changed."],
|
||||
["38", "regionId", "Retrieve the selected region from the `localStorage`."],
|
||||
["41", "list", "If no region is selected, retrieve the list of regions from the Medusa application and select the first one."],
|
||||
["47", "retrieve", "If a region is selected, retrieve it from the Medusa application."],
|
||||
["6", "useRegion", "The hook that child components of the provider use to access the region."]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -41,6 +55,7 @@ import {
|
||||
useState,
|
||||
} from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "../lib/sdk"
|
||||
|
||||
type RegionContextType = {
|
||||
region?: HttpTypes.StoreRegion
|
||||
@@ -55,9 +70,7 @@ type RegionProviderProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const RegionProvider = (
|
||||
{ children }: RegionProviderProps
|
||||
) => {
|
||||
export const RegionProvider = ({ children }: RegionProviderProps) => {
|
||||
const [region, setRegion] = useState<
|
||||
HttpTypes.StoreRegion
|
||||
>()
|
||||
@@ -73,25 +86,13 @@ export const RegionProvider = (
|
||||
const regionId = localStorage.getItem("region_id")
|
||||
if (!regionId) {
|
||||
// retrieve regions and select the first one
|
||||
fetch(`http://localhost:9000/store/regions`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
sdk.store.region.list()
|
||||
.then(({ regions }) => {
|
||||
setRegion(regions[0])
|
||||
})
|
||||
} else {
|
||||
// retrieve selected region
|
||||
fetch(`http://localhost:9000/store/regions/${regionId}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
sdk.store.region.retrieve(regionId)
|
||||
.then(({ region: dataRegion }) => {
|
||||
setRegion(dataRegion)
|
||||
})
|
||||
@@ -163,9 +164,7 @@ export default function RootLayout({
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Use useRegion Hook
|
||||
### Use useRegion Hook
|
||||
|
||||
Now, you can use the `useRegion` hook in child components of `RegionProvider`.
|
||||
|
||||
|
||||
@@ -12,31 +12,27 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you'll learn how to retrieve the list of regions in your storefront.
|
||||
|
||||
<Note title="Good to know">
|
||||
|
||||
A region is a geographical area that you sell your products in. In your storefront, you should display regions to your customers, allowing them to select their region to see prices, taxes, and payment methods specific to their region.
|
||||
|
||||
</Note>
|
||||
|
||||
To list regions in your storefront, send a request to the [List Regions API route](!api!/store#regions_getregions):
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="Fetch API" value="fetch">
|
||||
|
||||
```ts
|
||||
fetch(`http://localhost:9000/store/regions`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ regions }) => {
|
||||
// use regions...
|
||||
console.log(regions)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["17"], ["18"], ["19"], ["20"], ["21"], ["22"], ["23"], ["24"],
|
||||
["25"], ["26"], ["27"]
|
||||
["18"], ["19"], ["20"], ["21"], ["22"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -44,6 +40,7 @@ export const highlights = [
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "../../lib/sdk"
|
||||
|
||||
export default function Regions() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -56,13 +53,7 @@ export const highlights = [
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`http://localhost:9000/store/regions`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
sdk.store.region.list()
|
||||
.then(({ regions: dataRegions }) => {
|
||||
setRegions(dataRegions)
|
||||
setLoading(false)
|
||||
@@ -85,7 +76,20 @@ export const highlights = [
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="JS SDK" value="js-sdk">
|
||||
|
||||
```ts
|
||||
sdk.store.region.list()
|
||||
.then(({ regions: dataRegions }) => {
|
||||
setRegions(dataRegions)
|
||||
setLoading(false)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The response has a `regions` field, which is an array of [regions](!api!/store#regions_region_schema).
|
||||
|
||||
Next, you can learn how to allow the customer to select a region in the [Store and Retrieve Region guide](../store-retrieve-region/page.mdx).
|
||||
+27
-14
@@ -5,16 +5,24 @@ tags:
|
||||
---
|
||||
|
||||
export const metadata = {
|
||||
title: `Store and Retrieve Region`,
|
||||
title: `Store Selected Region in Storefront`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how to store a customer's region's ID and retrieve the selected region.
|
||||
In this guide, you'll learn how to store a customer's selected region in your storefront, then retrieve it for later use.
|
||||
|
||||
## Why Store and Retrieve Region?
|
||||
|
||||
In your store, prices, taxes, and available payment methods can vary between regions. So, you should allow customers to select their region to see the correct prices, taxes, and payment methods.
|
||||
|
||||
---
|
||||
|
||||
## Store Selected Region ID
|
||||
|
||||
When the customer selects their region, for example, from a dropdown, store that region's ID in the `localStorage`.
|
||||
To allow the customer to select a region, you should show them the list of regions as explained in the [List Regions](../list/page.mdx) guide. You can show them in a select input, for example.
|
||||
|
||||
Then, once the customer selects their region, store that region's ID in the `localStorage`.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -22,7 +30,7 @@ For example:
|
||||
localStorage.setItem("region_id", region.id)
|
||||
```
|
||||
|
||||
Then, you retrieve it later using the `localSorage.getItem` method later:
|
||||
Then, you can retrieve it later using the `localSorage.getItem` method:
|
||||
|
||||
```ts
|
||||
const regionId = localStorage.getItem("region_id")
|
||||
@@ -30,22 +38,27 @@ const regionId = localStorage.getItem("region_id")
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Selected Region
|
||||
## Retrieve Selected Region's Details
|
||||
|
||||
To retrieve the selected region, use the [Retrieve Region API route](!api!/store#regions_getregionsid):
|
||||
As you build your storefront, you may need to retrieve the full details of a region. For example, to get the region's currency code.
|
||||
|
||||
To retrieve the selected region's details from Medusa, use the [Retrieve Region API route](!api!/store#regions_getregionsid):
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
```ts
|
||||
const regionId = localStorage.getItem("region_id")
|
||||
|
||||
fetch(`http://localhost:9000/store/regions/${regionId}`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
sdk.store.region.retrieve(regionId)
|
||||
.then(({ region }) => {
|
||||
// do something with region.
|
||||
console.log(region)
|
||||
})
|
||||
```
|
||||
|
||||
The response has a `regions` field, which is an array of [regions](!api!/store#regions_region_schema).
|
||||
|
||||
If you're using React, it's then recommended to create a context that stores the region details and make it available to all components in your application, as explained in the [Region React Context in Storefront](../context/page.mdx) guide.
|
||||
|
||||
@@ -15,7 +15,7 @@ In this document, you’ll find tips useful when building a storefront.
|
||||
|
||||
To send requests from the storefront to the Medusa application’s Store API Routes, you have three options:
|
||||
|
||||
- **For JavaScript frameworks**: use Medusa’s [JS SDK](../../js-sdk/page.mdx) in any JavaScript framework. This NPM package facilitates interacting with the backend’s REST APIs.
|
||||
- **For JavaScript frameworks**: use Medusa’s [JS SDK](../../js-sdk/page.mdx) in any JavaScript framework. This NPM package facilitates interacting with the backend’s REST APIs. All Storefront Development guides use the JS SDK.
|
||||
- **For other frontend technologies**: interact directly with the Medusa application by sending requests to its [Store REST APIs](https://docs.medusajs.com/api/store).
|
||||
|
||||
---
|
||||
@@ -24,7 +24,7 @@ To send requests from the storefront to the Medusa application’s Store API Rou
|
||||
|
||||
The `@medusajs/types` package provide API routes' request and response types.
|
||||
|
||||
If you're not using the JS SDK, install `@medusajs/types` to use the correct request and response types:
|
||||
If you're not using the JS SDK but are building your application with TypeScript, install `@medusajs/types` to use the correct request and response types:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install @medusajs/types@latest
|
||||
|
||||
@@ -164,20 +164,20 @@ export const generatedEditDates = {
|
||||
"app/storefront-development/products/collections/products/page.mdx": "2025-02-26T11:47:46.882Z",
|
||||
"app/storefront-development/products/collections/retrieve/page.mdx": "2025-02-26T11:48:08.506Z",
|
||||
"app/storefront-development/products/collections/page.mdx": "2024-06-11T19:55:56+02:00",
|
||||
"app/storefront-development/products/list/page.mdx": "2025-02-26T11:48:38.941Z",
|
||||
"app/storefront-development/products/price/examples/sale-price/page.mdx": "2025-01-06T15:39:33.475Z",
|
||||
"app/storefront-development/products/price/examples/show-price/page.mdx": "2025-01-06T15:37:57.350Z",
|
||||
"app/storefront-development/products/price/examples/tax-price/page.mdx": "2025-01-06T15:40:56.854Z",
|
||||
"app/storefront-development/products/price/page.mdx": "2024-12-19T16:35:19.471Z",
|
||||
"app/storefront-development/products/retrieve/page.mdx": "2025-02-26T11:48:25.232Z",
|
||||
"app/storefront-development/products/variants/page.mdx": "2025-01-06T15:36:41.374Z",
|
||||
"app/storefront-development/products/list/page.mdx": "2025-03-26T11:27:42.966Z",
|
||||
"app/storefront-development/products/price/examples/sale-price/page.mdx": "2025-03-26T12:06:29.002Z",
|
||||
"app/storefront-development/products/price/examples/show-price/page.mdx": "2025-03-26T12:04:39.304Z",
|
||||
"app/storefront-development/products/price/examples/tax-price/page.mdx": "2025-03-26T12:16:45.294Z",
|
||||
"app/storefront-development/products/price/page.mdx": "2025-03-26T12:08:16.029Z",
|
||||
"app/storefront-development/products/retrieve/page.mdx": "2025-03-26T11:27:19.695Z",
|
||||
"app/storefront-development/products/variants/page.mdx": "2025-03-26T11:27:49.917Z",
|
||||
"app/storefront-development/products/page.mdx": "2024-06-11T19:55:56+02:00",
|
||||
"app/storefront-development/regions/context/page.mdx": "2024-12-19T16:36:07.406Z",
|
||||
"app/storefront-development/regions/list/page.mdx": "2025-01-06T15:23:05.744Z",
|
||||
"app/storefront-development/regions/store-retrieve-region/page.mdx": "2024-12-19T16:36:22.800Z",
|
||||
"app/storefront-development/regions/context/page.mdx": "2025-03-26T10:53:16.917Z",
|
||||
"app/storefront-development/regions/list/page.mdx": "2025-03-26T10:51:33.951Z",
|
||||
"app/storefront-development/regions/store-retrieve-region/page.mdx": "2025-03-26T10:51:27.384Z",
|
||||
"app/storefront-development/regions/page.mdx": "2024-06-09T15:19:09+02:00",
|
||||
"app/storefront-development/tips/page.mdx": "2024-12-19T16:36:32.938Z",
|
||||
"app/storefront-development/page.mdx": "2025-03-10T12:26:51.415Z",
|
||||
"app/storefront-development/tips/page.mdx": "2025-03-26T10:31:43.816Z",
|
||||
"app/storefront-development/page.mdx": "2025-03-26T10:31:43.815Z",
|
||||
"app/troubleshooting/cors-errors/page.mdx": "2024-05-03T17:36:38+03:00",
|
||||
"app/troubleshooting/create-medusa-app-errors/page.mdx": "2024-07-11T10:29:13+03:00",
|
||||
"app/troubleshooting/database-errors/page.mdx": "2024-05-03T17:36:38+03:00",
|
||||
@@ -945,7 +945,7 @@ export const generatedEditDates = {
|
||||
"references/order/IOrderModuleService/methods/order.IOrderModuleService.updateOrderChangeActions/page.mdx": "2025-01-13T18:05:56.207Z",
|
||||
"references/types/ModulesSdkTypes/types/types.ModulesSdkTypes.RemoteQueryFunction/page.mdx": "2025-02-24T10:48:38.938Z",
|
||||
"references/types/types.CommonTypes/page.mdx": "2025-01-13T17:30:27.580Z",
|
||||
"app/storefront-development/publishable-api-keys/page.mdx": "2025-02-26T11:49:00.515Z",
|
||||
"app/storefront-development/publishable-api-keys/page.mdx": "2025-03-26T10:31:43.815Z",
|
||||
"references/api_key/types/api_key.ExpandScalar/page.mdx": "2024-09-17T00:10:59.563Z",
|
||||
"references/api_key/types/api_key.FilterQuery/page.mdx": "2024-11-27T16:33:40.706Z",
|
||||
"references/api_key/types/api_key.FilterValue/page.mdx": "2024-09-17T00:10:59.571Z",
|
||||
|
||||
Reference in New Issue
Block a user