diff --git a/.changeset/large-clocks-decide.md b/.changeset/large-clocks-decide.md new file mode 100644 index 0000000000..09a5a91f50 --- /dev/null +++ b/.changeset/large-clocks-decide.md @@ -0,0 +1,5 @@ +--- +"@medusajs/dashboard": patch +--- + +fix(dashboard): inventory kit combobox state diff --git a/packages/admin/dashboard/src/hooks/use-combobox-data.tsx b/packages/admin/dashboard/src/hooks/use-combobox-data.tsx index 46e45f8cc0..02e839b682 100644 --- a/packages/admin/dashboard/src/hooks/use-combobox-data.tsx +++ b/packages/admin/dashboard/src/hooks/use-combobox-data.tsx @@ -13,6 +13,7 @@ type ComboboxExternalData = { } type ComboboxQueryParams = { + id?: string q?: string offset?: number limit?: number diff --git a/packages/admin/dashboard/src/routes/product-variants/product-variant-manage-inventory-items/components/manage-variant-inventory-items-form/manage-variant-inventory-items-form.tsx b/packages/admin/dashboard/src/routes/product-variants/product-variant-manage-inventory-items/components/manage-variant-inventory-items-form/manage-variant-inventory-items-form.tsx index e768d6ef00..b7844f5dfa 100644 --- a/packages/admin/dashboard/src/routes/product-variants/product-variant-manage-inventory-items/components/manage-variant-inventory-items-form/manage-variant-inventory-items-form.tsx +++ b/packages/admin/dashboard/src/routes/product-variants/product-variant-manage-inventory-items/components/manage-variant-inventory-items-form/manage-variant-inventory-items-form.tsx @@ -3,7 +3,7 @@ import { XMarkMini } from "@medusajs/icons" import { AdminProductVariant, HttpTypes } from "@medusajs/types" import { Button, Heading, IconButton, Input, Label, toast } from "@medusajs/ui" import i18next from "i18next" -import { useFieldArray, useForm } from "react-hook-form" +import { useFieldArray, useForm, UseFormReturn } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" @@ -56,6 +56,130 @@ const ManageVariantInventoryItemsSchema = zod.object({ ), }) +type InventoryItemFormData = zod.infer< + typeof ManageVariantInventoryItemsSchema +>["inventory"] + +type VariantInventoryItemRowProps = { + form: UseFormReturn + inventoryIndex: number + inventoryItem: { + id: string + inventory_item_id: string + required_quantity: number + } + onRemove: () => void +} + +function VariantInventoryItemRow({ + form, + inventoryIndex, + inventoryItem, + onRemove, +}: VariantInventoryItemRowProps) { + const { t } = useTranslation() + + const items = useComboboxData({ + queryKey: ["inventory_items"], + defaultValueKey: "id", + defaultValue: inventoryItem.inventory_item_id, + queryFn: (params) => sdk.admin.inventoryItem.list(params), + getOptions: (data) => + data.inventory_items.map((item) => ({ + label: `${item.title} ${item.sku ? `(${item.sku})` : ""}`, + value: item.id!, + })), + }) + + return ( +
  • +
    +
    + +
    + + { + return ( + + + items.onSearchValueChange("")} + fetchNextPage={items.fetchNextPage} + className="bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover" + placeholder={t("products.create.inventory.itemPlaceholder")} + /> + + + + ) + }} + /> + +
    + +
    + { + return ( + + + + + + + ) + }} + /> +
    + + + +
  • + ) +} + export function ManageVariantInventoryItemsForm({ variant, }: ManageVariantInventoryItemsFormProps) { @@ -86,17 +210,6 @@ export function ManageVariantInventoryItemsForm({ const hasKit = inventory.fields.length > 1 - const items = useComboboxData({ - queryKey: ["inventory_items"], - queryFn: (params) => sdk.admin.inventoryItem.list(params), - getOptions: (data) => - data.inventory_items.map((item) => ({ - label: `${item.title} ${item.sku ? `(${item.sku})` : ""}`, - value: item.id!, - })), - defaultValue: variant.inventory_items?.[0]?.inventory_item_id, - }) - const { mutateAsync, isPending } = useProductVariantsInventoryItemsBatch( variant?.product_id! ) @@ -212,92 +325,13 @@ export function ManageVariantInventoryItemsForm({ {inventory.fields.map((inventoryItem, inventoryIndex) => ( -
  • -
    -
    - -
    - - { - return ( - - - - - - - ) - }} - /> - -
    - -
    - { - return ( - - - - - - - ) - }} - /> -
    - inventory.remove(inventoryIndex)} - > - - -
  • + form={form} + inventoryIndex={inventoryIndex} + inventoryItem={inventoryItem} + onRemove={() => inventory.remove(inventoryIndex)} + /> ))} diff --git a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-inventory-kit-form/components/product-create-inventory-kit-section/product-create-inventory-kit-section.tsx b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-inventory-kit-form/components/product-create-inventory-kit-section/product-create-inventory-kit-section.tsx index dfb20324fe..5b7206c958 100644 --- a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-inventory-kit-form/components/product-create-inventory-kit-section/product-create-inventory-kit-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-inventory-kit-form/components/product-create-inventory-kit-section/product-create-inventory-kit-section.tsx @@ -9,6 +9,139 @@ import { Combobox } from "../../../../../../../components/inputs/combobox" import { useComboboxData } from "../../../../../../../hooks/use-combobox-data" import { sdk } from "../../../../../../../lib/client" +type InventoryItemRowProps = { + form: UseFormReturn + variantIndex: number + inventoryIndex: number + inventoryItem: any + isItemOptionDisabled: ( + option: { value: string }, + inventoryIndex: number + ) => boolean + onRemove: () => void +} + +function InventoryItemRow({ + form, + variantIndex, + inventoryIndex, + inventoryItem, + isItemOptionDisabled, + onRemove, +}: InventoryItemRowProps) { + const { t } = useTranslation() + + const items = useComboboxData({ + queryKey: ["inventory_items"], + defaultValueKey: "id", + defaultValue: inventoryItem.inventory_item_id, // prefetch existing inventory items + queryFn: (params) => sdk.admin.inventoryItem.list(params), + getOptions: (data) => + data.inventory_items.map((item) => ({ + label: `${item.title} ${item.sku ? `(${item.sku})` : ""}`, + value: item.id, + })), + }) + + return ( +
  • +
    +
    + +
    + + { + return ( + + + ({ + ...o, + disabled: isItemOptionDisabled(o, inventoryIndex), + }))} + searchValue={items.searchValue} + onBlur={() => items.onSearchValueChange("")} + onSearchValueChange={items.onSearchValueChange} + fetchNextPage={items.fetchNextPage} + className="bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover" + placeholder={t("products.create.inventory.itemPlaceholder")} + /> + + + ) + }} + /> + +
    + +
    + { + return ( + + + { + const value = e.target.value + + if (value === "") { + onChange(null) + } else { + onChange(Number(value)) + } + }} + {...field} + placeholder={t( + "products.create.inventory.quantityPlaceholder" + )} + /> + + + + ) + }} + /> +
    + + + +
  • + ) +} + type VariantSectionProps = { form: UseFormReturn variant: ProductCreateSchemaType["variants"][0] @@ -28,26 +161,14 @@ function VariantSection({ form, variant, index }: VariantSectionProps) { name: `variants.${index}.inventory`, }) - const items = useComboboxData({ - queryKey: ["inventory_items"], - queryFn: (params) => sdk.admin.inventoryItem.list(params), - getOptions: (data) => - data.inventory_items.map((item) => ({ - label: `${item.title} ${item.sku ? `(${item.sku})` : ""}`, - value: item.id, - })), - }) - /** * Will mark an option as disabled if another input already selected that option - * @param option - * @param inventoryIndex */ const isItemOptionDisabled = ( - option: (typeof items.options)[0], + option: { value: string }, inventoryIndex: number ) => { - return inventoryFormData?.some( + return !!inventoryFormData?.some( (i, index) => index != inventoryIndex && i.inventory_item_id === option.value ) @@ -75,102 +196,15 @@ function VariantSection({ form, variant, index }: VariantSectionProps) { {inventory.fields.map((inventoryItem, inventoryIndex) => ( -
  • -
    -
    - -
    - - { - return ( - - - ({ - ...o, - disabled: isItemOptionDisabled(o, inventoryIndex), - }))} - searchValue={items.searchValue} - onSearchValueChange={items.onSearchValueChange} - fetchNextPage={items.fetchNextPage} - className="bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover" - placeholder={t( - "products.create.inventory.itemPlaceholder" - )} - /> - - - ) - }} - /> - -
    - -
    - { - return ( - - - { - const value = e.target.value - - if (value === "") { - onChange(null) - } else { - onChange(Number(value)) - } - }} - {...field} - placeholder={t( - "products.create.inventory.quantityPlaceholder" - )} - /> - - - - ) - }} - /> -
    - inventory.remove(inventoryIndex)} - > - - -
  • + form={form} + variantIndex={index} + inventoryIndex={inventoryIndex} + inventoryItem={inventoryItem} + isItemOptionDisabled={isItemOptionDisabled} + onRemove={() => inventory.remove(inventoryIndex)} + /> ))} )