diff --git a/.changeset/five-crews-rest.md b/.changeset/five-crews-rest.md new file mode 100644 index 0000000000000..3bfafeeb5c5e2 --- /dev/null +++ b/.changeset/five-crews-rest.md @@ -0,0 +1,5 @@ +--- +"@medusajs/dashboard": patch +--- + +fix(dashboard): Add default value to inventory item combobox diff --git a/packages/admin/dashboard/src/hooks/api/products.tsx b/packages/admin/dashboard/src/hooks/api/products.tsx index 7361263d0ede4..edb4a68b38135 100644 --- a/packages/admin/dashboard/src/hooks/api/products.tsx +++ b/packages/admin/dashboard/src/hooks/api/products.tsx @@ -192,12 +192,15 @@ export const useUpdateProductVariantsBatch = ( export const useProductVariantsInventoryItemsBatch = ( productId: string, - options?: UseMutationOptions + options?: UseMutationOptions< + HttpTypes.AdminBatchProductVariantInventoryItemResponse, + FetchError, + HttpTypes.AdminBatchProductVariantInventoryItemRequest + > ) => { return useMutation({ - mutationFn: ( - payload: HttpTypes.AdminBatchProductVariantInventoryItemRequest - ) => sdk.admin.product.batchVariantInventoryItems(productId, payload), + mutationFn: (payload) => + sdk.admin.product.batchVariantInventoryItems(productId, payload), onSuccess: (data: any, variables: any, context: any) => { queryClient.invalidateQueries({ queryKey: variantsQueryKeys.lists() }) queryClient.invalidateQueries({ queryKey: variantsQueryKeys.details() }) diff --git a/packages/admin/dashboard/src/hooks/use-combobox-data.tsx b/packages/admin/dashboard/src/hooks/use-combobox-data.tsx index c11d14d06fa34..159bf0e9e2226 100644 --- a/packages/admin/dashboard/src/hooks/use-combobox-data.tsx +++ b/packages/admin/dashboard/src/hooks/use-combobox-data.tsx @@ -50,6 +50,7 @@ export const useComboboxData = < enabled: !!defaultValue, }) + const { data, ...rest } = useInfiniteQuery({ queryKey: [...queryKey, query], queryFn: async ({ pageParam = 0 }) => { 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 b142f93e9d5b3..a5799a1deeca7 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 @@ -1,6 +1,6 @@ import { zodResolver } from "@hookform/resolvers/zod" import { XMarkMini } from "@medusajs/icons" -import { AdminInventoryItem, AdminProductVariant } from "@medusajs/types" +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" @@ -16,33 +16,43 @@ import { import { KeyboundForm } from "../../../../../components/utilities/keybound-form" import { useProductVariantsInventoryItemsBatch } from "../../../../../hooks/api/products" import { useComboboxData } from "../../../../../hooks/use-combobox-data" +import { castNumber } from "../../../../../lib/cast-number" import { sdk } from "../../../../../lib/client" type ManageVariantInventoryItemsFormProps = { variant: AdminProductVariant & { inventory_items: { - inventory: AdminInventoryItem[] + inventory: HttpTypes.AdminInventoryItem + inventory_item_id: string required_quantity: number - } + }[] } } const ManageVariantInventoryItemsSchema = zod.object({ inventory: zod.array( - zod.object({ - inventory_item_id: zod - .string() - .min(1, i18next.t("products.variant.inventory.validation.itemId")), - required_quantity: zod - .number({ - errorMap: () => ({ + zod + .object({ + inventory_item_id: zod + .string() + .min(1, i18next.t("products.variant.inventory.validation.itemId")), + required_quantity: zod.union([zod.number(), zod.string()]), + }) + .superRefine((data, ctx) => { + const quantity = data.required_quantity + ? castNumber(data.required_quantity) + : 0 + + if (quantity < 1) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, message: i18next.t( "products.variant.inventory.validation.quantity" ), - }), - }) - .min(0, i18next.t("products.variant.inventory.validation.quantity")), - }) + path: ["required_quantity"], + }) + } + }) ), }) @@ -81,18 +91,19 @@ export function ManageVariantInventoryItemsForm({ queryFn: (params) => sdk.admin.inventoryItem.list(params), getOptions: (data) => data.inventory_items.map((item) => ({ - label: item.title, - value: item.id, + label: item.title || item.sku!, + value: item.id!, })), + defaultValue: variant.inventory_items?.[0]?.inventory_item_id, }) const { mutateAsync, isPending } = useProductVariantsInventoryItemsBatch( - variant.product_id + variant?.product_id! ) const handleSubmit = form.handleSubmit(async (values) => { - const existingItems = {} - const selectedItems = {} + const existingItems: Record = {} + const selectedItems: Record = {} variant.inventory_items.forEach( (i) => (existingItems[i.inventory.id] = i.required_quantity) @@ -100,24 +111,24 @@ export function ManageVariantInventoryItemsForm({ values.inventory.forEach((i) => (selectedItems[i.inventory_item_id] = true)) - const payload = { - create: [], - update: [], - delete: [], - } + const payload: HttpTypes.AdminBatchProductVariantInventoryItemRequest = {} values.inventory.forEach((v) => { if (v.inventory_item_id in existingItems) { if (v.required_quantity !== existingItems[v.inventory_item_id]) { + payload.update = payload.update || [] + payload.update.push({ - required_quantity: v.required_quantity, + required_quantity: castNumber(v.required_quantity), inventory_item_id: v.inventory_item_id, variant_id: variant.id, }) } } else { + payload.create = payload.create || [] + payload.create.push({ - required_quantity: v.required_quantity, + required_quantity: castNumber(v.required_quantity), inventory_item_id: v.inventory_item_id, variant_id: variant.id, }) @@ -126,6 +137,8 @@ export function ManageVariantInventoryItemsForm({ variant.inventory_items.forEach((i) => { if (!(i.inventory.id in selectedItems)) { + payload.delete = payload.delete || [] + payload.delete.push({ inventory_item_id: i.inventory.id, variant_id: variant.id, @@ -133,12 +146,6 @@ export function ManageVariantInventoryItemsForm({ } }) - for (const k in payload) { - if (!payload[k].length) { - delete payload[k] - } - } - await mutateAsync(payload, { onSuccess: () => { toast.success(t("products.variant.inventory.toast.itemsManageSuccess")) @@ -268,15 +275,7 @@ export function ManageVariantInventoryItemsForm({ className="bg-ui-bg-field-component" min={0} value={value} - onChange={(e) => { - const value = e.target.value - - if (value === "") { - onChange(null) - } else { - onChange(Number(value)) - } - }} + onChange={onChange} {...field} placeholder={t( "products.create.inventory.quantityPlaceholder"