fix(dashboard): Fix broken number input in adjust inventory form (#10416)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/dashboard": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(dashboard): Fix broken number input in adjust inventory form
|
||||||
@@ -3267,6 +3267,27 @@
|
|||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"adjustInventory": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"errors": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"stockedQuantity": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"stockedQuantity"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"errors"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -3300,6 +3321,7 @@
|
|||||||
"editItemDetails",
|
"editItemDetails",
|
||||||
"create",
|
"create",
|
||||||
"reservation",
|
"reservation",
|
||||||
|
"adjustInventory",
|
||||||
"toast"
|
"toast"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -790,6 +790,11 @@
|
|||||||
"quantityOutOfRange": "Minimum quantity is 1 and maximum quantity is {{max}}"
|
"quantityOutOfRange": "Minimum quantity is 1 and maximum quantity is {{max}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"adjustInventory": {
|
||||||
|
"errors": {
|
||||||
|
"stockedQuantity": "Stocked quantity cannot be updated to less than the reserved quantity of {{quantity}}."
|
||||||
|
}
|
||||||
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"updateLocations": "Locations updated successfully.",
|
"updateLocations": "Locations updated successfully.",
|
||||||
"updateLevel": "Inventory level updated successfully.",
|
"updateLevel": "Inventory level updated successfully.",
|
||||||
|
|||||||
+48
-27
@@ -1,15 +1,15 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import * as zod from "zod"
|
|
||||||
|
|
||||||
import { HttpTypes, InventoryLevelDTO, StockLocationDTO } from "@medusajs/types"
|
import { HttpTypes, InventoryLevelDTO, StockLocationDTO } from "@medusajs/types"
|
||||||
import { Button, Input, Text, toast } from "@medusajs/ui"
|
import { Button, Input, Text, toast } from "@medusajs/ui"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../../components/modals"
|
import { useForm, useWatch } from "react-hook-form"
|
||||||
|
|
||||||
import { useForm } from "react-hook-form"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
import { Form } from "../../../../../../components/common/form"
|
import { Form } from "../../../../../../components/common/form"
|
||||||
|
import { RouteDrawer, useRouteModal } from "../../../../../../components/modals"
|
||||||
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateInventoryLevel } from "../../../../../../hooks/api/inventory"
|
import { useUpdateInventoryLevel } from "../../../../../../hooks/api/inventory"
|
||||||
|
import { castNumber } from "../../../../../../lib/cast-number"
|
||||||
|
|
||||||
type AdjustInventoryFormProps = {
|
type AdjustInventoryFormProps = {
|
||||||
item: HttpTypes.AdminInventoryItem
|
item: HttpTypes.AdminInventoryItem
|
||||||
@@ -44,18 +44,52 @@ export const AdjustInventoryForm = ({
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { handleSuccess } = useRouteModal()
|
const { handleSuccess } = useRouteModal()
|
||||||
|
|
||||||
const AdjustInventorySchema = zod.object({
|
const AdjustInventorySchema = z
|
||||||
stocked_quantity: zod.number().min(level.reserved_quantity),
|
.object({
|
||||||
})
|
stocked_quantity: z.union([z.number(), z.string()]),
|
||||||
|
})
|
||||||
|
.superRefine((data, ctx) => {
|
||||||
|
const quantity = data.stocked_quantity
|
||||||
|
? castNumber(data.stocked_quantity)
|
||||||
|
: null
|
||||||
|
|
||||||
const form = useForm<zod.infer<typeof AdjustInventorySchema>>({
|
if (quantity === null) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.invalid_type,
|
||||||
|
expected: "number",
|
||||||
|
received: "undefined",
|
||||||
|
path: ["stocked_quantity"],
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quantity < level.reserved_quantity) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: t("inventory.adjustInventory.errors.stockedQuantity", {
|
||||||
|
quantity: level.reserved_quantity,
|
||||||
|
}),
|
||||||
|
path: ["stocked_quantity"],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const form = useForm<z.infer<typeof AdjustInventorySchema>>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
stocked_quantity: level.stocked_quantity,
|
stocked_quantity: level.stocked_quantity,
|
||||||
},
|
},
|
||||||
resolver: zodResolver(AdjustInventorySchema),
|
resolver: zodResolver(AdjustInventorySchema),
|
||||||
})
|
})
|
||||||
|
|
||||||
const stockedQuantityUpdate = form.watch("stocked_quantity")
|
const stockedQuantityUpdate = useWatch({
|
||||||
|
control: form.control,
|
||||||
|
name: "stocked_quantity",
|
||||||
|
})
|
||||||
|
|
||||||
|
const availableQuantity = stockedQuantityUpdate
|
||||||
|
? castNumber(stockedQuantityUpdate) - level.reserved_quantity
|
||||||
|
: 0 - level.reserved_quantity
|
||||||
|
|
||||||
const { mutateAsync, isPending: isLoading } = useUpdateInventoryLevel(
|
const { mutateAsync, isPending: isLoading } = useUpdateInventoryLevel(
|
||||||
item.id,
|
item.id,
|
||||||
@@ -63,13 +97,9 @@ export const AdjustInventoryForm = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const handleSubmit = form.handleSubmit(async (value) => {
|
const handleSubmit = form.handleSubmit(async (value) => {
|
||||||
if (value.stocked_quantity === level.stocked_quantity) {
|
|
||||||
return handleSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
await mutateAsync(
|
await mutateAsync(
|
||||||
{
|
{
|
||||||
stocked_quantity: value.stocked_quantity,
|
stocked_quantity: castNumber(value.stocked_quantity),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@@ -106,7 +136,7 @@ export const AdjustInventoryForm = ({
|
|||||||
/>
|
/>
|
||||||
<AttributeGridRow
|
<AttributeGridRow
|
||||||
title={t("inventory.available")}
|
title={t("inventory.available")}
|
||||||
value={stockedQuantityUpdate - level.reserved_quantity}
|
value={availableQuantity}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -119,17 +149,8 @@ export const AdjustInventoryForm = ({
|
|||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
min={level.reserved_quantity}
|
value={value}
|
||||||
value={value || ""}
|
onChange={onChange}
|
||||||
onChange={(e) => {
|
|
||||||
const value = e.target.value
|
|
||||||
|
|
||||||
if (value === "") {
|
|
||||||
onChange(null)
|
|
||||||
} else {
|
|
||||||
onChange(parseFloat(value))
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
|
|||||||
Reference in New Issue
Block a user