feat(admin-ui, medusa-js, medusa-react, medusa): Multiwarehousing UI (#3403)

* add "get-variant" endpoint

* import from a different place

* fix unit test

* add changeset

* inventory management for orders

* add changeset

* initial create-fulfillment

* add changeset

* type oas and admin

* Move inv. creation and listing from admin repo

* Fix location editing bug (CORE-1216)

* Fix default warehouse on inventory table view

* remove actions from each table line

* Use feature flag hook instead of context directly

* remove manage inventory action if inventory management is not enabled

* Address review comments

* fix queries made when inventorymodules are disabled

* variant form changes for feature enabled

* move exclamation icon into warning icon

* ensure queries are not run unless feature is enabled for create-fulfillment

---------

Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com>
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
This commit is contained in:
Rares Stefan
2023-03-08 16:08:56 +01:00
committed by GitHub
parent 53eda215e0
commit 57d7728dd9
49 changed files with 3922 additions and 722 deletions

View File

@@ -1,4 +1,4 @@
import clsx from "clsx"
import InputHeader, { InputHeaderProps } from "../../fundamentals/input-header"
import React, {
ChangeEventHandler,
FocusEventHandler,
@@ -6,10 +6,11 @@ import React, {
useImperativeHandle,
useRef,
} from "react"
import InputError from "../../atoms/input-error"
import MinusIcon from "../../fundamentals/icons/minus-icon"
import PlusIcon from "../../fundamentals/icons/plus-icon"
import InputHeader, { InputHeaderProps } from "../../fundamentals/input-header"
import clsx from "clsx"
export type InputProps = Omit<React.ComponentPropsWithRef<"input">, "prefix"> &
InputHeaderProps & {
@@ -21,9 +22,11 @@ export type InputProps = Omit<React.ComponentPropsWithRef<"input">, "prefix"> &
onFocus?: FocusEventHandler<HTMLInputElement>
errors?: { [x: string]: unknown }
prefix?: React.ReactNode
suffix?: React.ReactNode
props?: React.HTMLAttributes<HTMLDivElement>
}
// eslint-disable-next-line react/display-name
const InputField = React.forwardRef<HTMLInputElement, InputProps>(
(
{
@@ -39,6 +42,7 @@ const InputField = React.forwardRef<HTMLInputElement, InputProps>(
tooltipContent,
tooltip,
prefix,
suffix,
errors,
props,
className,
@@ -89,9 +93,9 @@ const InputField = React.forwardRef<HTMLInputElement, InputProps>(
)}
<div
className={clsx(
"w-full flex items-center bg-grey-5 border border-gray-20 px-small py-xsmall rounded-rounded focus-within:shadow-input focus-within:border-violet-60",
"bg-grey-5 border-gray-20 px-small py-xsmall rounded-rounded focus-within:shadow-input focus-within:border-violet-60 flex w-full items-center border",
{
"border-rose-50 focus-within:shadow-cta focus-within:shadow-rose-60/10 focus-within:border-rose-50":
"focus-within:shadow-cta focus-within:shadow-rose-60/10 border-rose-50 focus-within:border-rose-50":
errors && name && errors[name],
},
small ? "h-8" : "h-10"
@@ -102,7 +106,7 @@ const InputField = React.forwardRef<HTMLInputElement, InputProps>(
) : null}
<input
className={clsx(
"bg-transparent outline-none outline-0 w-full remove-number-spinner leading-base text-grey-90 font-normal caret-violet-60 placeholder-grey-40",
"remove-number-spinner leading-base text-grey-90 caret-violet-60 placeholder-grey-40 w-full bg-transparent font-normal outline-none outline-0",
{ "text-small": small, "pt-[1px]": small }
)}
ref={inputRef}
@@ -114,11 +118,14 @@ const InputField = React.forwardRef<HTMLInputElement, InputProps>(
required={required}
{...fieldProps}
/>
{suffix ? (
<span className="mx-2xsmall text-grey-40">{suffix}</span>
) : null}
{deletable && (
<button
onClick={onDelete}
className="flex items-center justify-center w-4 h-4 pb-px ml-2 outline-none cursor-pointer text-grey-50 hover:bg-grey-10 focus:bg-grey-20 rounded-soft"
className="text-grey-50 hover:bg-grey-10 focus:bg-grey-20 rounded-soft ml-2 flex h-4 w-4 cursor-pointer items-center justify-center pb-px outline-none"
type="button"
>
&times;
@@ -126,11 +133,11 @@ const InputField = React.forwardRef<HTMLInputElement, InputProps>(
)}
{fieldProps.type === "number" && (
<div className="flex items-center self-end h-full">
<div className="flex h-full items-center self-end">
<button
onClick={onNumberDecrement}
onMouseDown={(e) => e.preventDefault()}
className="w-4 h-4 mr-2 outline-none cursor-pointer text-grey-50 hover:bg-grey-10 focus:bg-grey-20 rounded-soft"
className="text-grey-50 hover:bg-grey-10 focus:bg-grey-20 rounded-soft mr-2 h-4 w-4 cursor-pointer outline-none"
type="button"
>
<MinusIcon size={16} />
@@ -138,7 +145,7 @@ const InputField = React.forwardRef<HTMLInputElement, InputProps>(
<button
onMouseDown={(e) => e.preventDefault()}
onClick={onNumberIncrement}
className="w-4 h-4 outline-none cursor-pointer text-grey-50 hover:bg-grey-10 focus:bg-grey-20 rounded-soft"
className="text-grey-50 hover:bg-grey-10 focus:bg-grey-20 rounded-soft h-4 w-4 cursor-pointer outline-none"
type="button"
>
<PlusIcon size={16} />

View File

@@ -3,6 +3,7 @@ import * as Portal from "@radix-ui/react-portal"
import clsx from "clsx"
import React from "react"
import { useWindowDimensions } from "../../../hooks/use-window-dimensions"
import Button from "../../fundamentals/button"
import CrossIcon from "../../fundamentals/icons/cross-icon"
type ModalState = {
@@ -42,7 +43,7 @@ type ModalType = React.FC<ModalProps> & {
const Overlay: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<Dialog.Overlay className="fixed bg-grey-90/40 z-50 grid top-0 left-0 right-0 bottom-0 place-items-center overflow-y-auto">
<Dialog.Overlay className="fixed top-0 bottom-0 left-0 right-0 z-50 grid overflow-y-auto bg-grey-90/40 place-items-center">
{children}
</Dialog.Overlay>
)
@@ -56,7 +57,7 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<Dialog.Content
style={style}
className="bg-grey-0 min-w-modal rounded-rounded overflow-x-hidden"
className="overflow-x-hidden min-w-modal rounded-rounded bg-grey-0"
>
{children}
</Dialog.Content>
@@ -108,7 +109,7 @@ Modal.Content = ({ children, className }) => {
<div
style={style}
className={clsx(
"px-7 pt-5 overflow-y-auto",
"overflow-y-auto px-8 pt-6",
{
["w-largeModal pb-7"]: isLargeModal,
["pb-5"]: !isLargeModal,
@@ -124,17 +125,22 @@ Modal.Content = ({ children, className }) => {
Modal.Header = ({ handleClose = undefined, children }) => {
return (
<div
className="pl-7 pt-3.5 pr-3.5 flex flex-col w-full"
className="flex items-center w-full px-8 py-6 border-b"
onClick={(e) => e.stopPropagation()}
>
<div className="pb-1 flex w-full justify-end">
<div className="flex flex-grow">{children}</div>
<div className="self-end">
{handleClose && (
<button onClick={handleClose} className="text-grey-50 cursor-pointer">
<Button
variant="ghost"
size="small"
onClick={handleClose}
className="text-grey-50 cursor-pointer border p-1.5"
>
<CrossIcon size={20} />
</button>
</Button>
)}
</div>
{children}
</div>
)
}
@@ -146,9 +152,9 @@ Modal.Footer = ({ children, className }) => {
<div
onClick={(e) => e.stopPropagation()}
className={clsx(
"px-7 bottom-0 pb-5 flex w-full",
"bottom-0 flex w-full px-7 pb-5",
{
"border-t border-grey-20 pt-4": isLargeModal,
"border-grey-20 border-t pt-4": isLargeModal,
},
className
)}

View File

@@ -1,7 +1,7 @@
import clsx from "clsx"
import React, { ReactNode, useContext, useReducer } from "react"
import Button from "../../fundamentals/button"
import ArrowLeftIcon from "../../fundamentals/icons/arrow-left-icon"
import UTurnIcon from "../../fundamentals/icons/u-turn-icon"
import Modal, { ModalProps } from "../../molecules/modal"
enum LayeredModalActions {
@@ -112,13 +112,13 @@ const LayeredModal: React.FC<LayeredModalProps> = ({
<Button
variant="ghost"
size="small"
className="h-8 w-8 text-grey-50"
className="w-8 h-8 border text-grey-50"
onClick={screen.onBack}
>
<ArrowLeftIcon size={20} />
<UTurnIcon size={20} />
</Button>
<div className="flex items-center gap-x-2xsmall">
<h2 className="inter-xlarge-semibold ml-5">{screen.title}</h2>
<h2 className="ml-4 inter-xlarge-semibold">{screen.title}</h2>
{screen.subtitle && (
<span className="inter-xlarge-regular text-grey-50">
({screen.subtitle})