fix(admin-ui): Edit allocation update (#3447)
**What** - update the edit-allocation side-bar with the new table layout Fixes CORE-1215
This commit is contained in:
1 parent
ad7d7fcd51
commit
c16f387d1c
2 files changed
+109
-18
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/admin-ui": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(admin-ui): update edit-allocation sidebar
|
||||||
+104
-18
@@ -1,13 +1,11 @@
|
|||||||
import {
|
import { AllocationLineItemForm } from "./allocate-items-modal"
|
||||||
AllocationLineItem,
|
|
||||||
AllocationLineItemForm,
|
|
||||||
} from "./allocate-items-modal"
|
|
||||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||||
import { LineItem, ReservationItemDTO } from "@medusajs/medusa"
|
import { LineItem, ReservationItemDTO } from "@medusajs/medusa"
|
||||||
import {
|
import {
|
||||||
useAdminDeleteReservation,
|
useAdminDeleteReservation,
|
||||||
useAdminStockLocations,
|
useAdminStockLocations,
|
||||||
useAdminUpdateReservation,
|
useAdminUpdateReservation,
|
||||||
|
useAdminVariantsInventory,
|
||||||
} from "medusa-react"
|
} from "medusa-react"
|
||||||
import { useEffect, useMemo } from "react"
|
import { useEffect, useMemo } from "react"
|
||||||
|
|
||||||
@@ -15,8 +13,9 @@ import Button from "../../../../components/fundamentals/button"
|
|||||||
import CrossIcon from "../../../../components/fundamentals/icons/cross-icon"
|
import CrossIcon from "../../../../components/fundamentals/icons/cross-icon"
|
||||||
import Select from "../../../../components/molecules/select/next-select/select"
|
import Select from "../../../../components/molecules/select/next-select/select"
|
||||||
import SideModal from "../../../../components/molecules/modal/side-modal"
|
import SideModal from "../../../../components/molecules/modal/side-modal"
|
||||||
import { nestedForm } from "../../../../utils/nested-form"
|
|
||||||
import useNotification from "../../../../hooks/use-notification"
|
import useNotification from "../../../../hooks/use-notification"
|
||||||
|
import Thumbnail from "../../../../components/atoms/thumbnail"
|
||||||
|
import { getFulfillableQuantity } from "../create-fulfillment/item-table"
|
||||||
|
|
||||||
type EditAllocationLineItemForm = {
|
type EditAllocationLineItemForm = {
|
||||||
location: { label: string; value: string }
|
location: { label: string; value: string }
|
||||||
@@ -48,6 +47,10 @@ const EditAllocationDrawer = ({
|
|||||||
|
|
||||||
const { stock_locations } = useAdminStockLocations(stockLocationsFilter)
|
const { stock_locations } = useAdminStockLocations(stockLocationsFilter)
|
||||||
|
|
||||||
|
const { variant, isLoading } = useAdminVariantsInventory(
|
||||||
|
item.variant_id as string
|
||||||
|
)
|
||||||
|
|
||||||
const { mutate: updateReservation } = useAdminUpdateReservation(
|
const { mutate: updateReservation } = useAdminUpdateReservation(
|
||||||
reservation?.id || ""
|
reservation?.id || ""
|
||||||
)
|
)
|
||||||
@@ -126,6 +129,36 @@ const EditAllocationDrawer = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { availableQuantity, inStockQuantity } = useMemo(() => {
|
||||||
|
if (isLoading || !selectedLocation?.value || !variant) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
const { inventory } = variant
|
||||||
|
const locationInventory = inventory[0].location_levels?.find(
|
||||||
|
(inv) => inv.location_id === selectedLocation?.value
|
||||||
|
)
|
||||||
|
if (!locationInventory) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
availableQuantity: locationInventory.available_quantity,
|
||||||
|
inStockQuantity: locationInventory.stocked_quantity,
|
||||||
|
}
|
||||||
|
}, [variant, selectedLocation, isLoading])
|
||||||
|
|
||||||
|
// we can adjust up to fulfillable quantity - the quantity reserved in other reservations
|
||||||
|
const lineItemReservationCapacity =
|
||||||
|
getFulfillableQuantity(item) -
|
||||||
|
(totalReservedQuantity - (reservation?.quantity || 0))
|
||||||
|
|
||||||
|
const inventoryItemReservationCapacity =
|
||||||
|
typeof availableQuantity === "number" ? availableQuantity : 0
|
||||||
|
|
||||||
|
const maxReservation = Math.min(
|
||||||
|
lineItemReservationCapacity,
|
||||||
|
inventoryItemReservationCapacity
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SideModal isVisible close={close}>
|
<SideModal isVisible close={close}>
|
||||||
<form
|
<form
|
||||||
@@ -133,14 +166,14 @@ const EditAllocationDrawer = ({
|
|||||||
onSubmit={handleSubmit(submit)}
|
onSubmit={handleSubmit(submit)}
|
||||||
>
|
>
|
||||||
<div className="flex h-full flex-col justify-between">
|
<div className="flex h-full flex-col justify-between">
|
||||||
<div>
|
<div className="flex grow flex-col">
|
||||||
<div className="border-grey-20 flex items-center justify-between border-b px-8 py-6">
|
<div className="border-grey-20 flex items-center justify-between border-b px-8 py-6">
|
||||||
<h1 className="inter-large-semibold ">Edit allocation</h1>
|
<h1 className="inter-large-semibold ">Edit allocation</h1>
|
||||||
<Button variant="ghost" className="p-1.5" onClick={close}>
|
<Button variant="ghost" className="p-1.5" onClick={close}>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-y-8 px-8 pt-6">
|
<div className="flex h-full flex-col justify-between gap-y-8 px-8 pb-8 pt-6">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="inter-base-semibold">Location</h2>
|
<h2 className="inter-base-semibold">Location</h2>
|
||||||
<span className="inter-base-regular text-grey-50">
|
<span className="inter-base-regular text-grey-50">
|
||||||
@@ -152,28 +185,81 @@ const EditAllocationDrawer = ({
|
|||||||
rules={{ required: true }}
|
rules={{ required: true }}
|
||||||
render={({ field: { value, onChange } }) => (
|
render={({ field: { value, onChange } }) => (
|
||||||
<Select
|
<Select
|
||||||
|
className="mt-4"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
options={locationOptions}
|
options={locationOptions}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 className="inter-base-semibold">Items to Allocate</h2>
|
<h2 className="inter-base-semibold mt-8">
|
||||||
|
Items to Allocate
|
||||||
|
</h2>
|
||||||
<span className="inter-base-regular text-grey-50">
|
<span className="inter-base-regular text-grey-50">
|
||||||
Select the number of items that you wish to allocate.
|
Select the number of items that you wish to allocate.
|
||||||
</span>
|
</span>
|
||||||
<AllocationLineItem
|
<div className="gap-x-base mt-6 flex w-full">
|
||||||
form={nestedForm(form, `item` as "item")}
|
<div className="min-w-9">
|
||||||
item={item}
|
<Thumbnail size="medium" src={item.thumbnail} />
|
||||||
compact
|
|
||||||
locationId={selectedLocation?.value}
|
|
||||||
reservedQuantity={
|
|
||||||
totalReservedQuantity - (reservation?.quantity || 0)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-grey-50 truncate">
|
||||||
|
<p className="inter-base-semibold text-grey-90 truncate">
|
||||||
|
{item.title}
|
||||||
|
</p>
|
||||||
|
<p className="inter-base-semibold gap-x-2xsmall flex">
|
||||||
|
<p>{`(${item.variant.sku})`}</p>
|
||||||
|
<span>·</span>
|
||||||
|
<span className="inter-base-regular gap-x-2xsmall flex">
|
||||||
|
{item.variant.options
|
||||||
|
?.map((option, i) => [
|
||||||
|
<span key={`${option.id}-${i}`}>
|
||||||
|
{option.value}
|
||||||
|
</span>,
|
||||||
|
<span key={`${option.id}-${i}.dot`}>·</span>,
|
||||||
|
])
|
||||||
|
.flat()
|
||||||
|
.slice(0, -1) ||
|
||||||
|
item.variant.title ||
|
||||||
|
"-"}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={`
|
||||||
|
bg-grey-5 text-grey-50 border-grey-20
|
||||||
|
mt-8
|
||||||
|
grid border-collapse grid-cols-2 grid-rows-3
|
||||||
|
[&>*]:border-r [&>*]:border-b [&>*]:py-2
|
||||||
|
[&>*:nth-child(odd)]:border-l [&>*:nth-child(odd)]:pl-4
|
||||||
|
[&>*:nth-child(even)]:pr-4 [&>*:nth-child(even)]:text-right
|
||||||
|
[&>*:nth-child(-n+2)]:border-t`}
|
||||||
|
>
|
||||||
|
<div className="rounded-tl-rounded">In stock</div>
|
||||||
|
<div className="rounded-tr-rounded">
|
||||||
|
{inStockQuantity ?? "N/A"}
|
||||||
|
</div>
|
||||||
|
<div className="">Available</div>
|
||||||
|
<div className="">{availableQuantity ?? "N/A"}</div>
|
||||||
|
<div className="rounded-bl-rounded">Allocate</div>
|
||||||
|
<div className="bg-grey-0 rounded-br-rounded text-grey-80 flex items-center">
|
||||||
|
<input
|
||||||
|
className="remove-number-spinner inter-base-regular w-full shrink border-none bg-transparent text-right font-normal outline-none outline-0"
|
||||||
|
{...form.register("item.quantity", {
|
||||||
|
valueAsNumber: true,
|
||||||
|
})}
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
max={maxReservation}
|
||||||
|
/>
|
||||||
|
<span className="text-grey-50 nowrap whitespace-nowrap pl-2">{` / ${maxReservation} requested`}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="my-1 w-full border text-rose-50"
|
className="my-1 w-full border text-rose-50"
|
||||||
|
|||||||
Reference in new issue
Block a user