From 478d1af8d0df0af16baf4f130e19b0be34f5f295 Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Wed, 8 Mar 2023 16:56:49 +0100 Subject: [PATCH] feat(medusa, admin-ui): Improvements to product categories (#3416) --- .changeset/smart-spies-bake.md | 11 ++++++ .../fundamentals/icons/tag-dot-icon/index.tsx | 29 ++++++++++++++++ .../molecules/tooltip-icon/index.tsx | 20 +++++++++++ .../components/product-categories-list.tsx | 23 +++++++------ .../product-category-list-item-details.tsx | 34 +++++++++++++++++-- .../modals/add-product-category.tsx | 7 ++-- .../modals/edit-product-category.tsx | 10 ++++-- .../update-product-category.ts | 5 +++ 8 files changed, 122 insertions(+), 17 deletions(-) create mode 100644 .changeset/smart-spies-bake.md create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/tag-dot-icon/index.tsx create mode 100644 packages/admin-ui/ui/src/components/molecules/tooltip-icon/index.tsx diff --git a/.changeset/smart-spies-bake.md b/.changeset/smart-spies-bake.md new file mode 100644 index 0000000000..4e29d6b64d --- /dev/null +++ b/.changeset/smart-spies-bake.md @@ -0,0 +1,11 @@ +--- +"@medusajs/admin-ui": patch +"@medusajs/medusa": patch +--- + +feat(medusa, admin-ui): Improvements to product categories +- Adds name as required in category create form +- Adds name and handle as required in category edit form +- Updates message on create/update forms +- Adds category indicators for is_internal and is_active fields in the tree list +- Fixes bug where tree is not reset when update fails diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/tag-dot-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/tag-dot-icon/index.tsx new file mode 100644 index 0000000000..ee9b095cb0 --- /dev/null +++ b/packages/admin-ui/ui/src/components/fundamentals/icons/tag-dot-icon/index.tsx @@ -0,0 +1,29 @@ +import React from "react" +import IconProps from "../types/icon-type" + +type TagDotIconProps = IconProps & { + outerColor: string +} + +const TagDotIcon: React.FC = ({ + size = "24px", + color = "#E5484D", + outerColor = "transparent", + ...attributes +}) => { + return ( + + + + + ) +} + +export default TagDotIcon diff --git a/packages/admin-ui/ui/src/components/molecules/tooltip-icon/index.tsx b/packages/admin-ui/ui/src/components/molecules/tooltip-icon/index.tsx new file mode 100644 index 0000000000..740befa7d3 --- /dev/null +++ b/packages/admin-ui/ui/src/components/molecules/tooltip-icon/index.tsx @@ -0,0 +1,20 @@ +import React from "react" +import Tooltip, { TooltipProps } from "../../atoms/tooltip" + +type TooltipIconProps = TooltipProps & { + icon: React.ReactNode +} + +const TooltipIcon: React.FC = ({ + content, + icon, + ...props +}) => { + return ( + + {icon} + + ) +} + +export default TooltipIcon diff --git a/packages/admin-ui/ui/src/domain/product-categories/components/product-categories-list.tsx b/packages/admin-ui/ui/src/domain/product-categories/components/product-categories-list.tsx index 18c513e6e7..18faabc6d5 100644 --- a/packages/admin-ui/ui/src/domain/product-categories/components/product-categories-list.tsx +++ b/packages/admin-ui/ui/src/domain/product-categories/components/product-categories-list.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useMemo, useState } from "react" +import React, { useCallback, useMemo } from "react" import Nestable from "react-nestable" import { dropRight, get, flatMap } from "lodash" @@ -13,6 +13,7 @@ import ProductCategoryListItemDetails from "./product-category-list-item-details import ReorderIcon from "../../../components/fundamentals/icons/reorder-icon" import { useQueryClient } from "@tanstack/react-query" import useNotification from "../../../hooks/use-notification" +import useToggleState from "../../../hooks/use-toggle-state" type ProductCategoriesListProps = { categories: ProductCategory[] @@ -25,8 +26,8 @@ function ProductCategoriesList(props: ProductCategoriesListProps) { const { client } = useMedusa() const queryClient = useQueryClient() const notification = useNotification() - const [isUpdating, setIsUpdating] = useState(false) - + const [isUpdating, enableUpdating, disableUpdating] = useToggleState(false) + const [isError, enableError, disableError] = useToggleState(false) const { categories } = props const onItemDrop = useCallback( @@ -35,7 +36,7 @@ function ProductCategoriesList(props: ProductCategoriesListProps) { items: ProductCategory[] path: number[] }) => { - setIsUpdating(true) + enableUpdating() let parentId = null const { dragItem, items, targetPath } = params const [rank] = targetPath.slice(-1) @@ -53,16 +54,19 @@ function ProductCategoriesList(props: ProductCategoriesListProps) { } try { + disableError() + await client.admin.productCategories.update(dragItem.id, { parent_category_id: parentId, rank, }) - notification("Success", "New order saved", "success") - await queryClient.invalidateQueries(adminProductCategoryKeys.lists()) + notification("Success", "Successfully updated category tree", "success") } catch (e) { - notification("Error", "Failed to save new order", "error") + notification("Error", "Failed to update category tree", "error") + enableError() } finally { - setIsUpdating(false) + await queryClient.invalidateQueries(adminProductCategoryKeys.lists()) + disableUpdating() } }, [] @@ -71,7 +75,6 @@ function ProductCategoriesList(props: ProductCategoriesListProps) { const NestableList = useMemo( () => ( ), - [categories] + [categories, isError] ) return ( diff --git a/packages/admin-ui/ui/src/domain/product-categories/components/product-category-list-item-details.tsx b/packages/admin-ui/ui/src/domain/product-categories/components/product-category-list-item-details.tsx index ff9e7b6995..f836f96296 100644 --- a/packages/admin-ui/ui/src/domain/product-categories/components/product-category-list-item-details.tsx +++ b/packages/admin-ui/ui/src/domain/product-categories/components/product-category-list-item-details.tsx @@ -8,11 +8,14 @@ import { ProductCategoriesContext } from "../pages" import Tooltip from "../../../components/atoms/tooltip" import Button from "../../../components/fundamentals/button" import Actionables from "../../../components/molecules/actionables" +import TooltipIcon from "../../../components/molecules/tooltip-icon" import TrashIcon from "../../../components/fundamentals/icons/trash-icon" import EditIcon from "../../../components/fundamentals/icons/edit-icon" import PlusIcon from "../../../components/fundamentals/icons/plus-icon" import FolderOpenIcon from "../../../components/fundamentals/icons/folder-open-icon" import TagIcon from "../../../components/fundamentals/icons/tag-icon" +import TagDotIcon from "../../../components/fundamentals/icons/tag-dot-icon" +import EyeOffIcon from "../../../components/fundamentals/icons/eye-off-icon" import MoreHorizontalIcon from "../../../components/fundamentals/icons/more-horizontal-icon" import useNotification from "../../../hooks/use-notification" @@ -70,11 +73,11 @@ function ProductCategoryListItemDetails(
{hasChildren && ( -
+
{props.collapseIcon}
)} -
+
{hasChildren && } {!hasChildren && }
@@ -85,6 +88,33 @@ function ProductCategoryListItemDetails( > {item.name} + +
+ {!item.is_active && ( + + } + /> + )} + {item.is_internal && ( + + } + /> + )} +
diff --git a/packages/admin-ui/ui/src/domain/product-categories/modals/add-product-category.tsx b/packages/admin-ui/ui/src/domain/product-categories/modals/add-product-category.tsx index efca73d405..5e0fb658d9 100644 --- a/packages/admin-ui/ui/src/domain/product-categories/modals/add-product-category.tsx +++ b/packages/admin-ui/ui/src/domain/product-categories/modals/add-product-category.tsx @@ -59,9 +59,11 @@ function CreateProductCategory(props: CreateProductCategoryProps) { // TODO: temporary here, investigate why `useAdminCreateProductCategory` doesn't invalidate this await queryClient.invalidateQueries(adminProductCategoryKeys.lists()) closeModal() - notification("Success", "Created a new product category", "success") + notification("Success", "Successfully created a category", "success") } catch (e) { - notification("Error", "Failed to create a new product category", "error") + const errorMessage = + e.response?.data?.message || "Failed to create a new category" + notification("Error", errorMessage, "error") } } @@ -95,6 +97,7 @@ function CreateProductCategory(props: CreateProductCategoryProps) {
{ @@ -98,6 +100,7 @@ function EditProductCategoriesSideModal(