feat(dashboard, medusa, medusa-js, medusa-react, icons): DataGrid, partial Product domain, and ProductVariant hook (#6428)

The PR for the Products section is growing quite large, so I would like to merge this PR that contains a lot of the ground work before moving onto finalizing the rest of the domain.

**Note**
Since the PR contains changes to the core, that the dashboard depends on, the staging env will not work. To preview this PR, you will need to run it locally. 

## `@medusajs/medusa`

**What**
- Adds missing query params to `GET /admin/products/:id/variants`
- `options.values` has been added to the default relations of admin product endpoints.

## `medusa-react`

**What**
- Adds missing hook for `GET /admin/products/:id/variants`

## `@medusajs/dashboard`
- Adds base implementation for `DataGrid` component (formerly `BulkEditor`) (WIP)
- Adds `/products` overview page
- Adds partial `/products/create` page for creating new products (WIP - need to go over design w/ Ludvig before continuing)
- Adds `/products/:id` details page
- Adds `/products/:id/gallery` page for inspecting a products images in fullscreen.
- Adds `/products/:id/edit` page for editing the general information of a product
- Adds `/products/:id/attributes` page for editing the attributes information of a product
- Adds `/products/:id/sales-channels` page for editing which sales channels a product is available in
- Fixes a bug in `DataTable` where a table with two fixed columns would not display correctly

For the review its not important to test the DataGrid, as it is still WIP, and I need to go through some minor changes to the behaviour with Ludvig, as virtualizing it adds some constraints.

## `@medusajs/icons`

**What**
- Pulls latest icons from Figma

## TODO in next PR
- [ ] Fix the typing of POST /admin/products/:id as it is currently not possible to delete any of the nullable fields once they have been added. Be aware of this when reviewing this PR.
- [ ] Wrap up `/products/create` page
- [ ] Add `/products/:id/media` page for managing media associated with the product.
- [ ] Add `/products/id/options` for managing product options (need Ludvig to rethink this as the current API is very limited and we can implement the current design as is.)
- [ ] Add `/products/:id/variants/:id` page for editing a variant. (Possibly concat all of these into one BulkEditor page?)
This commit is contained in:
Kasper Fabricius Kristensen
2024-02-21 11:29:35 +00:00
committed by GitHub
parent c3e30224c7
commit 44d43e8155
131 changed files with 5799 additions and 656 deletions
@@ -1,8 +1,10 @@
import {
AdminGetProductParams,
AdminGetProductsParams,
AdminGetProductsVariantsParams,
AdminProductsListRes,
AdminProductsListTagsRes,
AdminProductsListVariantsRes,
AdminProductsRes,
} from "@medusajs/medusa"
import { Response } from "@medusajs/medusa-js"
@@ -13,24 +15,33 @@ import { queryKeysFactory } from "../../utils/index"
const ADMIN_PRODUCTS_QUERY_KEY = `admin_products` as const
export const adminProductKeys = queryKeysFactory(ADMIN_PRODUCTS_QUERY_KEY)
export const adminProductKeys = {
...queryKeysFactory(ADMIN_PRODUCTS_QUERY_KEY),
detailVariants(id: string, query?: any) {
return [
...this.detail(id),
"variants" as const,
{ ...(query || {}) },
] as const
},
}
type ProductQueryKeys = typeof adminProductKeys
/**
* This hook retrieves a list of products. The products can be filtered by fields such as `q` or `status` passed in
* This hook retrieves a list of products. The products can be filtered by fields such as `q` or `status` passed in
* the `query` parameter. The products can also be sorted or paginated.
*
*
* @example
* To list products:
*
*
* ```tsx
* import React from "react"
* import { useAdminProducts } from "medusa-react"
*
*
* const Products = () => {
* const { products, isLoading } = useAdminProducts()
*
*
* return (
* <div>
* {isLoading && <span>Loading...</span>}
@@ -45,21 +56,21 @@ type ProductQueryKeys = typeof adminProductKeys
* </div>
* )
* }
*
*
* export default Products
* ```
*
*
* To specify relations that should be retrieved within the products:
*
*
* ```tsx
* import React from "react"
* import { useAdminProducts } from "medusa-react"
*
*
* const Products = () => {
* const { products, isLoading } = useAdminProducts({
* expand: "images"
* })
*
*
* return (
* <div>
* {isLoading && <span>Loading...</span>}
@@ -74,19 +85,19 @@ type ProductQueryKeys = typeof adminProductKeys
* </div>
* )
* }
*
*
* export default Products
* ```
*
*
* By default, only the first `50` records are retrieved. You can control pagination by specifying the `limit` and `offset` properties:
*
*
* ```tsx
* import React from "react"
* import { useAdminProducts } from "medusa-react"
*
*
* const Products = () => {
* const {
* products,
* const {
* products,
* limit,
* offset,
* isLoading
@@ -95,7 +106,7 @@ type ProductQueryKeys = typeof adminProductKeys
* limit: 20,
* offset: 0
* })
*
*
* return (
* <div>
* {isLoading && <span>Loading...</span>}
@@ -110,10 +121,10 @@ type ProductQueryKeys = typeof adminProductKeys
* </div>
* )
* }
*
*
* export default Products
* ```
*
*
* @customNamespace Hooks.Admin.Products
* @category Queries
*/
@@ -139,32 +150,32 @@ export const useAdminProducts = (
/**
* This hook retrieves a product's details.
*
*
* @example
* import React from "react"
* import { useAdminProduct } from "medusa-react"
*
*
* type Props = {
* productId: string
* }
*
*
* const Product = ({ productId }: Props) => {
* const {
* product,
* isLoading,
* const {
* product,
* isLoading,
* } = useAdminProduct(productId)
*
*
* return (
* <div>
* {isLoading && <span>Loading...</span>}
* {product && <span>{product.title}</span>}
*
*
* </div>
* )
* }
*
*
* export default Product
*
*
* @customNamespace Hooks.Admin.Products
* @category Queries
*/
@@ -192,16 +203,40 @@ export const useAdminProduct = (
return { ...data, ...rest } as const
}
export const useAdminProductVariants = (
/**
* The product's ID.
*/
id: string,
/**
* Configurations to apply on the retrieved product variants.
*/
query?: AdminGetProductsVariantsParams,
options?: UseQueryOptionsWrapper<
Response<AdminProductsListVariantsRes>,
Error,
ReturnType<ProductQueryKeys["detailVariants"]>
>
) => {
const { client } = useMedusa()
const { data, ...rest } = useQuery(
adminProductKeys.detailVariants(id, query),
() => client.admin.products.listVariants(id, query),
options
)
return { ...data, ...rest } as const
}
/**
* This hook retrieves a list of Product Tags with how many times each is used in products.
*
*
* @example
* import React from "react"
* import { useAdminProductTagUsage } from "medusa-react"
*
*
* const ProductTags = (productId: string) => {
* const { tags, isLoading } = useAdminProductTagUsage()
*
*
* return (
* <div>
* {isLoading && <span>Loading...</span>}
@@ -216,9 +251,9 @@ export const useAdminProduct = (
* </div>
* )
* }
*
*
* export default ProductTags
*
*
* @customNamespace Hooks.Admin.Products
* @category Queries
*/