docs: small fixes and improvements to text (#14385)

This commit is contained in:
Shahed Nasser
2025-12-22 17:06:25 +02:00
committed by GitHub
parent b221e882d4
commit dc52dfd1dd
9 changed files with 134 additions and 210 deletions

View File

@@ -6,18 +6,12 @@ export const metadata = {
In this chapter, you'll build a Brand Module that adds a `brand` table to the database and provides data-management features for it.
A module is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](!resources!/commerce-modules/cart) that holds the data models and business logic for cart operations.
A [module](../../../fundamentals/modules/page.mdx) is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](!resources!/commerce-modules/cart) that holds the data models and business logic for cart operations.
In a module, you create data models and business logic to manage them. In the next chapters, you'll see how you use the module to build commerce features.
![Diagram showcasing an overview of the Brand Module](https://res.cloudinary.com/dza7lstvk/image/upload/v1746546820/Medusa%20Resources/brand-module_pg86gm.jpg)
<Note>
Learn more about modules in [this chapter](../../../fundamentals/modules/page.mdx).
</Note>
## 1. Create Module Directory
Modules are created in a sub-directory of `src/modules`. So, start by creating the directory `src/modules/brand` that will hold the Brand Module's files.
@@ -28,13 +22,7 @@ Modules are created in a sub-directory of `src/modules`. So, start by creating t
## 2. Create Data Model
A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations.
<Note>
Learn more about data models in [this chapter](../../../fundamentals/modules/page.mdx#1-create-data-model).
</Note>
A [data model](../../../fundamentals/modules/page.mdx#1-create-data-model) represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations.
You create a data model in a TypeScript or JavaScript file under the `models` directory of a module. So, to create a data model that represents a new `brand` table in the database, create the file `src/modules/brand/models/brand.ts` with the following content:
@@ -58,7 +46,7 @@ You define the data model using the `define` method of the DML. It accepts two p
<Note title="Tip">
Learn about other property types in [this chapter](../../../fundamentals/data-models/properties/page.mdx).
Refer to the [Properties](../../../fundamentals/data-models/properties/page.mdx) chapter to learn more.
</Note>
@@ -66,16 +54,10 @@ Learn about other property types in [this chapter](../../../fundamentals/data-mo
## 3. Create Module Service
You perform database operations on your data models in a service, which is a class exported by the module and acts like an interface to its functionalities.
You perform database operations on your data models in a [service](../../../fundamentals/modules/page.mdx#2-create-service), which is a class exported by the module and acts like an interface to its functionalities.
In this step, you'll create the Brand Module's service that provides methods to manage the `Brand` data model. In the next chapters, you'll use this service when exposing custom features that involve managing brands.
<Note>
Learn more about services in [this chapter](../../../fundamentals/modules/page.mdx#2-create-service).
</Note>
You define a service in a `service.ts` or `service.js` file at the root of your module's directory. So, create the file `src/modules/brand/service.ts` with the following content:
![Directory structure in module after adding the service](https://res.cloudinary.com/dza7lstvk/image/upload/v1732868984/Medusa%20Book/brand-dir-overview-3_jo7baj.jpg)
@@ -105,7 +87,7 @@ You'll use these methods in the [next chapter](../workflow/page.mdx).
<Note title="Tip">
Find a reference of all generated methods in [this guide](!resources!/service-factory-reference).
Refer to the [service factory reference](!resources!/service-factory-reference) to learn more about the generated methods.
</Note>
@@ -166,13 +148,7 @@ The Brand Module is now added to your Medusa application. You'll start using it
## 6. Generate and Run Migrations
A migration is a TypeScript or JavaScript file that defines database changes made by a module. Migrations ensure that your module is re-usable and removes friction when working in a team, making it easy to reflect changes across team members' databases.
<Note>
Learn more about migrations in [this chapter](../../../fundamentals/modules/page.mdx#5-generate-migrations).
</Note>
A [migration](../../../fundamentals/modules/page.mdx#5-generate-migrations) is a TypeScript or JavaScript file that defines database changes made by a module. Migrations ensure that your module is re-usable and removes friction when working in a team, making it easy to reflect changes across team members' databases.
[Medusa's CLI tool](!resources!/medusa-cli) allows you to generate migration files for your module, then run those migrations to reflect the changes in the database. So, run the following commands in your Medusa application's directory:

View File

@@ -76,7 +76,7 @@ You return in the response the retrieved brands and the pagination configuration
<Note>
Learn more about pagination with Query in [this chapter](../../../fundamentals/module-links/query/page.mdx#apply-pagination).
Refer to the [Query](../../../fundamentals/module-links/query/page.mdx#apply-pagination) chapter to learn more about applying pagination when retrieving linked records.
</Note>
@@ -138,7 +138,7 @@ By applying the above middleware, you can pass pagination configurations to `GET
<Note>
Learn more about using the `validateAndTransformQuery` middleware to configure Query in [this chapter](../../../fundamentals/module-links/query/page.mdx#request-query-configurations).
Refer to the [Query](../../../fundamentals/module-links/query/page.mdx#request-query-configurations) chapter to learn more about using the `validateAndTransformQuery` middleware to configure Query.
</Note>
@@ -176,7 +176,7 @@ You can now use the SDK to send requests to the Medusa server.
<Note>
Learn more about the JS SDK and its options in [this reference](!resources!/js-sdk).
Refer to the [JS SDK Reference](!resources!/js-sdk) to learn more about the it, its options, and how to use it to send requests to Medusa's API routes.
</Note>
@@ -188,7 +188,7 @@ You'll now add the UI route that shows the paginated list of brands. A UI route
<Note>
Learn more about UI routes in [this chapter](../../../fundamentals/admin/ui-routes/page.mdx).
Refer to the [UI Routes](../../../fundamentals/admin/ui-routes/page.mdx) chapter to learn more about UI routes.
</Note>

View File

@@ -48,13 +48,13 @@ You initialize the SDK passing it the following options:
- `debug`: Whether to enable logging debug messages. This should only be enabled in development.
- `auth.type`: The authentication method used in the client application, which is `session` in the Medusa Admin dashboard.
Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in [this chapter](../../../fundamentals/admin/environment-variables/page.mdx).
Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in the [Admin Environment Variables](../../../fundamentals/admin/environment-variables/page.mdx) chapter.
You can now use the SDK to send requests to the Medusa server.
<Note>
Learn more about the JS SDK and its options in [this reference](!resources!/js-sdk).
Refer to the [JS SDK Reference](!resources!/js-sdk) to learn more about the it, its options, and how to use it to send requests to Medusa's API routes.
</Note>
@@ -62,13 +62,7 @@ Learn more about the JS SDK and its options in [this reference](!resources!/js-s
## 2. Add Widget to Product Details Page
You'll now add a widget to the product-details page. A widget is a React component that's injected into pre-defined zones in the Medusa Admin dashboard. It's created in a `.tsx` file under the `src/admin/widgets` directory.
<Note>
Learn more about widgets in [this documentation](../../../fundamentals/admin/widgets/page.mdx).
</Note>
You'll now add a widget to the product-details page. A [widget](../../../fundamentals/admin/widgets/page.mdx) is a React component that's injected into pre-defined zones in the Medusa Admin dashboard. It's created in a `.tsx` file under the `src/admin/widgets` directory.
To create a widget that shows a product's brand in its details page, create the file `src/admin/widgets/product-brand.tsx` with the following content:

View File

@@ -13,18 +13,12 @@ export const metadata = {
In this chapter, you'll learn how to define a module link between a brand defined in the [custom Brand Module](../../custom-features/module/page.mdx), and a product defined in the [Product Module](!resources!/commerce-modules/product) that's available in your Medusa application out-of-the-box.
Modules are [isolated](../../../fundamentals/modules/isolation/page.mdx) from other resources, ensuring that they're integrated into the Medusa application without side effects. However, you may need to associate data models of different modules, or you're trying to extend data models from Commerce Modules with custom properties. To do that, you define module links.
Modules are [isolated](../../../fundamentals/modules/isolation/page.mdx) from other resources, ensuring that they're integrated into the Medusa application without side effects. However, you may need to build relations between data models of different modules, or you're trying to extend data models from [Commerce Modules](!resources!/commerce-modules) with custom properties. To do that, you define module links.
A module link forms an association between two data models of different modules while maintaining module isolation. You can then manage and query linked records of the data models using Medusa's Modules SDK.
A [module link](../../../fundamentals/module-links/page.mdx) forms an association between two data models of different modules while maintaining module isolation. You can then manage and query linked records of the data models using Medusa's Modules SDK.
In this chapter, you'll define a module link between the `Brand` data model of the Brand Module, and the `Product` data model of the Product Module. In later chapters, you'll manage and retrieve linked product and brand records.
<Note>
Learn more about module links in [this chapters](../../../fundamentals/module-links/page.mdx).
</Note>
<Prerequisites
items={[
{

View File

@@ -22,7 +22,7 @@ So, in this chapter, to extend the create product flow and associate a brand wit
<Note>
To learn more about the `additional_data` property and the API routes that accept additional data, refer to [this chapter](../../../fundamentals/api-routes/additional-data/page.mdx).
To learn more about the `additional_data` property and the API routes that accept additional data, refer to the [Additional Data](../../../fundamentals/api-routes/additional-data/page.mdx) chapter.
</Note>
@@ -43,13 +43,7 @@ To learn more about the `additional_data` property and the API routes that accep
## 1. Consume the productsCreated Hook
A workflow hook is a point in a workflow where you can inject a step to perform a custom functionality. Consuming a workflow hook allows you to extend the features of a workflow and, consequently, the API route that uses it.
<Note>
Learn more about the workflow hooks in [this chapter](../../../fundamentals/workflows/workflow-hooks/page.mdx).
</Note>
A [workflow hook](../../../fundamentals/workflows/workflow-hooks/page.mdx) is a point in a workflow where you can inject a step to perform a custom functionality. Consuming a workflow hook allows you to extend the features of a workflow and, consequently, the API route that uses it.
The [createProductsWorkflow](!resources!/references/medusa-workflows/createProductsWorkflow) used in the [Create Product API route](!api!/admin#products_postproducts) has a `productsCreated` hook that runs after the product is created. You'll consume this hook to link the created product with the brand specified in the request parameters.
@@ -98,13 +92,7 @@ In the step, if a brand ID is passed in `additional_data`, you resolve the Brand
### Link Brand to Product
Next, you want to create a link between the created products and the brand. To do so, you use Link, which is a class from the Modules SDK that provides methods to manage linked records.
<Note>
Learn more about Link in [this chapter](../../../fundamentals/module-links/link/page.mdx).
</Note>
Next, you want to create a link between the created products and the brand. To do so, you use [Link](../../../fundamentals/module-links/link/page.mdx), which is a class from the Modules SDK that provides methods to manage linked records.
To use Link in the `productsCreated` hook, replace the `TODO` with the following:
@@ -139,7 +127,7 @@ logger.info("Linked brand to products")
return new StepResponse(links, links)
```
You resolve Link from the container. Then you loop over the created products to assemble an array of links to be created. After that, you pass the array of links to Link's `create` method, which will link the product and brand records.
You resolve Link from the container. Then, you loop over the created products to assemble an array of links to be created. After that, you pass the array of links to Link's `create` method, which will link the product and brand records.
Each property in the link object is the name of a module, and its value is an object having a `{model_name}_id` property, where `{model_name}` is the snake-case name of the module's data model. Its value is the ID of the record to be linked. The link object's properties must be set in the same order as the link configurations passed to `defineLink`.

View File

@@ -44,7 +44,7 @@ For example, send the following request to retrieve the list of products with th
```bash
curl 'http://localhost:9000/admin/products?fields=+brand.*' \
--header 'Authorization: Bearer {token}'
-H 'Authorization: Bearer {token}'
```
<Note title="Tip">
@@ -75,19 +75,13 @@ By using the `fields` query parameter, you don't have to re-create existing API
While you can retrieve linked records using the `fields` query parameter of an existing API route, you can't filter by linked records.
Instead, you'll have to create a custom API route that uses Query to retrieve linked records with filters, as explained in the [Query documentation](../../../fundamentals/module-links/query/page.mdx#apply-filters-and-pagination-on-linked-records).
Instead, you'll have to create a custom API route that uses [Query](../../../fundamentals/module-links/query/page.mdx#apply-filters-and-pagination-on-linked-records) to retrieve linked records with filters.
---
## Approach 2: Use Query to Retrieve Linked Records
You can also retrieve linked records using Query. Query allows you to retrieve data across modules with filters, pagination, and more. You can resolve Query from the Medusa container and use it in your API route or workflow.
<Note>
Learn more about Query in [this chapter](../../../fundamentals/module-links/query/page.mdx).
</Note>
You can also retrieve linked records using [Query](../../../fundamentals/module-links/query/page.mdx). Query allows you to retrieve data across modules with filters, pagination, and more. You can resolve Query from the Medusa container and use it in your API route or workflow.
For example, you can create an API route that retrieves brands and their products. If you followed the [Create Brands API route chapter](../../custom-features/api-route/page.mdx), you'll have the file `src/api/admin/brands/route.ts` with a `POST` API route. Add a new `GET` function to the same file:
@@ -183,6 +177,6 @@ By following the examples of the previous chapters, you:
## Next Steps: Customize Medusa Admin
Clients, such as the Medusa Admin dashboard, can now use brand-related features, such as creating a brand or setting the brand of a product.
Client applications, such as the Medusa Admin dashboard, can now use brand-related features, such as creating a brand or setting the brand of a product.
In the next chapters, you'll learn how to customize the Medusa Admin to show a product's brand on its details page, and to show a new page with the list of brands in your store.

View File

@@ -8,7 +8,7 @@ export const metadata = {
In this chapter, you'll learn the approach recommended when you need to override an existing API route in Medusa.
## Approaches to Consider Before Overriding API Routes
## Approaches to Consider Instead of Overriding API Routes
While building customizations in your Medusa application, you may need to make changes to existing API routes for your business use case.

View File

@@ -73,16 +73,16 @@ export const generatedEditDates = {
"app/learn/fundamentals/api-routes/additional-data/page.mdx": "2025-04-17T08:50:17.036Z",
"app/learn/fundamentals/workflows/variable-manipulation/page.mdx": "2025-04-24T13:14:43.967Z",
"app/learn/customization/custom-features/api-route/page.mdx": "2025-10-16T11:23:11.195Z",
"app/learn/customization/custom-features/module/page.mdx": "2025-05-06T16:10:50.090Z",
"app/learn/customization/custom-features/module/page.mdx": "2025-12-22T13:56:57.561Z",
"app/learn/customization/custom-features/workflow/page.mdx": "2024-12-09T14:36:29.482Z",
"app/learn/customization/extend-features/extend-create-product/page.mdx": "2025-01-06T11:18:58.250Z",
"app/learn/customization/extend-features/extend-create-product/page.mdx": "2025-12-22T13:05:12.452Z",
"app/learn/customization/custom-features/page.mdx": "2025-07-21T08:17:33.542Z",
"app/learn/customization/customize-admin/page.mdx": "2025-07-21T08:19:07.699Z",
"app/learn/customization/customize-admin/route/page.mdx": "2025-02-11T15:56:03.835Z",
"app/learn/customization/customize-admin/widget/page.mdx": "2025-02-05T09:10:18.163Z",
"app/learn/customization/extend-features/define-link/page.mdx": "2025-04-17T08:50:17.036Z",
"app/learn/customization/customize-admin/route/page.mdx": "2025-12-22T13:54:49.635Z",
"app/learn/customization/customize-admin/widget/page.mdx": "2025-12-22T13:51:50.597Z",
"app/learn/customization/extend-features/define-link/page.mdx": "2025-12-22T13:50:02.230Z",
"app/learn/customization/extend-features/page.mdx": "2024-12-09T11:02:39.244Z",
"app/learn/customization/extend-features/query-linked-records/page.mdx": "2025-04-18T07:41:05.912Z",
"app/learn/customization/extend-features/query-linked-records/page.mdx": "2025-12-22T13:01:28.620Z",
"app/learn/customization/integrate-systems/handle-event/page.mdx": "2025-06-26T14:26:15.310Z",
"app/learn/customization/integrate-systems/page.mdx": "2024-12-09T10:40:08.528Z",
"app/learn/customization/integrate-systems/schedule-task/page.mdx": "2025-01-28T16:42:42.071Z",
@@ -119,7 +119,7 @@ export const generatedEditDates = {
"app/learn/fundamentals/framework/page.mdx": "2025-06-26T14:26:22.120Z",
"app/learn/fundamentals/api-routes/retrieve-custom-links/page.mdx": "2025-07-14T10:24:32.582Z",
"app/learn/fundamentals/workflows/errors/page.mdx": "2025-04-25T14:26:25.000Z",
"app/learn/fundamentals/api-routes/override/page.mdx": "2025-05-09T08:01:24.493Z",
"app/learn/fundamentals/api-routes/override/page.mdx": "2025-12-22T12:56:06.558Z",
"app/learn/fundamentals/module-links/index/page.mdx": "2025-05-23T07:57:58.958Z",
"app/learn/fundamentals/module-links/index-module/page.mdx": "2025-11-26T11:20:25.961Z",
"app/learn/introduction/build-with-llms-ai/page.mdx": "2025-12-09T14:17:13.295Z",

View File

@@ -3122,14 +3122,12 @@ In the next chapters, you'll learn how to build associations between data models
In this chapter, you'll build a Brand Module that adds a `brand` table to the database and provides data-management features for it.
A module is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](https://docs.medusajs.com/resources/commerce-modules/cart/index.html.md) that holds the data models and business logic for cart operations.
A [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](https://docs.medusajs.com/resources/commerce-modules/cart/index.html.md) that holds the data models and business logic for cart operations.
In a module, you create data models and business logic to manage them. In the next chapters, you'll see how you use the module to build commerce features.
![Diagram showcasing an overview of the Brand Module](https://res.cloudinary.com/dza7lstvk/image/upload/v1746546820/Medusa%20Resources/brand-module_pg86gm.jpg)
Learn more about modules in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md).
## 1. Create Module Directory
Modules are created in a sub-directory of `src/modules`. So, start by creating the directory `src/modules/brand` that will hold the Brand Module's files.
@@ -3140,9 +3138,7 @@ Modules are created in a sub-directory of `src/modules`. So, start by creating t
## 2. Create Data Model
A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations.
Learn more about data models in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules#1-create-data-model/index.html.md).
A [data model](https://docs.medusajs.com/learn/fundamentals/modules#1-create-data-model/index.html.md) represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations.
You create a data model in a TypeScript or JavaScript file under the `models` directory of a module. So, to create a data model that represents a new `brand` table in the database, create the file `src/modules/brand/models/brand.ts` with the following content:
@@ -3164,18 +3160,16 @@ You define the data model using the `define` method of the DML. It accepts two p
1. The first one is the name of the data model's table in the database. Use snake-case names.
2. The second is an object, which is the data model's schema.
Learn about other property types in [this chapter](https://docs.medusajs.com/learn/fundamentals/data-models/properties/index.html.md).
Refer to the [Properties](https://docs.medusajs.com/learn/fundamentals/data-models/properties/index.html.md) chapter to learn more.
***
## 3. Create Module Service
You perform database operations on your data models in a service, which is a class exported by the module and acts like an interface to its functionalities.
You perform database operations on your data models in a [service](https://docs.medusajs.com/learn/fundamentals/modules#2-create-service/index.html.md), which is a class exported by the module and acts like an interface to its functionalities.
In this step, you'll create the Brand Module's service that provides methods to manage the `Brand` data model. In the next chapters, you'll use this service when exposing custom features that involve managing brands.
Learn more about services in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules#2-create-service/index.html.md).
You define a service in a `service.ts` or `service.js` file at the root of your module's directory. So, create the file `src/modules/brand/service.ts` with the following content:
![Directory structure in module after adding the service](https://res.cloudinary.com/dza7lstvk/image/upload/v1732868984/Medusa%20Book/brand-dir-overview-3_jo7baj.jpg)
@@ -3199,7 +3193,7 @@ The `MedusaService` function receives an object of the module's data models as a
You'll use these methods in the [next chapter](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md).
Find a reference of all generated methods in [this guide](https://docs.medusajs.com/resources/service-factory-reference/index.html.md).
Refer to the [service factory reference](https://docs.medusajs.com/resources/service-factory-reference/index.html.md) to learn more about the generated methods.
***
@@ -3254,9 +3248,7 @@ The Brand Module is now added to your Medusa application. You'll start using it
## 6. Generate and Run Migrations
A migration is a TypeScript or JavaScript file that defines database changes made by a module. Migrations ensure that your module is re-usable and removes friction when working in a team, making it easy to reflect changes across team members' databases.
Learn more about migrations in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules#5-generate-migrations/index.html.md).
A [migration](https://docs.medusajs.com/learn/fundamentals/modules#5-generate-migrations/index.html.md) is a TypeScript or JavaScript file that defines database changes made by a module. Migrations ensure that your module is re-usable and removes friction when working in a team, making it easy to reflect changes across team members' databases.
[Medusa's CLI tool](https://docs.medusajs.com/resources/medusa-cli/index.html.md) allows you to generate migration files for your module, then run those migrations to reflect the changes in the database. So, run the following commands in your Medusa application's directory:
@@ -3520,7 +3512,7 @@ When you pass pagination configurations to the `graph` method, the returned obje
You return in the response the retrieved brands and the pagination configurations.
Learn more about pagination with Query in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-pagination/index.html.md).
Refer to the [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-pagination/index.html.md) chapter to learn more about applying pagination when retrieving linked records.
***
@@ -3578,7 +3570,7 @@ You apply the `validateAndTransformQuery` middleware on the `GET /admin/brands`
By applying the above middleware, you can pass pagination configurations to `GET /admin/brands`, which will return a paginated list of brands. You'll see how it works when you create the UI route.
Learn more about using the `validateAndTransformQuery` middleware to configure Query in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query#request-query-configurations/index.html.md).
Refer to the [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query#request-query-configurations/index.html.md) chapter to learn more about using the `validateAndTransformQuery` middleware to configure Query.
***
@@ -3612,7 +3604,7 @@ Notice that you use `import.meta.env` to access environment variables in your cu
You can now use the SDK to send requests to the Medusa server.
Learn more about the JS SDK and its options in [this reference](https://docs.medusajs.com/resources/js-sdk/index.html.md).
Refer to the [JS SDK Reference](https://docs.medusajs.com/resources/js-sdk/index.html.md) to learn more about the it, its options, and how to use it to send requests to Medusa's API routes.
***
@@ -3620,7 +3612,7 @@ Learn more about the JS SDK and its options in [this reference](https://docs.med
You'll now add the UI route that shows the paginated list of brands. A UI route is a React component created in a `page.tsx` file under a sub-directory of `src/admin/routes`. The file's path relative to src/admin/routes determines its path in the dashboard.
Learn more about UI routes in [this chapter](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md).
Refer to the [UI Routes](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md) chapter to learn more about UI routes.
So, to add the UI route at the `localhost:9000/app/brands` path, create the file `src/admin/routes/brands/page.tsx` with the following content:
@@ -3866,19 +3858,17 @@ You initialize the SDK passing it the following options:
- `debug`: Whether to enable logging debug messages. This should only be enabled in development.
- `auth.type`: The authentication method used in the client application, which is `session` in the Medusa Admin dashboard.
Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in [this chapter](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md).
Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in the [Admin Environment Variables](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md) chapter.
You can now use the SDK to send requests to the Medusa server.
Learn more about the JS SDK and its options in [this reference](https://docs.medusajs.com/resources/js-sdk/index.html.md).
Refer to the [JS SDK Reference](https://docs.medusajs.com/resources/js-sdk/index.html.md) to learn more about the it, its options, and how to use it to send requests to Medusa's API routes.
***
## 2. Add Widget to Product Details Page
You'll now add a widget to the product-details page. A widget is a React component that's injected into pre-defined zones in the Medusa Admin dashboard. It's created in a `.tsx` file under the `src/admin/widgets` directory.
Learn more about widgets in [this documentation](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md).
You'll now add a widget to the product-details page. A [widget](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md) is a React component that's injected into pre-defined zones in the Medusa Admin dashboard. It's created in a `.tsx` file under the `src/admin/widgets` directory.
To create a widget that shows a product's brand in its details page, create the file `src/admin/widgets/product-brand.tsx` with the following content:
@@ -3990,14 +3980,12 @@ In the next chapter, you'll add a UI route that displays the list of brands in y
In this chapter, you'll learn how to define a module link between a brand defined in the [custom Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md), and a product defined in the [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md) that's available in your Medusa application out-of-the-box.
Modules are [isolated](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md) from other resources, ensuring that they're integrated into the Medusa application without side effects. However, you may need to associate data models of different modules, or you're trying to extend data models from Commerce Modules with custom properties. To do that, you define module links.
Modules are [isolated](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md) from other resources, ensuring that they're integrated into the Medusa application without side effects. However, you may need to build relations between data models of different modules, or you're trying to extend data models from [Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md) with custom properties. To do that, you define module links.
A module link forms an association between two data models of different modules while maintaining module isolation. You can then manage and query linked records of the data models using Medusa's Modules SDK.
A [module link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) forms an association between two data models of different modules while maintaining module isolation. You can then manage and query linked records of the data models using Medusa's Modules SDK.
In this chapter, you'll define a module link between the `Brand` data model of the Brand Module, and the `Product` data model of the Product Module. In later chapters, you'll manage and retrieve linked product and brand records.
Learn more about module links in [this chapters](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md).
### Prerequisites
- [Brand Module having a Brand data model](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md)
@@ -4067,7 +4055,7 @@ So, in this chapter, to extend the create product flow and associate a brand wit
- Consume the [productsCreated](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow#productsCreated/index.html.md) hook of the [createProductsWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow/index.html.md), which is executed within the workflow after the product is created. You'll link the product with the brand passed in the `additional_data` parameter.
- Extend the Create Product API route to allow passing a brand ID in `additional_data`.
To learn more about the `additional_data` property and the API routes that accept additional data, refer to [this chapter](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data/index.html.md).
To learn more about the `additional_data` property and the API routes that accept additional data, refer to the [Additional Data](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data/index.html.md) chapter.
### Prerequisites
@@ -4078,9 +4066,7 @@ To learn more about the `additional_data` property and the API routes that accep
## 1. Consume the productsCreated Hook
A workflow hook is a point in a workflow where you can inject a step to perform a custom functionality. Consuming a workflow hook allows you to extend the features of a workflow and, consequently, the API route that uses it.
Learn more about the workflow hooks in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md).
A [workflow hook](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) is a point in a workflow where you can inject a step to perform a custom functionality. Consuming a workflow hook allows you to extend the features of a workflow and, consequently, the API route that uses it.
The [createProductsWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow/index.html.md) used in the [Create Product API route](https://docs.medusajs.com/api/admin#products_postproducts) has a `productsCreated` hook that runs after the product is created. You'll consume this hook to link the created product with the brand specified in the request parameters.
@@ -4122,9 +4108,7 @@ In the step, if a brand ID is passed in `additional_data`, you resolve the Brand
### Link Brand to Product
Next, you want to create a link between the created products and the brand. To do so, you use Link, which is a class from the Modules SDK that provides methods to manage linked records.
Learn more about Link in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/link/index.html.md).
Next, you want to create a link between the created products and the brand. To do so, you use [Link](https://docs.medusajs.com/learn/fundamentals/module-links/link/index.html.md), which is a class from the Modules SDK that provides methods to manage linked records.
To use Link in the `productsCreated` hook, replace the `TODO` with the following:
@@ -4152,7 +4136,7 @@ logger.info("Linked brand to products")
return new StepResponse(links, links)
```
You resolve Link from the container. Then you loop over the created products to assemble an array of links to be created. After that, you pass the array of links to Link's `create` method, which will link the product and brand records.
You resolve Link from the container. Then, you loop over the created products to assemble an array of links to be created. After that, you pass the array of links to Link's `create` method, which will link the product and brand records.
Each property in the link object is the name of a module, and its value is an object having a `{model_name}_id` property, where `{model_name}` is the snake-case name of the module's data model. Its value is the ID of the record to be linked. The link object's properties must be set in the same order as the link configurations passed to `defineLink`.
@@ -4314,7 +4298,7 @@ For example, send the following request to retrieve the list of products with th
```bash
curl 'http://localhost:9000/admin/products?fields=+brand.*' \
--header 'Authorization: Bearer {token}'
-H 'Authorization: Bearer {token}'
```
Make sure to replace `{token}` with your admin user's authentication token. Learn how to retrieve it in the [API reference](https://docs.medusajs.com/api/store#authentication).
@@ -4341,15 +4325,13 @@ By using the `fields` query parameter, you don't have to re-create existing API
While you can retrieve linked records using the `fields` query parameter of an existing API route, you can't filter by linked records.
Instead, you'll have to create a custom API route that uses Query to retrieve linked records with filters, as explained in the [Query documentation](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records/index.html.md).
Instead, you'll have to create a custom API route that uses [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records/index.html.md) to retrieve linked records with filters.
***
## Approach 2: Use Query to Retrieve Linked Records
You can also retrieve linked records using Query. Query allows you to retrieve data across modules with filters, pagination, and more. You can resolve Query from the Medusa container and use it in your API route or workflow.
Learn more about Query in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md).
You can also retrieve linked records using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). Query allows you to retrieve data across modules with filters, pagination, and more. You can resolve Query from the Medusa container and use it in your API route or workflow.
For example, you can create an API route that retrieves brands and their products. If you followed the [Create Brands API route chapter](https://docs.medusajs.com/learn/customization/custom-features/api-route/index.html.md), you'll have the file `src/api/admin/brands/route.ts` with a `POST` API route. Add a new `GET` function to the same file:
@@ -4434,7 +4416,7 @@ By following the examples of the previous chapters, you:
## Next Steps: Customize Medusa Admin
Clients, such as the Medusa Admin dashboard, can now use brand-related features, such as creating a brand or setting the brand of a product.
Client applications, such as the Medusa Admin dashboard, can now use brand-related features, such as creating a brand or setting the brand of a product.
In the next chapters, you'll learn how to customize the Medusa Admin to show a product's brand on its details page, and to show a new page with the list of brands in your store.
@@ -10792,7 +10774,7 @@ Learn more in the [Override API Routes](https://docs.medusajs.com/learn/fundamen
In this chapter, you'll learn the approach recommended when you need to override an existing API route in Medusa.
## Approaches to Consider Before Overriding API Routes
## Approaches to Consider Instead of Overriding API Routes
While building customizations in your Medusa application, you may need to make changes to existing API routes for your business use case.
@@ -30723,57 +30705,57 @@ The returned `cart` object will look like this:
The cart will include the following total fields:
- `total`: The grand total of the cart, including all line items, shipping methods, taxes, and discounts.
- `subtotal`: The cart's total excluding taxes, including promotions.
- `tax_total`: The total tax amount applied to the cart.
- `discount_total`: The total amount of discounts applied to the cart.
- `discount_subtotal`: The total amount of discounts applied to the cart's subtotal.
- `discount_tax_total`: The total amount of discounts applied to the cart's tax.
- `original_total`: The cart's total including taxes, excluding promotions.
- `original_tax_total`: The cart items' tax total including promotions.
- `item_total`: The cart items' total including taxes and promotions.
- `item_subtotal`: The cart items' total excluding taxes, including promotions.
- `item_tax_total`: The cart items' tax total including promotions.
- `original_item_total`: The cart items' total including taxes, excluding promotions.
- `original_item_subtotal`: The cart items' total excluding taxes, including promotions.
- `original_item_tax_total`: The cart items' tax total excluding promotions.
- `shipping_total`: The cart's shipping total including taxes and promotions.
- `shipping_subtotal`: The cart's shipping total excluding taxes, including promotions.
- `shipping_tax_total`: The total taxes applied to the cart's shipping amount.
- `original_shipping_tax_total`: The total taxes applied to the cart's shipping amount, excluding promotions.
- `original_shipping_subtotal`: The cart's shipping total excluding taxes, including promotions.
- `original_shipping_total`: The cart's shipping total including taxes, excluding promotions.
- `credit_line_subtotal`: The subtotal of the credit line applied to the cart.
- `credit_line_tax_total`: The total tax amount applied to the credit line.
- `credit_line_total`: The total amount of the credit line applied to the cart.
- `total`: The cart's final total after discounts and credit lines, including taxes.
- `subtotal`: The cart's subtotal before discounts, excluding taxes. Calculated as the sum of `item_subtotal` and `shipping_subtotal`.
- `tax_total`: The cart's tax total after discounts. Calculated as the sum of `item_tax_total` and `shipping_tax_total`.
- `discount_total`: The total amount of discounts applied to the cart, including the tax portion of discounts.
- `discount_subtotal`: The total amount of discounts applied to the cart's subtotal (excluding tax portion). Used in the final total calculation.
- `discount_tax_total`: The total amount of discounts applied to the cart's tax. Represents the tax portion of discounts.
- `original_total`: The cart's total before discounts, including taxes. Calculated as the sum of `original_item_total` and `original_shipping_total`.
- `original_tax_total`: The cart's tax total before discounts. Calculated as the sum of `original_item_tax_total` and `original_shipping_tax_total`.
- `item_total`: The sum of all line items' totals after discounts, including taxes.
- `item_subtotal`: The sum of all line items' subtotals before discounts, excluding taxes.
- `item_tax_total`: The sum of all line items' tax totals after discounts.
- `original_item_total`: The sum of all line items' original totals before discounts, including taxes.
- `original_item_subtotal`: The sum of all line items' original subtotals before discounts, excluding taxes.
- `original_item_tax_total`: The sum of all line items' original tax totals before discounts.
- `shipping_total`: The sum of all shipping methods' totals after discounts, including taxes.
- `shipping_subtotal`: The sum of all shipping methods' subtotals before discounts, excluding taxes.
- `shipping_tax_total`: The sum of all shipping methods' tax totals after discounts.
- `original_shipping_tax_total`: The sum of all shipping methods' original tax totals before discounts.
- `original_shipping_subtotal`: The sum of all shipping methods' original subtotals before discounts, excluding taxes.
- `original_shipping_total`: The sum of all shipping methods' original totals before discounts, including taxes.
- `credit_line_subtotal`: The subtotal of credit lines applied to the cart, excluding taxes.
- `credit_line_tax_total`: The tax total of credit lines applied to the cart.
- `credit_line_total`: The total amount of credit lines applied to the cart, including taxes. Subtracted from the final total.
### Cart Line Item Totals
The `items` array in the `cart` object contains total fields for each line item:
- `unit_price`: The price of a single unit of the line item. This field is not calculated and is stored in the database.
- `subtotal`: The total price of the line item before any discounts or taxes.
- `total`: The total price of the line item after applying discounts and taxes.
- `original_total`: The total price of the line item before any discounts.
- `discount_total`: The total amount of discounts applied to the line item.
- `discount_subtotal`: The total amount of discounts applied to the line item's subtotal.
- `discount_tax_total`: The total amount of discounts applied to the line item's tax.
- `tax_total`: The total tax amount applied to the line item.
- `original_tax_total`: The total tax amount applied to the line item before any discounts.
- `subtotal`: The line item's subtotal before discounts, excluding taxes.
- `total`: The line item's total after discounts, including taxes.
- `original_total`: The line item's original total before discounts, including taxes.
- `discount_total`: The total amount of discounts applied to the line item, including the tax portion of discounts.
- `discount_subtotal`: The total amount of discounts applied to the line item's subtotal (excluding tax portion).
- `discount_tax_total`: The total amount of discounts applied to the line item's tax. Represents the tax portion of discounts.
- `tax_total`: The line item's tax total after discounts.
- `original_tax_total`: The line item's original tax total before discounts.
### Cart Shipping Method Totals
The `shipping_methods` array in the `cart` object contains total fields for each shipping method:
- `amount`: The amount charged for the shipping method. This field is not calculated and is stored in the database.
- `subtotal`: The total price of the shipping method before any discounts or taxes.
- `total`: The total price of the shipping method after applying discounts and taxes.
- `original_total`: The total price of the shipping method before any discounts.
- `discount_total`: The total amount of discounts applied to the shipping method.
- `discount_subtotal`: The total amount of discounts applied to the shipping method's subtotal.
- `discount_tax_total`: The total amount of discounts applied to the shipping method's tax.
- `tax_total`: The total tax amount applied to the shipping method.
- `original_tax_total`: The total tax amount applied to the shipping method before any discounts.
- `subtotal`: The shipping method's subtotal before discounts, excluding taxes.
- `total`: The shipping method's total after discounts, including taxes.
- `original_total`: The shipping method's original total before discounts, including taxes.
- `discount_total`: The total amount of discounts applied to the shipping method, including the tax portion of discounts.
- `discount_subtotal`: The total amount of discounts applied to the shipping method's subtotal (excluding tax portion).
- `discount_tax_total`: The total amount of discounts applied to the shipping method's tax. Represents the tax portion of discounts.
- `tax_total`: The shipping method's tax total after discounts.
- `original_tax_total`: The shipping method's original tax total before discounts.
***
@@ -35161,26 +35143,26 @@ The returned `order` object will look like this:
The order will include the following total fields:
- `total`: The grand total of the order, including all line items, shipping methods, taxes, and discounts.
- `subtotal`: The order's total excluding taxes, including promotions.
- `tax_total`: The order's tax total including promotions.
- `original_total`: The order's total including taxes, excluding promotions.
- `original_subtotal`: The order's total excluding taxes, including promotions.
- `original_tax_total`: The order's tax total excluding promotions.
- `discount_total`: The order's discount or promotions total.
- `discount_tax_total`: The tax total of the order's discount or promotion.
- `shipping_total`: The order's shipping total including taxes and promotions.
- `shipping_subtotal`: The order's shipping total excluding taxes, including promotions.
- `shipping_tax_total`: The tax total of the order's shipping.
- `original_shipping_total`: The order's shipping total including taxes, excluding promotions.
- `original_shipping_subtotal`: The order's shipping total excluding taxes, including promotions.
- `original_shipping_tax_total`: The tax total of the order's shipping excluding promotions.
- `item_total`: The total of all line items in the order, including taxes and promotions.
- `item_tax_total`: The tax total of all line items in the order, including promotions.
- `item_subtotal`: The subtotal of all line items in the order, excluding taxes, including promotions.
- `original_item_total`: The total of all line items in the order, including taxes, excluding promotions.
- `original_item_tax_total`: The tax total of all line items in the order, excluding promotions.
- `original_item_subtotal`: The subtotal of all line items in the order, excluding taxes, including promotions.
- `total`: The order's final total after discounts and credit lines, including taxes.
- `subtotal`: The order's subtotal before discounts, excluding taxes. Calculated as the sum of `item_subtotal` and `shipping_subtotal`.
- `tax_total`: The order's tax total after discounts. Calculated as the sum of `item_tax_total` and `shipping_tax_total`.
- `original_total`: The order's total before discounts, including taxes. Calculated as the sum of `original_item_total` and `original_shipping_total`.
- `original_subtotal`: The order's subtotal before discounts, excluding taxes. Calculated as the sum of `original_item_subtotal` and `original_shipping_subtotal`.
- `original_tax_total`: The order's tax total before discounts. Calculated as the sum of `original_item_tax_total` and `original_shipping_tax_total`.
- `discount_total`: The total amount of discounts applied to the order, including the tax portion of discounts.
- `discount_tax_total`: The total amount of discounts applied to the order's tax. Represents the tax portion of discounts.
- `shipping_total`: The sum of all shipping methods' totals after discounts, including taxes.
- `shipping_subtotal`: The sum of all shipping methods' subtotals before discounts, excluding taxes.
- `shipping_tax_total`: The sum of all shipping methods' tax totals after discounts.
- `original_shipping_total`: The sum of all shipping methods' original totals before discounts, including taxes.
- `original_shipping_subtotal`: The sum of all shipping methods' original subtotals before discounts, excluding taxes.
- `original_shipping_tax_total`: The sum of all shipping methods' original tax totals before discounts.
- `item_total`: The sum of all line items' totals after discounts, including taxes.
- `item_tax_total`: The sum of all line items' tax totals after discounts.
- `item_subtotal`: The sum of all line items' subtotals before discounts, excluding taxes.
- `original_item_total`: The sum of all line items' original totals before discounts, including taxes.
- `original_item_tax_total`: The sum of all line items' original tax totals before discounts.
- `original_item_subtotal`: The sum of all line items' original subtotals before discounts, excluding taxes.
- `gift_card_total`: The total amount of gift cards applied to the order.
- `gift_card_tax_total`: The tax total of the gift cards applied to the order.
@@ -35189,14 +35171,14 @@ The order will include the following total fields:
The `items` array in the `order` object contains total fields for each line item:
- `unit_price`: The price of a single unit of the line item. This field is not calculated and is stored in the database.
- `subtotal`: The total price of the line item before any discounts or taxes.
- `total`: The total price of the line item after applying discounts and taxes.
- `original_total`: The total price of the line item before any discounts.
- `discount_total`: The total amount of discounts applied to the line item.
- `discount_subtotal`: The total amount of discounts applied to the line item's subtotal.
- `discount_tax_total`: The total amount of discounts applied to the line item's tax.
- `tax_total`: The total tax amount applied to the line item.
- `original_tax_total`: The total tax amount applied to the line item before any discounts.
- `subtotal`: The line item's subtotal before discounts, excluding taxes.
- `total`: The line item's total after discounts, including taxes.
- `original_total`: The line item's original total before discounts, including taxes.
- `discount_total`: The total amount of discounts applied to the line item, including the tax portion of discounts.
- `discount_subtotal`: The total amount of discounts applied to the line item's subtotal (excluding tax portion).
- `discount_tax_total`: The total amount of discounts applied to the line item's tax. Represents the tax portion of discounts.
- `tax_total`: The line item's tax total after discounts.
- `original_tax_total`: The line item's original tax total before discounts.
- `refundable_total_per_unit`: The total amount that can be refunded per unit of the line item.
- `refundable_total`: The total amount that can be refunded for the line item.
- `fulfilled_total`: The total amount of the line item that has been fulfilled.
@@ -35213,14 +35195,14 @@ The `items` array in the `order` object contains total fields for each line item
The `shipping_methods` array in the `order` object contains total fields for each shipping method:
- `amount`: The amount charged for the shipping method. This field is not calculated and is stored in the database.
- `subtotal`: The total price of the shipping method before any discounts or taxes.
- `total`: The total price of the shipping method after applying discounts and taxes.
- `original_total`: The total price of the shipping method before any discounts.
- `discount_total`: The total amount of discounts applied to the shipping method.
- `discount_subtotal`: The total amount of discounts applied to the shipping method's subtotal.
- `discount_tax_total`: The total amount of discounts applied to the shipping method's tax.
- `tax_total`: The total tax amount applied to the shipping method.
- `original_tax_total`: The total tax amount applied to the shipping method before any discounts.
- `subtotal`: The shipping method's subtotal before discounts, excluding taxes.
- `total`: The shipping method's total after discounts, including taxes.
- `original_total`: The shipping method's original total before discounts, including taxes.
- `discount_total`: The total amount of discounts applied to the shipping method, including the tax portion of discounts.
- `discount_subtotal`: The total amount of discounts applied to the shipping method's subtotal (excluding tax portion).
- `discount_tax_total`: The total amount of discounts applied to the shipping method's tax. Represents the tax portion of discounts.
- `tax_total`: The shipping method's tax total after discounts.
- `original_tax_total`: The shipping method's original tax total before discounts.
### Order Summary Totals
@@ -48862,10 +48844,6 @@ Our Cloud offering automatically provisions a Redis instance and configures the
Add the module into the `modules` property of the exported object in `medusa-config.ts`:
```ts title="medusa-config.ts" highlights={highlights}
import { Modules } from "@medusajs/framework/utils"
// ...
module.exports = defineConfig({
// ...
modules: [
@@ -82212,7 +82190,7 @@ export const retrieveItemsToFulfillStep = createStep(
Then, update the workflow to the following:
```ts title="src/workflows/fulfill-preorder.ts" highlights={fulfillPreorderWorkflowHighlights2}
```ts title="src/workflows/fulfill-preorder.ts"
import { InferTypeOf } from "@medusajs/framework/types"
import { PreorderVariant } from "../modules/preorder/models/preorder-variant"
import { createWorkflow, transform, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
@@ -88047,7 +88025,7 @@ You calculate the total items by summing the quantities of the `filteredItems`,
Finally, in the `return` statement, replace all usages of `cartState.items` with `filteredItems`, and remove the children element of the `DeleteButton` for better styling:
```tsx title="src/modules/layout/components/cart-dropdown/index.tsx" badgeLabel="Storefront" badgeColor="blue" highlights={cartDropdownHighlights}
```tsx title="src/modules/layout/components/cart-dropdown/index.tsx" badgeLabel="Storefront" badgeColor="blue" highlights={[["6"], ["9"], ["21"], ["22"], ["23"], ["24"], ["25"]]}
return (
<div
// ...
@@ -107059,7 +107037,7 @@ This guide was built with Payload v3.54.0. If you're using a different version a
## Summary
By following this tutorial, you'll learn how to:
By following this tutorial, you'll learn how t"o:
- Install and set up Medusa.
- Set up Payload in the Next.js Starter Storefront.
@@ -161173,7 +161151,7 @@ This displays the selected seat number and show date for ticket products instead
You should also remove the quantity selector for ticket products since you can't purchase multiple tickets for the same seat. Remove the following highlighted lines from the `return` statement of the `Item` component:
```tsx title="src/modules/cart/components/item/index.tsx" highlights={removeHighlights}
```tsx title="src/modules/cart/components/item/index.tsx"
{type === "full" && (
<Table.Cell>
<div className="flex gap-2 items-center w-28">