fix(dashboard): Add default value to inventory item combobox (#10412)

**What**
- Resolves CMRC-761
- Fixes TS errors in the same file.

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Kasper Fabricius Kristensen
2024-12-03 18:03:54 +00:00
committed by GitHub
co-authored by Oli Juhl
parent 18583ed567
commit e8f4f7ea2b
4 changed files with 53 additions and 45 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---
fix(dashboard): Add default value to inventory item combobox
@@ -192,12 +192,15 @@ export const useUpdateProductVariantsBatch = (
export const useProductVariantsInventoryItemsBatch = ( export const useProductVariantsInventoryItemsBatch = (
productId: string, productId: string,
options?: UseMutationOptions<any, FetchError, any> options?: UseMutationOptions<
HttpTypes.AdminBatchProductVariantInventoryItemResponse,
FetchError,
HttpTypes.AdminBatchProductVariantInventoryItemRequest
>
) => { ) => {
return useMutation({ return useMutation({
mutationFn: ( mutationFn: (payload) =>
payload: HttpTypes.AdminBatchProductVariantInventoryItemRequest sdk.admin.product.batchVariantInventoryItems(productId, payload),
) => sdk.admin.product.batchVariantInventoryItems(productId, payload),
onSuccess: (data: any, variables: any, context: any) => { onSuccess: (data: any, variables: any, context: any) => {
queryClient.invalidateQueries({ queryKey: variantsQueryKeys.lists() }) queryClient.invalidateQueries({ queryKey: variantsQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: variantsQueryKeys.details() }) queryClient.invalidateQueries({ queryKey: variantsQueryKeys.details() })
@@ -50,6 +50,7 @@ export const useComboboxData = <
enabled: !!defaultValue, enabled: !!defaultValue,
}) })
const { data, ...rest } = useInfiniteQuery({ const { data, ...rest } = useInfiniteQuery({
queryKey: [...queryKey, query], queryKey: [...queryKey, query],
queryFn: async ({ pageParam = 0 }) => { queryFn: async ({ pageParam = 0 }) => {
@@ -1,6 +1,6 @@
import { zodResolver } from "@hookform/resolvers/zod" import { zodResolver } from "@hookform/resolvers/zod"
import { XMarkMini } from "@medusajs/icons" 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 { Button, Heading, IconButton, Input, Label, toast } from "@medusajs/ui"
import i18next from "i18next" import i18next from "i18next"
import { useFieldArray, useForm } from "react-hook-form" import { useFieldArray, useForm } from "react-hook-form"
@@ -16,33 +16,43 @@ import {
import { KeyboundForm } from "../../../../../components/utilities/keybound-form" import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
import { useProductVariantsInventoryItemsBatch } from "../../../../../hooks/api/products" import { useProductVariantsInventoryItemsBatch } from "../../../../../hooks/api/products"
import { useComboboxData } from "../../../../../hooks/use-combobox-data" import { useComboboxData } from "../../../../../hooks/use-combobox-data"
import { castNumber } from "../../../../../lib/cast-number"
import { sdk } from "../../../../../lib/client" import { sdk } from "../../../../../lib/client"
type ManageVariantInventoryItemsFormProps = { type ManageVariantInventoryItemsFormProps = {
variant: AdminProductVariant & { variant: AdminProductVariant & {
inventory_items: { inventory_items: {
inventory: AdminInventoryItem[] inventory: HttpTypes.AdminInventoryItem
inventory_item_id: string
required_quantity: number required_quantity: number
} }[]
} }
} }
const ManageVariantInventoryItemsSchema = zod.object({ const ManageVariantInventoryItemsSchema = zod.object({
inventory: zod.array( inventory: zod.array(
zod.object({ zod
inventory_item_id: zod .object({
.string() inventory_item_id: zod
.min(1, i18next.t("products.variant.inventory.validation.itemId")), .string()
required_quantity: zod .min(1, i18next.t("products.variant.inventory.validation.itemId")),
.number({ required_quantity: zod.union([zod.number(), zod.string()]),
errorMap: () => ({ })
.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( message: i18next.t(
"products.variant.inventory.validation.quantity" "products.variant.inventory.validation.quantity"
), ),
}), path: ["required_quantity"],
}) })
.min(0, i18next.t("products.variant.inventory.validation.quantity")), }
}) })
), ),
}) })
@@ -81,18 +91,19 @@ export function ManageVariantInventoryItemsForm({
queryFn: (params) => sdk.admin.inventoryItem.list(params), queryFn: (params) => sdk.admin.inventoryItem.list(params),
getOptions: (data) => getOptions: (data) =>
data.inventory_items.map((item) => ({ data.inventory_items.map((item) => ({
label: item.title, label: item.title || item.sku!,
value: item.id, value: item.id!,
})), })),
defaultValue: variant.inventory_items?.[0]?.inventory_item_id,
}) })
const { mutateAsync, isPending } = useProductVariantsInventoryItemsBatch( const { mutateAsync, isPending } = useProductVariantsInventoryItemsBatch(
variant.product_id variant?.product_id!
) )
const handleSubmit = form.handleSubmit(async (values) => { const handleSubmit = form.handleSubmit(async (values) => {
const existingItems = {} const existingItems: Record<string, number> = {}
const selectedItems = {} const selectedItems: Record<string, boolean> = {}
variant.inventory_items.forEach( variant.inventory_items.forEach(
(i) => (existingItems[i.inventory.id] = i.required_quantity) (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)) values.inventory.forEach((i) => (selectedItems[i.inventory_item_id] = true))
const payload = { const payload: HttpTypes.AdminBatchProductVariantInventoryItemRequest = {}
create: [],
update: [],
delete: [],
}
values.inventory.forEach((v) => { values.inventory.forEach((v) => {
if (v.inventory_item_id in existingItems) { if (v.inventory_item_id in existingItems) {
if (v.required_quantity !== existingItems[v.inventory_item_id]) { if (v.required_quantity !== existingItems[v.inventory_item_id]) {
payload.update = payload.update || []
payload.update.push({ payload.update.push({
required_quantity: v.required_quantity, required_quantity: castNumber(v.required_quantity),
inventory_item_id: v.inventory_item_id, inventory_item_id: v.inventory_item_id,
variant_id: variant.id, variant_id: variant.id,
}) })
} }
} else { } else {
payload.create = payload.create || []
payload.create.push({ payload.create.push({
required_quantity: v.required_quantity, required_quantity: castNumber(v.required_quantity),
inventory_item_id: v.inventory_item_id, inventory_item_id: v.inventory_item_id,
variant_id: variant.id, variant_id: variant.id,
}) })
@@ -126,6 +137,8 @@ export function ManageVariantInventoryItemsForm({
variant.inventory_items.forEach((i) => { variant.inventory_items.forEach((i) => {
if (!(i.inventory.id in selectedItems)) { if (!(i.inventory.id in selectedItems)) {
payload.delete = payload.delete || []
payload.delete.push({ payload.delete.push({
inventory_item_id: i.inventory.id, inventory_item_id: i.inventory.id,
variant_id: variant.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, { await mutateAsync(payload, {
onSuccess: () => { onSuccess: () => {
toast.success(t("products.variant.inventory.toast.itemsManageSuccess")) toast.success(t("products.variant.inventory.toast.itemsManageSuccess"))
@@ -268,15 +275,7 @@ export function ManageVariantInventoryItemsForm({
className="bg-ui-bg-field-component" className="bg-ui-bg-field-component"
min={0} min={0}
value={value} value={value}
onChange={(e) => { onChange={onChange}
const value = e.target.value
if (value === "") {
onChange(null)
} else {
onChange(Number(value))
}
}}
{...field} {...field}
placeholder={t( placeholder={t(
"products.create.inventory.quantityPlaceholder" "products.create.inventory.quantityPlaceholder"