feat(dashboard): Submit forms on Cmd + Enter (#9623)
**What** - Changes all forms to only submit on Cmd/Ctrl + Enter instead of just Enter. - Cleans up the position of submit/cancel buttons in many FocusModals that still had them in the header. - Fixes responsiveness of multiple forms - Removes the SplitView component, and replaces its usages with StackedDrawer/Modal to align the UX across the project. Resolves CC-103, CC-535
This commit is contained in:
1 parent
0be50059f2
commit
1d540af783
120 files changed
+1138
-1056
No files matched your search
@@ -24,6 +24,7 @@ import { Form } from "../../common/form"
|
|||||||
import { InlineTip } from "../../common/inline-tip"
|
import { InlineTip } from "../../common/inline-tip"
|
||||||
import { Skeleton } from "../../common/skeleton"
|
import { Skeleton } from "../../common/skeleton"
|
||||||
import { RouteDrawer, useRouteModal } from "../../modals"
|
import { RouteDrawer, useRouteModal } from "../../modals"
|
||||||
|
import { KeyboundForm } from "../../utilities/keybound-form"
|
||||||
|
|
||||||
type MetaDataSubmitHook<TRes> = (
|
type MetaDataSubmitHook<TRes> = (
|
||||||
params: { metadata?: Record<string, any> | null },
|
params: { metadata?: Record<string, any> | null },
|
||||||
@@ -125,7 +126,7 @@ const InnerForm = <TRes,>({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -277,7 +278,7 @@ const InnerForm = <TRes,>({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
} from "react"
|
} from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
import { genericForwardRef } from "../../common/generic-forward-ref"
|
import { genericForwardRef } from "../../utilities/generic-forward-ref"
|
||||||
|
|
||||||
type ComboboxOption = {
|
type ComboboxOption = {
|
||||||
value: string
|
value: string
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
export * from "./split-view"
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import { Button, clx } from "@medusajs/ui"
|
|
||||||
import * as Dialog from "@radix-ui/react-dialog"
|
|
||||||
import {
|
|
||||||
ComponentPropsWithoutRef,
|
|
||||||
PropsWithChildren,
|
|
||||||
createContext,
|
|
||||||
useContext,
|
|
||||||
useRef,
|
|
||||||
} from "react"
|
|
||||||
|
|
||||||
type SplitViewContextValue = {
|
|
||||||
open: boolean
|
|
||||||
onOpenChange: (open: boolean) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const SplitViewContext = createContext<SplitViewContextValue | null>(null)
|
|
||||||
|
|
||||||
const useSplitViewContext = () => {
|
|
||||||
const context = useContext(SplitViewContext)
|
|
||||||
|
|
||||||
if (!context) {
|
|
||||||
throw new Error("useSplitViewContext must be used within a SplitView")
|
|
||||||
}
|
|
||||||
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
type SplitViewProps = PropsWithChildren<{
|
|
||||||
open?: boolean
|
|
||||||
onOpenChange?: (open: boolean) => void
|
|
||||||
}>
|
|
||||||
|
|
||||||
const Root = ({ open, onOpenChange, children }: SplitViewProps) => {
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog.Root open={open} onOpenChange={onOpenChange}>
|
|
||||||
<div ref={containerRef} className="relative size-full overflow-hidden">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</Dialog.Root>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Content = ({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: ComponentPropsWithoutRef<"div">) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={clx("relative h-full overflow-y-auto", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Drawer = ({ children }: PropsWithChildren) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Dialog.Overlay
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-base absolute inset-0 opacity-40",
|
|
||||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Dialog.Content
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-base border-ui-border-base absolute inset-y-0 right-0 flex w-full max-w-[calc(100%-128px)] flex-1 flex-col border-l focus:outline-none md:max-w-[80%] lg:max-w-[50%]",
|
|
||||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-right-1/2 data-[state=open]:slide-in-from-right-1/2 duration-200"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Dialog.Content>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Close = ({
|
|
||||||
variant = "secondary",
|
|
||||||
size = "small",
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: ComponentPropsWithoutRef<typeof Button>) => {
|
|
||||||
return (
|
|
||||||
<Dialog.Close asChild>
|
|
||||||
<Button size={size} variant={variant} {...props}>
|
|
||||||
{children}
|
|
||||||
</Button>
|
|
||||||
</Dialog.Close>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SplitView is a layout component that allows you to create a split view layout within a FocusModal.
|
|
||||||
*/
|
|
||||||
export const SplitView = Object.assign(Root, {
|
|
||||||
Content,
|
|
||||||
Drawer,
|
|
||||||
Close,
|
|
||||||
})
|
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
|||||||
|
export * from "./keybound-form"
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A form that can only be submitted when using the meta or control key.
|
||||||
|
*/
|
||||||
|
export const KeyboundForm = React.forwardRef<
|
||||||
|
HTMLFormElement,
|
||||||
|
React.FormHTMLAttributes<HTMLFormElement>
|
||||||
|
>(({ onSubmit, onKeyDown, ...rest }, ref) => {
|
||||||
|
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
event.preventDefault()
|
||||||
|
onSubmit?.(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLFormElement>) => {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
if (event.metaKey || event.ctrlKey) {
|
||||||
|
handleSubmit(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form
|
||||||
|
{...rest}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
onKeyDown={onKeyDown ?? handleKeyDown}
|
||||||
|
ref={ref}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
KeyboundForm.displayName = "KeyboundForm"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./visually-hidden"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { PropsWithChildren } from "react"
|
||||||
|
|
||||||
|
export const VisuallyHidden = ({ children }: PropsWithChildren) => {
|
||||||
|
return <span className="sr-only">{children}</span>
|
||||||
|
}
|
||||||
@@ -1877,6 +1877,7 @@
|
|||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"header": "Edit Campaign",
|
"header": "Edit Campaign",
|
||||||
|
"description": "Edit the details of the campaign.",
|
||||||
"successToast": "Campaign '{{name}}' was successfully updated."
|
"successToast": "Campaign '{{name}}' was successfully updated."
|
||||||
},
|
},
|
||||||
"configuration": {
|
"configuration": {
|
||||||
@@ -1888,6 +1889,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"create": {
|
"create": {
|
||||||
|
"title": "Create Campaign",
|
||||||
|
"description": "Create a promotional campaign.",
|
||||||
"hint": "Create a promotional campaign.",
|
"hint": "Create a promotional campaign.",
|
||||||
"header": "Create Campaign",
|
"header": "Create Campaign",
|
||||||
"successToast": "Campaign '{{name}}' was successfully created."
|
"successToast": "Campaign '{{name}}' was successfully created."
|
||||||
@@ -2301,9 +2304,12 @@
|
|||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"header": "Edit API Key",
|
"header": "Edit API Key",
|
||||||
|
"description": "Edit the API key's title.",
|
||||||
"successToast": "API key {{title}} was successfully updated."
|
"successToast": "API key {{title}} was successfully updated."
|
||||||
},
|
},
|
||||||
"salesChannels": {
|
"salesChannels": {
|
||||||
|
"title": "Add Sales Channels",
|
||||||
|
"description": "Add the sales channels that the API key should be limited to.",
|
||||||
"successToast_one": "{{count}} sales channel was successfully added to the API key.",
|
"successToast_one": "{{count}} sales channel was successfully added to the API key.",
|
||||||
"successToast_other": "{{count}} sales channels were successfully added to the API key.",
|
"successToast_other": "{{count}} sales channels were successfully added to the API key.",
|
||||||
"alreadyAddedTooltip": "The sales channel has already been added to the API key.",
|
"alreadyAddedTooltip": "The sales channel has already been added to the API key.",
|
||||||
|
|||||||
+30
-24
@@ -12,6 +12,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateApiKey } from "../../../../../hooks/api/api-keys"
|
import { useCreateApiKey } from "../../../../../hooks/api/api-keys"
|
||||||
import { ApiKeyType } from "../../../common/constants"
|
import { ApiKeyType } from "../../../common/constants"
|
||||||
|
|
||||||
@@ -97,36 +98,29 @@ export const ApiKeyCreateForm = ({ keyType }: ApiKeyCreateFormProps) => {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isPending}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-hidden">
|
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-hidden">
|
||||||
<div className="flex flex-1 flex-col items-center overflow-y-auto">
|
<div className="flex flex-1 flex-col items-center overflow-y-auto">
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
||||||
<div>
|
<div>
|
||||||
<Heading>
|
<RouteFocusModal.Title asChild>
|
||||||
{keyType === ApiKeyType.PUBLISHABLE
|
<Heading>
|
||||||
? t("apiKeyManagement.create.createPublishableHeader")
|
{keyType === ApiKeyType.PUBLISHABLE
|
||||||
: t("apiKeyManagement.create.createSecretHeader")}
|
? t("apiKeyManagement.create.createPublishableHeader")
|
||||||
</Heading>
|
: t("apiKeyManagement.create.createSecretHeader")}
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
</Heading>
|
||||||
{keyType === ApiKeyType.PUBLISHABLE
|
</RouteFocusModal.Title>
|
||||||
? t("apiKeyManagement.create.createPublishableHint")
|
<RouteFocusModal.Description asChild>
|
||||||
: t("apiKeyManagement.create.createSecretHint")}
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
</Text>
|
{keyType === ApiKeyType.PUBLISHABLE
|
||||||
|
? t("apiKeyManagement.create.createPublishableHint")
|
||||||
|
: t("apiKeyManagement.create.createSecretHint")}
|
||||||
|
</Text>
|
||||||
|
</RouteFocusModal.Description>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -148,7 +142,19 @@ export const ApiKeyCreateForm = ({ keyType }: ApiKeyCreateFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isPending}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
<Prompt variant="confirmation" open={!!createdKey}>
|
<Prompt variant="confirmation" open={!!createdKey}>
|
||||||
<Prompt.Content className="w-fit max-w-[42.5%]">
|
<Prompt.Content className="w-fit max-w-[42.5%]">
|
||||||
|
|||||||
+9
-1
@@ -2,6 +2,7 @@ import { Heading } from "@medusajs/ui"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { useParams } from "react-router-dom"
|
import { useParams } from "react-router-dom"
|
||||||
import { RouteDrawer } from "../../../components/modals"
|
import { RouteDrawer } from "../../../components/modals"
|
||||||
|
import { VisuallyHidden } from "../../../components/utilities/visually-hidden"
|
||||||
import { useApiKey } from "../../../hooks/api/api-keys"
|
import { useApiKey } from "../../../hooks/api/api-keys"
|
||||||
import { EditApiKeyForm } from "./components/edit-api-key-form"
|
import { EditApiKeyForm } from "./components/edit-api-key-form"
|
||||||
|
|
||||||
@@ -18,7 +19,14 @@ export const ApiKeyManagementEdit = () => {
|
|||||||
return (
|
return (
|
||||||
<RouteDrawer>
|
<RouteDrawer>
|
||||||
<RouteDrawer.Header>
|
<RouteDrawer.Header>
|
||||||
<Heading>{t("apiKeyManagement.edit.header")}</Heading>
|
<RouteDrawer.Title asChild>
|
||||||
|
<Heading>{t("apiKeyManagement.edit.header")}</Heading>
|
||||||
|
</RouteDrawer.Title>
|
||||||
|
<RouteDrawer.Description asChild>
|
||||||
|
<VisuallyHidden>
|
||||||
|
{t("apiKeyManagement.edit.description")}
|
||||||
|
</VisuallyHidden>
|
||||||
|
</RouteDrawer.Description>
|
||||||
</RouteDrawer.Header>
|
</RouteDrawer.Header>
|
||||||
{!isLoading && !!api_key && <EditApiKeyForm apiKey={api_key} />}
|
{!isLoading && !!api_key && <EditApiKeyForm apiKey={api_key} />}
|
||||||
</RouteDrawer>
|
</RouteDrawer>
|
||||||
|
|||||||
+3
-2
@@ -7,6 +7,7 @@ import * as zod from "zod"
|
|||||||
import { ApiKeyDTO } from "@medusajs/types"
|
import { ApiKeyDTO } from "@medusajs/types"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateApiKey } from "../../../../../hooks/api/api-keys"
|
import { useUpdateApiKey } from "../../../../../hooks/api/api-keys"
|
||||||
|
|
||||||
type EditApiKeyFormProps = {
|
type EditApiKeyFormProps = {
|
||||||
@@ -48,7 +49,7 @@ export const EditApiKeyForm = ({ apiKey }: EditApiKeyFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -80,7 +81,7 @@ export const EditApiKeyForm = ({ apiKey }: EditApiKeyFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+30
-14
@@ -16,9 +16,12 @@ import {
|
|||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
|
import { VisuallyHidden } from "../../../../../components/utilities/visually-hidden"
|
||||||
import { useBatchAddSalesChannelsToApiKey } from "../../../../../hooks/api/api-keys"
|
import { useBatchAddSalesChannelsToApiKey } from "../../../../../hooks/api/api-keys"
|
||||||
import { useSalesChannels } from "../../../../../hooks/api/sales-channels"
|
import { useSalesChannels } from "../../../../../hooks/api/sales-channels"
|
||||||
import { useSalesChannelTableColumns } from "../../../../../hooks/table/columns/use-sales-channel-table-columns"
|
import { useSalesChannelTableColumns } from "../../../../../hooks/table/columns/use-sales-channel-table-columns"
|
||||||
|
import { useSalesChannelTableFilters } from "../../../../../hooks/table/filters"
|
||||||
import { useSalesChannelTableQuery } from "../../../../../hooks/table/query/use-sales-channel-table-query"
|
import { useSalesChannelTableQuery } from "../../../../../hooks/table/query/use-sales-channel-table-query"
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
|
|
||||||
@@ -58,6 +61,7 @@ export const ApiKeySalesChannelsForm = ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const columns = useColumns()
|
const columns = useColumns()
|
||||||
|
const filters = useSalesChannelTableFilters()
|
||||||
|
|
||||||
const { sales_channels, count, isLoading } = useSalesChannels(
|
const { sales_channels, count, isLoading } = useSalesChannels(
|
||||||
{ ...searchParams },
|
{ ...searchParams },
|
||||||
@@ -114,33 +118,33 @@ export const ApiKeySalesChannelsForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
onSubmit={handleSubmit}
|
|
||||||
className="flex h-full flex-col overflow-hidden"
|
|
||||||
>
|
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
|
<RouteFocusModal.Title asChild>
|
||||||
|
<VisuallyHidden>
|
||||||
|
{t("apiKeyManagement.salesChannels.title")}
|
||||||
|
</VisuallyHidden>
|
||||||
|
</RouteFocusModal.Title>
|
||||||
|
<RouteFocusModal.Description asChild>
|
||||||
|
<VisuallyHidden>
|
||||||
|
{t("apiKeyManagement.salesChannels.description")}
|
||||||
|
</VisuallyHidden>
|
||||||
|
</RouteFocusModal.Description>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
{form.formState.errors.sales_channel_ids && (
|
{form.formState.errors.sales_channel_ids && (
|
||||||
<Hint variant="error">
|
<Hint variant="error">
|
||||||
{form.formState.errors.sales_channel_ids.message}
|
{form.formState.errors.sales_channel_ids.message}
|
||||||
</Hint>
|
</Hint>
|
||||||
)}
|
)}
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isPending}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body>
|
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-auto">
|
||||||
<DataTable
|
<DataTable
|
||||||
table={table}
|
table={table}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
count={count}
|
count={count}
|
||||||
pageSize={PAGE_SIZE}
|
pageSize={PAGE_SIZE}
|
||||||
|
filters={filters}
|
||||||
pagination
|
pagination
|
||||||
search="autofocus"
|
search="autofocus"
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
@@ -154,7 +158,19 @@ export const ApiKeySalesChannelsForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isPending}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-10
@@ -13,6 +13,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
import { RouteFocusModal, useRouteModal } from "../../../../components/modals"
|
import { RouteFocusModal, useRouteModal } from "../../../../components/modals"
|
||||||
import { DataTable } from "../../../../components/table/data-table"
|
import { DataTable } from "../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../components/utilities/keybound-form"
|
||||||
import { useAddOrRemoveCampaignPromotions } from "../../../../hooks/api/campaigns"
|
import { useAddOrRemoveCampaignPromotions } from "../../../../hooks/api/campaigns"
|
||||||
import { usePromotions } from "../../../../hooks/api/promotions"
|
import { usePromotions } from "../../../../hooks/api/promotions"
|
||||||
import { usePromotionTableColumns } from "../../../../hooks/table/columns/use-promotion-table-columns"
|
import { usePromotionTableColumns } from "../../../../hooks/table/columns/use-promotion-table-columns"
|
||||||
@@ -109,7 +110,7 @@ export const AddCampaignPromotionsForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -120,14 +121,6 @@ export const AddCampaignPromotionsForm = ({
|
|||||||
{form.formState.errors.promotion_ids.message}
|
{form.formState.errors.promotion_ids.message}
|
||||||
</Hint>
|
</Hint>
|
||||||
)}
|
)}
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isPending}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="flex size-full flex-col overflow-y-auto">
|
<RouteFocusModal.Body className="flex size-full flex-col overflow-y-auto">
|
||||||
@@ -148,7 +141,19 @@ export const AddCampaignPromotionsForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isPending}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -18,7 +18,9 @@ export const CampaignBudgetEdit = () => {
|
|||||||
return (
|
return (
|
||||||
<RouteDrawer>
|
<RouteDrawer>
|
||||||
<RouteDrawer.Header>
|
<RouteDrawer.Header>
|
||||||
<Heading>{t("campaigns.budget.edit.header")}</Heading>
|
<RouteDrawer.Title asChild>
|
||||||
|
<Heading>{t("campaigns.budget.edit.header")}</Heading>
|
||||||
|
</RouteDrawer.Title>
|
||||||
</RouteDrawer.Header>
|
</RouteDrawer.Header>
|
||||||
|
|
||||||
{!isLoading && campaign && <EditCampaignBudgetForm campaign={campaign} />}
|
{!isLoading && campaign && <EditCampaignBudgetForm campaign={campaign} />}
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateCampaign } from "../../../../../hooks/api/campaigns"
|
import { useUpdateCampaign } from "../../../../../hooks/api/campaigns"
|
||||||
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ export const EditCampaignBudgetForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -131,7 +132,7 @@ export const EditCampaignBudgetForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -7,6 +7,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateCampaign } from "../../../../../hooks/api/campaigns"
|
import { useUpdateCampaign } from "../../../../../hooks/api/campaigns"
|
||||||
|
|
||||||
type CampaignConfigurationFormProps = {
|
type CampaignConfigurationFormProps = {
|
||||||
@@ -59,7 +60,7 @@ export const CampaignConfigurationForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -127,7 +128,7 @@ export const CampaignConfigurationForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+16
-18
@@ -4,20 +4,22 @@ import { useForm } from "react-hook-form"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
import { CampaignBudgetTypeValues } from "@medusajs/types"
|
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
|
import { VisuallyHidden } from "../../../../../components/utilities/visually-hidden"
|
||||||
import { useCreateCampaign } from "../../../../../hooks/api/campaigns"
|
import { useCreateCampaign } from "../../../../../hooks/api/campaigns"
|
||||||
import { CreateCampaignFormFields } from "../../../common/components/create-campaign-form-fields"
|
import { CreateCampaignFormFields } from "../../../common/components/create-campaign-form-fields"
|
||||||
|
import { DEFAULT_CAMPAIGN_VALUES } from "../../../common/constants"
|
||||||
|
|
||||||
export const CreateCampaignSchema = zod.object({
|
export const CreateCampaignSchema = zod.object({
|
||||||
name: zod.string().min(1),
|
name: zod.string().min(1),
|
||||||
description: zod.string().optional(),
|
description: zod.string().optional(),
|
||||||
campaign_identifier: zod.string().min(1),
|
campaign_identifier: zod.string().min(1),
|
||||||
starts_at: zod.date().optional(),
|
starts_at: zod.date().nullable(),
|
||||||
ends_at: zod.date().optional(),
|
ends_at: zod.date().nullable(),
|
||||||
budget: zod.object({
|
budget: zod.object({
|
||||||
limit: zod.number().min(0).nullish(),
|
limit: zod.number().min(0).nullish(),
|
||||||
type: zod.enum(["spend", "usage"]),
|
type: zod.enum(["spend", "usage"]),
|
||||||
@@ -25,24 +27,13 @@ export const CreateCampaignSchema = zod.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const defaultCampaignValues = {
|
|
||||||
name: "",
|
|
||||||
description: "",
|
|
||||||
campaign_identifier: "",
|
|
||||||
budget: {
|
|
||||||
type: "usage" as CampaignBudgetTypeValues,
|
|
||||||
currency_code: null,
|
|
||||||
limit: null,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CreateCampaignForm = () => {
|
export const CreateCampaignForm = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { handleSuccess } = useRouteModal()
|
const { handleSuccess } = useRouteModal()
|
||||||
const { mutateAsync, isPending } = useCreateCampaign()
|
const { mutateAsync, isPending } = useCreateCampaign()
|
||||||
|
|
||||||
const form = useForm<zod.infer<typeof CreateCampaignSchema>>({
|
const form = useForm<zod.infer<typeof CreateCampaignSchema>>({
|
||||||
defaultValues: defaultCampaignValues,
|
defaultValues: DEFAULT_CAMPAIGN_VALUES,
|
||||||
resolver: zodResolver(CreateCampaignSchema),
|
resolver: zodResolver(CreateCampaignSchema),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -78,11 +69,18 @@ export const CreateCampaignForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header>
|
||||||
|
<RouteFocusModal.Title asChild>
|
||||||
|
<VisuallyHidden>{t("campaigns.create.title")}</VisuallyHidden>
|
||||||
|
</RouteFocusModal.Title>
|
||||||
|
<RouteFocusModal.Description asChild>
|
||||||
|
<VisuallyHidden>{t("campaigns.create.description")}</VisuallyHidden>
|
||||||
|
</RouteFocusModal.Description>
|
||||||
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="flex size-full flex-col items-center overflow-auto py-16">
|
<RouteFocusModal.Body className="flex size-full flex-col items-center overflow-auto py-16">
|
||||||
<CreateCampaignFormFields form={form} />
|
<CreateCampaignFormFields form={form} />
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
@@ -103,7 +101,7 @@ export const CreateCampaignForm = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import { Heading } from "@medusajs/ui"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { useParams } from "react-router-dom"
|
import { useParams } from "react-router-dom"
|
||||||
import { RouteDrawer } from "../../../components/modals"
|
import { RouteDrawer } from "../../../components/modals"
|
||||||
|
import { VisuallyHidden } from "../../../components/utilities/visually-hidden"
|
||||||
import { useCampaign } from "../../../hooks/api/campaigns"
|
import { useCampaign } from "../../../hooks/api/campaigns"
|
||||||
import { EditCampaignForm } from "./components/edit-campaign-form"
|
import { EditCampaignForm } from "./components/edit-campaign-form"
|
||||||
|
|
||||||
@@ -18,7 +19,12 @@ export const CampaignEdit = () => {
|
|||||||
return (
|
return (
|
||||||
<RouteDrawer>
|
<RouteDrawer>
|
||||||
<RouteDrawer.Header>
|
<RouteDrawer.Header>
|
||||||
<Heading>{t("campaigns.edit.header")}</Heading>
|
<RouteDrawer.Title asChild>
|
||||||
|
<Heading>{t("campaigns.edit.header")}</Heading>
|
||||||
|
</RouteDrawer.Title>
|
||||||
|
<RouteDrawer.Description asChild>
|
||||||
|
<VisuallyHidden>{t("campaigns.edit.description")}</VisuallyHidden>
|
||||||
|
</RouteDrawer.Description>
|
||||||
</RouteDrawer.Header>
|
</RouteDrawer.Header>
|
||||||
|
|
||||||
{!isLoading && campaign && <EditCampaignForm campaign={campaign} />}
|
{!isLoading && campaign && <EditCampaignForm campaign={campaign} />}
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateCampaign } from "../../../../../hooks/api/campaigns"
|
import { useUpdateCampaign } from "../../../../../hooks/api/campaigns"
|
||||||
|
|
||||||
type EditCampaignFormProps = {
|
type EditCampaignFormProps = {
|
||||||
@@ -65,7 +66,7 @@ export const EditCampaignForm = ({ campaign }: EditCampaignFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -187,7 +188,7 @@ export const EditCampaignForm = ({ campaign }: EditCampaignFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+11
-4
@@ -14,7 +14,10 @@ import { useTranslation } from "react-i18next"
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { useStore } from "../../../../../hooks/api/store"
|
import { useStore } from "../../../../../hooks/api/store"
|
||||||
import { currencies, getCurrencySymbol } from "../../../../../lib/data/currencies"
|
import {
|
||||||
|
currencies,
|
||||||
|
getCurrencySymbol,
|
||||||
|
} from "../../../../../lib/data/currencies"
|
||||||
|
|
||||||
export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@@ -118,7 +121,7 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
|||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>{t("fields.description")}</Form.Label>
|
<Form.Label optional>{t("fields.description")}</Form.Label>
|
||||||
|
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Textarea {...field} />
|
<Textarea {...field} />
|
||||||
@@ -138,7 +141,9 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
|||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>{t("campaigns.fields.start_date")}</Form.Label>
|
<Form.Label optional>
|
||||||
|
{t("campaigns.fields.start_date")}
|
||||||
|
</Form.Label>
|
||||||
|
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
@@ -160,7 +165,9 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
|||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>{t("campaigns.fields.end_date")}</Form.Label>
|
<Form.Label optional>
|
||||||
|
{t("campaigns.fields.end_date")}
|
||||||
|
</Form.Label>
|
||||||
|
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { CampaignBudgetTypeValues } from "@medusajs/types"
|
||||||
|
|
||||||
|
export const DEFAULT_CAMPAIGN_VALUES = {
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
campaign_identifier: "",
|
||||||
|
starts_at: null,
|
||||||
|
ends_at: null,
|
||||||
|
budget: {
|
||||||
|
type: "usage" as CampaignBudgetTypeValues,
|
||||||
|
currency_code: null,
|
||||||
|
limit: null,
|
||||||
|
},
|
||||||
|
}
|
||||||
+3
-2
@@ -8,6 +8,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateProductCategory } from "../../../../../hooks/api/categories"
|
import { useCreateProductCategory } from "../../../../../hooks/api/categories"
|
||||||
import { CreateCategoryDetails } from "./create-category-details"
|
import { CreateCategoryDetails } from "./create-category-details"
|
||||||
import { CreateCategoryNesting } from "./create-category-nesting"
|
import { CreateCategoryNesting } from "./create-category-nesting"
|
||||||
@@ -121,7 +122,7 @@ export const CreateCategoryForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -198,7 +199,7 @@ export const CreateCategoryForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</ProgressTabs>
|
</ProgressTabs>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -8,6 +8,7 @@ import { HttpTypes } from "@medusajs/types"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { HandleInput } from "../../../../../components/inputs/handle-input"
|
import { HandleInput } from "../../../../../components/inputs/handle-input"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProductCategory } from "../../../../../hooks/api/categories"
|
import { useUpdateProductCategory } from "../../../../../hooks/api/categories"
|
||||||
|
|
||||||
const EditCategorySchema = z.object({
|
const EditCategorySchema = z.object({
|
||||||
@@ -61,7 +62,7 @@ export const EditCategoryForm = ({ category }: EditCategoryFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -188,7 +189,7 @@ export const EditCategoryForm = ({ category }: EditCategoryFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -16,6 +16,7 @@ import {
|
|||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProductCategoryProducts } from "../../../../../hooks/api/categories"
|
import { useUpdateProductCategoryProducts } from "../../../../../hooks/api/categories"
|
||||||
import { useProducts } from "../../../../../hooks/api/products"
|
import { useProducts } from "../../../../../hooks/api/products"
|
||||||
import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns"
|
import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns"
|
||||||
@@ -136,7 +137,7 @@ export const EditCategoryProductsForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -173,7 +174,7 @@ export const EditCategoryProductsForm = ({
|
|||||||
search="autofocus"
|
search="autofocus"
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -16,6 +16,7 @@ import {
|
|||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals/index.ts"
|
} from "../../../../../components/modals/index.ts"
|
||||||
import { DataTable } from "../../../../../components/table/data-table/data-table.tsx"
|
import { DataTable } from "../../../../../components/table/data-table/data-table.tsx"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form/keybound-form.tsx"
|
||||||
import { useUpdateCollectionProducts } from "../../../../../hooks/api/collections.tsx"
|
import { useUpdateCollectionProducts } from "../../../../../hooks/api/collections.tsx"
|
||||||
import { useProducts } from "../../../../../hooks/api/products.tsx"
|
import { useProducts } from "../../../../../hooks/api/products.tsx"
|
||||||
import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns.tsx"
|
import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns.tsx"
|
||||||
@@ -147,7 +148,7 @@ export const AddProductsToCollectionForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -182,7 +183,7 @@ export const AddProductsToCollectionForm = ({
|
|||||||
search="autofocus"
|
search="autofocus"
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -10,6 +10,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateCollection } from "../../../../../hooks/api/collections"
|
import { useCreateCollection } from "../../../../../hooks/api/collections"
|
||||||
|
|
||||||
const CreateCollectionSchema = zod.object({
|
const CreateCollectionSchema = zod.object({
|
||||||
@@ -35,17 +36,17 @@ export const CreateCollectionForm = () => {
|
|||||||
await mutateAsync(data, {
|
await mutateAsync(data, {
|
||||||
onSuccess: ({ collection }) => {
|
onSuccess: ({ collection }) => {
|
||||||
handleSuccess(`/collections/${collection.id}`)
|
handleSuccess(`/collections/${collection.id}`)
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("collections.createSuccess"))
|
||||||
description: t("collections.createSuccess"),
|
},
|
||||||
dismissLabel: t("actions.close"),
|
onError: (error) => {
|
||||||
})
|
toast.error(error.message)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit}>
|
<KeyboundForm onSubmit={handleSubmit}>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
<RouteFocusModal.Close asChild>
|
||||||
@@ -110,7 +111,7 @@ export const CreateCollectionForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+4
-6
@@ -6,10 +6,8 @@ import * as zod from "zod"
|
|||||||
|
|
||||||
import { HttpTypes } from "@medusajs/types"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import {
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
RouteDrawer,
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
useRouteModal,
|
|
||||||
} from "../../../../../components/modals"
|
|
||||||
import { useUpdateCollection } from "../../../../../hooks/api/collections"
|
import { useUpdateCollection } from "../../../../../hooks/api/collections"
|
||||||
|
|
||||||
type EditCollectionFormProps = {
|
type EditCollectionFormProps = {
|
||||||
@@ -45,7 +43,7 @@ export const EditCollectionForm = ({ collection }: EditCollectionFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -106,7 +104,7 @@ export const EditCollectionForm = ({ collection }: EditCollectionFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -16,6 +16,7 @@ import {
|
|||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useAddCustomersToGroup } from "../../../../../hooks/api/customer-groups"
|
import { useAddCustomersToGroup } from "../../../../../hooks/api/customer-groups"
|
||||||
import { useCustomers } from "../../../../../hooks/api/customers"
|
import { useCustomers } from "../../../../../hooks/api/customers"
|
||||||
import { useCustomerTableColumns } from "../../../../../hooks/table/columns/use-customer-table-columns"
|
import { useCustomerTableColumns } from "../../../../../hooks/table/columns/use-customer-table-columns"
|
||||||
@@ -125,7 +126,7 @@ export const AddCustomersForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -175,7 +176,7 @@ export const AddCustomersForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-23
@@ -9,6 +9,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateCustomerGroup } from "../../../../../hooks/api/customer-groups"
|
import { useCreateCustomerGroup } from "../../../../../hooks/api/customer-groups"
|
||||||
|
|
||||||
export const CreateCustomerGroupSchema = zod.object({
|
export const CreateCustomerGroupSchema = zod.object({
|
||||||
@@ -52,31 +53,19 @@ export const CreateCustomerGroupForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit}>
|
<KeyboundForm onSubmit={handleSubmit}>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button variant="secondary" size="small">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant="primary"
|
|
||||||
size="small"
|
|
||||||
isLoading={isPending}
|
|
||||||
>
|
|
||||||
{t("actions.create")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex flex-col items-center pt-[72px]">
|
<RouteFocusModal.Body className="flex flex-col items-center pt-[72px]">
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||||
<div>
|
<div>
|
||||||
<Heading>{t("customerGroups.create.header")}</Heading>
|
<RouteFocusModal.Title asChild>
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
<Heading>{t("customerGroups.create.header")}</Heading>
|
||||||
{t("customerGroups.create.hint")}
|
</RouteFocusModal.Title>
|
||||||
</Text>
|
<RouteFocusModal.Description asChild>
|
||||||
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
|
{t("customerGroups.create.hint")}
|
||||||
|
</Text>
|
||||||
|
</RouteFocusModal.Description>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -97,7 +86,22 @@ export const CreateCustomerGroupForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button variant="secondary" size="small">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="primary"
|
||||||
|
size="small"
|
||||||
|
isLoading={isPending}
|
||||||
|
>
|
||||||
|
{t("actions.create")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import * as z from "zod"
|
import * as z from "zod"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateCustomerGroup } from "../../../../../hooks/api/customer-groups"
|
import { useUpdateCustomerGroup } from "../../../../../hooks/api/customer-groups"
|
||||||
|
|
||||||
type EditCustomerGroupFormProps = {
|
type EditCustomerGroupFormProps = {
|
||||||
@@ -50,7 +51,7 @@ export const EditCustomerGroupForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -83,7 +84,7 @@ export const EditCustomerGroupForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+25
-20
@@ -9,6 +9,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateCustomer } from "../../../../../hooks/api/customers"
|
import { useCreateCustomer } from "../../../../../hooks/api/customers"
|
||||||
|
|
||||||
const CreateCustomerSchema = zod.object({
|
const CreateCustomerSchema = zod.object({
|
||||||
@@ -63,25 +64,12 @@ export const CreateCustomerForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit}>
|
<KeyboundForm
|
||||||
<RouteFocusModal.Header>
|
onSubmit={handleSubmit}
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
<RouteFocusModal.Close asChild>
|
>
|
||||||
<Button size="small" variant="secondary">
|
<RouteFocusModal.Header />
|
||||||
{t("actions.cancel")}
|
<RouteFocusModal.Body className="flex flex-1 flex-col items-center overflow-y-auto py-16">
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
variant="primary"
|
|
||||||
type="submit"
|
|
||||||
isLoading={isPending}
|
|
||||||
>
|
|
||||||
{t("actions.create")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex flex-col items-center py-16">
|
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||||
<div>
|
<div>
|
||||||
<Heading>{t("customers.create.header")}</Heading>
|
<Heading>{t("customers.create.header")}</Heading>
|
||||||
@@ -168,7 +156,24 @@ export const CreateCustomerForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
isLoading={isPending}
|
||||||
|
>
|
||||||
|
{t("actions.create")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -10,6 +10,7 @@ import {
|
|||||||
RouteDrawer,
|
RouteDrawer,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals/index.ts"
|
} from "../../../../../components/modals/index.ts"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form/keybound-form.tsx"
|
||||||
import { useUpdateCustomer } from "../../../../../hooks/api/customers.tsx"
|
import { useUpdateCustomer } from "../../../../../hooks/api/customers.tsx"
|
||||||
|
|
||||||
type EditCustomerFormProps = {
|
type EditCustomerFormProps = {
|
||||||
@@ -69,7 +70,7 @@ export const EditCustomerForm = ({ customer }: EditCustomerFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -171,7 +172,7 @@ export const EditCustomerForm = ({ customer }: EditCustomerFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+4
-3
@@ -1,12 +1,13 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import { Button } from "@medusajs/ui"
|
import { Button } from "@medusajs/ui"
|
||||||
import { useForm } 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 { z } from "zod"
|
||||||
import { TransferOwnerShipForm } from "../../../../../components/forms/transfer-ownership-form"
|
import { TransferOwnerShipForm } from "../../../../../components/forms/transfer-ownership-form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { TransferOwnershipSchema } from "../../../../../lib/schemas"
|
import { TransferOwnershipSchema } from "../../../../../lib/schemas"
|
||||||
import { HttpTypes } from "@medusajs/types"
|
|
||||||
|
|
||||||
type TransferCustomerOrderOwnershipFormProps = {
|
type TransferCustomerOrderOwnershipFormProps = {
|
||||||
order: HttpTypes.AdminOrder
|
order: HttpTypes.AdminOrder
|
||||||
@@ -46,7 +47,7 @@ export const TransferCustomerOrderOwnershipForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -65,7 +66,7 @@ export const TransferCustomerOrderOwnershipForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+10
-9
@@ -10,11 +10,13 @@ import { useForm } from "react-hook-form"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
customerGroupsQueryKeys,
|
customerGroupsQueryKeys,
|
||||||
useCustomerGroups,
|
useCustomerGroups,
|
||||||
@@ -23,7 +25,7 @@ import { useCustomerGroupTableColumns } from "../../../../../hooks/table/columns
|
|||||||
import { useCustomerGroupTableFilters } from "../../../../../hooks/table/filters/use-customer-group-table-filters"
|
import { useCustomerGroupTableFilters } from "../../../../../hooks/table/filters/use-customer-group-table-filters"
|
||||||
import { useCustomerGroupTableQuery } from "../../../../../hooks/table/query/use-customer-group-table-query"
|
import { useCustomerGroupTableQuery } from "../../../../../hooks/table/query/use-customer-group-table-query"
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
import { client, sdk } from "../../../../../lib/client"
|
import { sdk } from "../../../../../lib/client"
|
||||||
import { queryClient } from "../../../../../lib/query-client"
|
import { queryClient } from "../../../../../lib/query-client"
|
||||||
|
|
||||||
type AddCustomerGroupsFormProps = {
|
type AddCustomerGroupsFormProps = {
|
||||||
@@ -126,15 +128,14 @@ export const AddCustomerGroupsForm = ({
|
|||||||
|
|
||||||
await Promise.all(promises)
|
await Promise.all(promises)
|
||||||
|
|
||||||
toast.success(t("general.success"), {
|
toast.success(
|
||||||
description: t("customers.groups.add.success", {
|
t("customers.groups.add.success", {
|
||||||
groups: data.customer_group_ids
|
groups: data.customer_group_ids
|
||||||
.map((id) => customer_groups?.find((g) => g.id === id))
|
.map((id) => customer_groups?.find((g) => g.id === id))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.map((cg) => cg.name),
|
.map((cg) => cg?.name),
|
||||||
}),
|
})
|
||||||
dismissLabel: t("actions.close"),
|
)
|
||||||
})
|
|
||||||
|
|
||||||
await queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: customerGroupsQueryKeys.lists(),
|
queryKey: customerGroupsQueryKeys.lists(),
|
||||||
@@ -154,7 +155,7 @@ export const AddCustomerGroupsForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -199,7 +200,7 @@ export const AddCustomerGroupsForm = ({
|
|||||||
{t("actions.save")}
|
{t("actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -22,6 +22,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
inventoryItemsQueryKeys,
|
inventoryItemsQueryKeys,
|
||||||
useCreateInventoryItem,
|
useCreateInventoryItem,
|
||||||
@@ -204,7 +205,7 @@ export function InventoryCreateForm({ locations }: InventoryCreateFormProps) {
|
|||||||
className="h-full"
|
className="h-full"
|
||||||
onValueChange={(tab) => onTabChange(tab as Tab)}
|
onValueChange={(tab) => onTabChange(tab as Tab)}
|
||||||
>
|
>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -507,7 +508,7 @@ export function InventoryCreateForm({ locations }: InventoryCreateFormProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</ProgressTabs>
|
</ProgressTabs>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-2
@@ -8,6 +8,7 @@ import { RouteDrawer, useRouteModal } from "../../../../../../components/modals"
|
|||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { Form } from "../../../../../../components/common/form"
|
import { Form } from "../../../../../../components/common/form"
|
||||||
|
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateInventoryLevel } from "../../../../../../hooks/api/inventory"
|
import { useUpdateInventoryLevel } from "../../../../../../hooks/api/inventory"
|
||||||
|
|
||||||
type AdjustInventoryFormProps = {
|
type AdjustInventoryFormProps = {
|
||||||
@@ -84,7 +85,7 @@ export const AdjustInventoryForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -150,7 +151,7 @@ export const AdjustInventoryForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -11,6 +11,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Form } from "../../../../../../components/common/form"
|
import { Form } from "../../../../../../components/common/form"
|
||||||
import { CountrySelect } from "../../../../../../components/inputs/country-select"
|
import { CountrySelect } from "../../../../../../components/inputs/country-select"
|
||||||
|
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateInventoryItem } from "../../../../../../hooks/api/inventory"
|
import { useUpdateInventoryItem } from "../../../../../../hooks/api/inventory"
|
||||||
|
|
||||||
type EditInventoryItemAttributeFormProps = {
|
type EditInventoryItemAttributeFormProps = {
|
||||||
@@ -64,7 +65,7 @@ export const EditInventoryItemAttributesForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -246,7 +247,7 @@ export const EditInventoryItemAttributesForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -9,6 +9,7 @@ import { useForm } from "react-hook-form"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { Form } from "../../../../../../components/common/form"
|
import { Form } from "../../../../../../components/common/form"
|
||||||
|
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateInventoryItem } from "../../../../../../hooks/api/inventory"
|
import { useUpdateInventoryItem } from "../../../../../../hooks/api/inventory"
|
||||||
|
|
||||||
type EditInventoryItemFormProps = {
|
type EditInventoryItemFormProps = {
|
||||||
@@ -50,7 +51,7 @@ export const EditInventoryItemForm = ({ item }: EditInventoryItemFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -98,7 +99,7 @@ export const EditInventoryItemForm = ({ item }: EditInventoryItemFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -10,6 +10,7 @@ import { RouteDrawer, useRouteModal } from "../../../../../../components/modals"
|
|||||||
import { useBatchUpdateInventoryLevels } from "../../../../../../hooks/api/inventory"
|
import { useBatchUpdateInventoryLevels } from "../../../../../../hooks/api/inventory"
|
||||||
|
|
||||||
import { useEffect, useMemo } from "react"
|
import { useEffect, useMemo } from "react"
|
||||||
|
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
||||||
import { LocationItem } from "./location-item"
|
import { LocationItem } from "./location-item"
|
||||||
|
|
||||||
type EditInventoryItemAttributeFormProps = {
|
type EditInventoryItemAttributeFormProps = {
|
||||||
@@ -120,7 +121,7 @@ export const ManageLocationsForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -189,7 +190,7 @@ export const ManageLocationsForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,11 @@ import { decodeToken } from "react-jwt"
|
|||||||
import { Link, useSearchParams } from "react-router-dom"
|
import { Link, useSearchParams } from "react-router-dom"
|
||||||
import * as z from "zod"
|
import * as z from "zod"
|
||||||
import { Form } from "../../components/common/form"
|
import { Form } from "../../components/common/form"
|
||||||
|
import AvatarBox from "../../components/common/logo-box/avatar-box"
|
||||||
|
import { KeyboundForm } from "../../components/utilities/keybound-form"
|
||||||
import { useSignUpWithEmailPass } from "../../hooks/api/auth"
|
import { useSignUpWithEmailPass } from "../../hooks/api/auth"
|
||||||
import { useAcceptInvite } from "../../hooks/api/invites"
|
import { useAcceptInvite } from "../../hooks/api/invites"
|
||||||
import { isFetchError } from "../../lib/is-fetch-error"
|
import { isFetchError } from "../../lib/is-fetch-error"
|
||||||
import AvatarBox from "../../components/common/logo-box/avatar-box"
|
|
||||||
|
|
||||||
const CreateAccountSchema = z
|
const CreateAccountSchema = z
|
||||||
.object({
|
.object({
|
||||||
@@ -139,7 +140,7 @@ const LoginLink = () => {
|
|||||||
<Link
|
<Link
|
||||||
key="login-link"
|
key="login-link"
|
||||||
to="/login"
|
to="/login"
|
||||||
className="text-ui-fg-interactive txt-small !text-ui-fg-base font-medium transition-fg hover:text-ui-fg-interactive-hover focus-visible:text-ui-fg-interactive-hover outline-none"
|
className="text-ui-fg-interactive txt-small !text-ui-fg-base transition-fg hover:text-ui-fg-interactive-hover focus-visible:text-ui-fg-interactive-hover font-medium outline-none"
|
||||||
>
|
>
|
||||||
{t("invite.backToLogin")}
|
{t("invite.backToLogin")}
|
||||||
</Link>
|
</Link>
|
||||||
@@ -250,7 +251,10 @@ const CreateView = ({
|
|||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={handleSubmit} className="flex w-full flex-col gap-y-6">
|
<KeyboundForm
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
className="flex w-full flex-col gap-y-6"
|
||||||
|
>
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-y-2">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -345,7 +349,7 @@ const CreateView = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{validationError && (
|
{validationError && (
|
||||||
<div className="text-center mt-6">
|
<div className="mt-6 text-center">
|
||||||
<Hint className="inline-flex" variant={"error"}>
|
<Hint className="inline-flex" variant={"error"}>
|
||||||
{validationError}
|
{validationError}
|
||||||
</Hint>
|
</Hint>
|
||||||
@@ -353,7 +357,7 @@ const CreateView = ({
|
|||||||
)}
|
)}
|
||||||
{serverError && (
|
{serverError && (
|
||||||
<Alert
|
<Alert
|
||||||
className="p-2 bg-ui-bg-base items-center"
|
className="bg-ui-bg-base items-center p-2"
|
||||||
dismissible
|
dismissible
|
||||||
variant="error"
|
variant="error"
|
||||||
>
|
>
|
||||||
@@ -369,7 +373,7 @@ const CreateView = ({
|
|||||||
>
|
>
|
||||||
{t("invite.createAccount")}
|
{t("invite.createAccount")}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</Form>
|
</Form>
|
||||||
<LoginLink />
|
<LoginLink />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+40
-28
@@ -11,7 +11,10 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { ChipGroup } from "../../../../../components/common/chip-group"
|
import { ChipGroup } from "../../../../../components/common/chip-group"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
import {
|
||||||
|
StackedFocusModal,
|
||||||
|
useStackedModal,
|
||||||
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
import {
|
import {
|
||||||
@@ -21,6 +24,7 @@ import {
|
|||||||
import { useCountries } from "../../../../regions/common/hooks/use-countries"
|
import { useCountries } from "../../../../regions/common/hooks/use-countries"
|
||||||
import { useCountryTableColumns } from "../../../../regions/common/hooks/use-country-table-columns"
|
import { useCountryTableColumns } from "../../../../regions/common/hooks/use-country-table-columns"
|
||||||
import { useCountryTableQuery } from "../../../../regions/common/hooks/use-country-table-query"
|
import { useCountryTableQuery } from "../../../../regions/common/hooks/use-country-table-query"
|
||||||
|
import { GEO_ZONE_STACKED_MODAL_ID } from "../../constants"
|
||||||
|
|
||||||
const GeoZoneSchema = z.object({
|
const GeoZoneSchema = z.object({
|
||||||
countries: z.array(
|
countries: z.array(
|
||||||
@@ -30,12 +34,10 @@ const GeoZoneSchema = z.object({
|
|||||||
|
|
||||||
type GeoZoneFormImplProps<TForm extends UseFormReturn<any>> = {
|
type GeoZoneFormImplProps<TForm extends UseFormReturn<any>> = {
|
||||||
form: TForm
|
form: TForm
|
||||||
onOpenChange: (open: boolean) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const GeoZoneFormImpl = <TForm extends UseFormReturn<any>>({
|
const GeoZoneFormImpl = <TForm extends UseFormReturn<any>>({
|
||||||
form,
|
form,
|
||||||
onOpenChange,
|
|
||||||
}: GeoZoneFormImplProps<TForm>) => {
|
}: GeoZoneFormImplProps<TForm>) => {
|
||||||
const castForm = form as unknown as UseFormReturn<
|
const castForm = form as unknown as UseFormReturn<
|
||||||
z.infer<typeof GeoZoneSchema>
|
z.infer<typeof GeoZoneSchema>
|
||||||
@@ -71,14 +73,11 @@ const GeoZoneFormImpl = <TForm extends UseFormReturn<any>>({
|
|||||||
{t("stockLocations.serviceZones.manageAreas.hint")}
|
{t("stockLocations.serviceZones.manageAreas.hint")}
|
||||||
</Form.Hint>
|
</Form.Hint>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<StackedFocusModal.Trigger asChild>
|
||||||
size="small"
|
<Button size="small" variant="secondary" type="button">
|
||||||
variant="secondary"
|
{t("stockLocations.serviceZones.manageAreas.action")}
|
||||||
type="button"
|
</Button>
|
||||||
onClick={() => onOpenChange(true)}
|
</StackedFocusModal.Trigger>
|
||||||
>
|
|
||||||
{t("stockLocations.serviceZones.manageAreas.action")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<Form.ErrorMessage />
|
<Form.ErrorMessage />
|
||||||
<Form.Control className="mt-0">
|
<Form.Control className="mt-0">
|
||||||
@@ -103,26 +102,25 @@ const GeoZoneFormImpl = <TForm extends UseFormReturn<any>>({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type AreasDrawerProps<TForm extends UseFormReturn<any>> = {
|
type AreasStackedModalProps<TForm extends UseFormReturn<any>> = {
|
||||||
form: TForm
|
form: TForm
|
||||||
open: boolean
|
|
||||||
onOpenChange: (open: boolean) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PREFIX = "ac"
|
const PREFIX = "ac"
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 50
|
||||||
|
|
||||||
const AreaDrawer = <TForm extends UseFormReturn<any>>({
|
const AreaStackedModal = <TForm extends UseFormReturn<any>>({
|
||||||
form,
|
form,
|
||||||
open,
|
}: AreasStackedModalProps<TForm>) => {
|
||||||
onOpenChange,
|
|
||||||
}: AreasDrawerProps<TForm>) => {
|
|
||||||
const castForm = form as unknown as UseFormReturn<
|
const castForm = form as unknown as UseFormReturn<
|
||||||
z.infer<typeof GeoZoneSchema>
|
z.infer<typeof GeoZoneSchema>
|
||||||
>
|
>
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { getValues, setValue } = castForm
|
const { getValues, setValue } = castForm
|
||||||
|
const { setIsOpen, getIsOpen } = useStackedModal()
|
||||||
|
|
||||||
|
const open = getIsOpen(GEO_ZONE_STACKED_MODAL_ID)
|
||||||
|
|
||||||
const [selection, setSelection] = useState<RowSelectionState>({})
|
const [selection, setSelection] = useState<RowSelectionState>({})
|
||||||
const [state, setState] = useState<{ iso_2: string; display_name: string }[]>(
|
const [state, setState] = useState<{ iso_2: string; display_name: string }[]>(
|
||||||
@@ -203,7 +201,7 @@ const AreaDrawer = <TForm extends UseFormReturn<any>>({
|
|||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldTouch: true,
|
shouldTouch: true,
|
||||||
})
|
})
|
||||||
onOpenChange(false)
|
setIsOpen(GEO_ZONE_STACKED_MODAL_ID, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns = useColumns()
|
const columns = useColumns()
|
||||||
@@ -226,8 +224,20 @@ const AreaDrawer = <TForm extends UseFormReturn<any>>({
|
|||||||
validateForm(form)
|
validateForm(form)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SplitView.Drawer>
|
<StackedFocusModal.Content className="flex flex-col overflow-hidden">
|
||||||
<div className="flex h-full flex-col overflow-hidden">
|
<StackedFocusModal.Header>
|
||||||
|
<StackedFocusModal.Title asChild>
|
||||||
|
<span className="sr-only">
|
||||||
|
{t("stockLocations.serviceZones.manageAreas.label")}
|
||||||
|
</span>
|
||||||
|
</StackedFocusModal.Title>
|
||||||
|
<StackedFocusModal.Description asChild>
|
||||||
|
<span className="sr-only">
|
||||||
|
{t("stockLocations.serviceZones.manageAreas.hint")}
|
||||||
|
</span>
|
||||||
|
</StackedFocusModal.Description>
|
||||||
|
</StackedFocusModal.Header>
|
||||||
|
<StackedFocusModal.Body className="flex-1 overflow-hidden">
|
||||||
<DataTable
|
<DataTable
|
||||||
table={table}
|
table={table}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@@ -240,18 +250,20 @@ const AreaDrawer = <TForm extends UseFormReturn<any>>({
|
|||||||
queryObject={raw}
|
queryObject={raw}
|
||||||
prefix={PREFIX}
|
prefix={PREFIX}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center justify-end gap-x-2 border-t p-4">
|
</StackedFocusModal.Body>
|
||||||
<SplitView.Close type="button" asChild>
|
<StackedFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<StackedFocusModal.Close type="button" asChild>
|
||||||
<Button variant="secondary" size="small">
|
<Button variant="secondary" size="small">
|
||||||
{t("actions.cancel")}
|
{t("actions.cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
</SplitView.Close>
|
</StackedFocusModal.Close>
|
||||||
<Button size="small" type="button" onClick={handleAdd}>
|
<Button size="small" type="button" onClick={handleAdd}>
|
||||||
{t("actions.add")}
|
{t("actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</StackedFocusModal.Footer>
|
||||||
</SplitView.Drawer>
|
</StackedFocusModal.Content>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,5 +320,5 @@ function validateForm(form: UseFormReturn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const GeoZoneForm = Object.assign(GeoZoneFormImpl, {
|
export const GeoZoneForm = Object.assign(GeoZoneFormImpl, {
|
||||||
AreaDrawer,
|
AreaDrawer: AreaStackedModal,
|
||||||
})
|
})
|
||||||
@@ -7,3 +7,5 @@ export enum ShippingOptionPriceType {
|
|||||||
FlatRate = "flat",
|
FlatRate = "flat",
|
||||||
Calculated = "calculated",
|
Calculated = "calculated",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GEO_ZONE_STACKED_MODAL_ID = "geo-zone"
|
||||||
+16
-14
@@ -9,6 +9,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateStockLocation } from "../../../../../hooks/api/stock-locations"
|
import { useCreateStockLocation } from "../../../../../hooks/api/stock-locations"
|
||||||
|
|
||||||
const CreateLocationSchema = zod.object({
|
const CreateLocationSchema = zod.object({
|
||||||
@@ -69,22 +70,11 @@ export const CreateLocationForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button type="submit" size="small" isLoading={isPending}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-hidden">
|
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-hidden">
|
||||||
<div className="flex flex-1 flex-col items-center overflow-y-auto">
|
<div className="flex flex-1 flex-col items-center overflow-y-auto">
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
||||||
@@ -240,7 +230,19 @@ export const CreateLocationForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button type="submit" size="small" isLoading={isPending}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -8,6 +8,7 @@ import * as zod from "zod"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { CountrySelect } from "../../../../../components/inputs/country-select"
|
import { CountrySelect } from "../../../../../components/inputs/country-select"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateStockLocation } from "../../../../../hooks/api/stock-locations"
|
import { useUpdateStockLocation } from "../../../../../hooks/api/stock-locations"
|
||||||
|
|
||||||
type EditLocationFormProps = {
|
type EditLocationFormProps = {
|
||||||
@@ -73,7 +74,7 @@ export const EditLocationForm = ({ location }: EditLocationFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -228,7 +229,7 @@ export const EditLocationForm = ({ location }: EditLocationFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+54
-55
@@ -8,14 +8,18 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { InlineTip } from "../../../../../components/common/inline-tip"
|
import { InlineTip } from "../../../../../components/common/inline-tip"
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
|
StackedFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
import { useCreateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
||||||
import { GeoZoneForm } from "../../../common/components/geo-zone-form"
|
import { GeoZoneForm } from "../../../common/components/geo-zone-form"
|
||||||
import { FulfillmentSetType } from "../../../common/constants"
|
import {
|
||||||
|
FulfillmentSetType,
|
||||||
|
GEO_ZONE_STACKED_MODAL_ID,
|
||||||
|
} from "../../../common/constants"
|
||||||
|
|
||||||
const CreateServiceZoneSchema = z.object({
|
const CreateServiceZoneSchema = z.object({
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
@@ -80,11 +84,55 @@ export function CreateServiceZoneForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
|
<RouteFocusModal.Body className="flex flex-1 flex-col items-center overflow-auto">
|
||||||
|
<StackedFocusModal id={GEO_ZONE_STACKED_MODAL_ID}>
|
||||||
|
<div className="flex flex-1 flex-col items-center">
|
||||||
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
||||||
|
<Heading>
|
||||||
|
{type === FulfillmentSetType.Pickup
|
||||||
|
? t("stockLocations.serviceZones.create.headerPickup", {
|
||||||
|
location: location.name,
|
||||||
|
})
|
||||||
|
: t("stockLocations.serviceZones.create.headerShipping", {
|
||||||
|
location: location.name,
|
||||||
|
})}
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
|
<Form.Field
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => {
|
||||||
|
return (
|
||||||
|
<Form.Item>
|
||||||
|
<Form.Label>{t("fields.name")}</Form.Label>
|
||||||
|
<Form.Control>
|
||||||
|
<Input {...field} />
|
||||||
|
</Form.Control>
|
||||||
|
<Form.ErrorMessage />
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<InlineTip>
|
||||||
|
{t("stockLocations.serviceZones.fields.tip")}
|
||||||
|
</InlineTip>
|
||||||
|
|
||||||
|
<GeoZoneForm form={form} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<GeoZoneForm.AreaDrawer form={form} />
|
||||||
|
</StackedFocusModal>
|
||||||
|
</RouteFocusModal.Body>
|
||||||
|
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
<RouteFocusModal.Close asChild>
|
||||||
<Button variant="secondary" size="small">
|
<Button variant="secondary" size="small">
|
||||||
@@ -95,57 +143,8 @@ export function CreateServiceZoneForm({
|
|||||||
{t("actions.save")}
|
{t("actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
<RouteFocusModal.Body className="m-auto flex h-full w-full flex-col items-center divide-y overflow-hidden">
|
|
||||||
<SplitView open={open} onOpenChange={setOpen}>
|
|
||||||
<SplitView.Content>
|
|
||||||
<div className="flex flex-1 flex-col items-center overflow-y-auto">
|
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
|
||||||
<Heading>
|
|
||||||
{type === FulfillmentSetType.Pickup
|
|
||||||
? t("stockLocations.serviceZones.create.headerPickup", {
|
|
||||||
location: location.name,
|
|
||||||
})
|
|
||||||
: t("stockLocations.serviceZones.create.headerShipping", {
|
|
||||||
location: location.name,
|
|
||||||
})}
|
|
||||||
</Heading>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
||||||
<Form.Field
|
|
||||||
control={form.control}
|
|
||||||
name="name"
|
|
||||||
render={({ field }) => {
|
|
||||||
return (
|
|
||||||
<Form.Item>
|
|
||||||
<Form.Label>{t("fields.name")}</Form.Label>
|
|
||||||
<Form.Control>
|
|
||||||
<Input {...field} />
|
|
||||||
</Form.Control>
|
|
||||||
<Form.ErrorMessage />
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<InlineTip>
|
|
||||||
{t("stockLocations.serviceZones.fields.tip")}
|
|
||||||
</InlineTip>
|
|
||||||
|
|
||||||
<GeoZoneForm form={form} onOpenChange={setOpen} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SplitView.Content>
|
|
||||||
<GeoZoneForm.AreaDrawer
|
|
||||||
form={form}
|
|
||||||
open={open}
|
|
||||||
onOpenChange={setOpen}
|
|
||||||
/>
|
|
||||||
</SplitView>
|
|
||||||
</RouteFocusModal.Body>
|
|
||||||
</form>
|
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+7
-3
@@ -7,6 +7,7 @@ import * as zod from "zod"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { InlineTip } from "../../../../../components/common/inline-tip"
|
import { InlineTip } from "../../../../../components/common/inline-tip"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
import { useUpdateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
||||||
|
|
||||||
type EditServiceZoneFormProps = {
|
type EditServiceZoneFormProps = {
|
||||||
@@ -59,8 +60,11 @@ export const EditServiceZoneForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm
|
||||||
<RouteDrawer.Body>
|
onSubmit={handleSubmit}
|
||||||
|
className="flex size-full flex-col overflow-hidden"
|
||||||
|
>
|
||||||
|
<RouteDrawer.Body className="flex-1 overflow-auto">
|
||||||
<div className="flex flex-col gap-y-8">
|
<div className="flex flex-col gap-y-8">
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -94,7 +98,7 @@ export const EditServiceZoneForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+25
-29
@@ -1,19 +1,20 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import { HttpTypes } from "@medusajs/types"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import { Button, Heading, toast } from "@medusajs/ui"
|
import { Button, Heading, toast } from "@medusajs/ui"
|
||||||
import { useState } from "react"
|
|
||||||
import { useForm } 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 { z } from "zod"
|
||||||
|
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
|
StackedFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
import { useUpdateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
||||||
import { countries } from "../../../../../lib/data/countries"
|
import { countries } from "../../../../../lib/data/countries"
|
||||||
import { GeoZoneForm } from "../../../common/components/geo-zone-form"
|
import { GeoZoneForm } from "../../../common/components/geo-zone-form"
|
||||||
|
import { GEO_ZONE_STACKED_MODAL_ID } from "../../../common/constants"
|
||||||
|
|
||||||
const EditeServiceZoneSchema = z.object({
|
const EditeServiceZoneSchema = z.object({
|
||||||
countries: z
|
countries: z
|
||||||
@@ -34,7 +35,6 @@ export function EditServiceZoneAreasForm({
|
|||||||
}: EditServiceZoneAreasFormProps) {
|
}: EditServiceZoneAreasFormProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { handleSuccess } = useRouteModal()
|
const { handleSuccess } = useRouteModal()
|
||||||
const [open, setOpen] = useState(false)
|
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof EditeServiceZoneSchema>>({
|
const form = useForm<z.infer<typeof EditeServiceZoneSchema>>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -80,11 +80,29 @@ export function EditServiceZoneAreasForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
|
|
||||||
|
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-auto">
|
||||||
|
<StackedFocusModal id={GEO_ZONE_STACKED_MODAL_ID}>
|
||||||
|
<div className="flex flex-col items-center p-16">
|
||||||
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||||
|
<Heading>
|
||||||
|
{t("stockLocations.serviceZones.manageAreas.header", {
|
||||||
|
name: zone.name,
|
||||||
|
})}
|
||||||
|
</Heading>
|
||||||
|
<GeoZoneForm form={form} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<GeoZoneForm.AreaDrawer form={form} />
|
||||||
|
</StackedFocusModal>
|
||||||
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
<RouteFocusModal.Close asChild>
|
||||||
<Button variant="secondary" size="small">
|
<Button variant="secondary" size="small">
|
||||||
@@ -95,30 +113,8 @@ export function EditServiceZoneAreasForm({
|
|||||||
{t("actions.save")}
|
{t("actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
|
||||||
<SplitView open={open} onOpenChange={setOpen}>
|
|
||||||
<SplitView.Content>
|
|
||||||
<div className="flex flex-col items-center p-16">
|
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
|
||||||
<Heading>
|
|
||||||
{t("stockLocations.serviceZones.manageAreas.header", {
|
|
||||||
name: zone.name,
|
|
||||||
})}
|
|
||||||
</Heading>
|
|
||||||
<GeoZoneForm form={form} onOpenChange={setOpen} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SplitView.Content>
|
|
||||||
<GeoZoneForm.AreaDrawer
|
|
||||||
form={form}
|
|
||||||
open={open}
|
|
||||||
onOpenChange={setOpen}
|
|
||||||
/>
|
|
||||||
</SplitView>
|
|
||||||
</RouteFocusModal.Body>
|
|
||||||
</form>
|
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+23
-20
@@ -9,6 +9,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
import { useCreateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
||||||
import { castNumber } from "../../../../../lib/cast-number"
|
import { castNumber } from "../../../../../lib/cast-number"
|
||||||
import { ShippingOptionPriceType } from "../../../common/constants"
|
import { ShippingOptionPriceType } from "../../../common/constants"
|
||||||
@@ -197,7 +198,7 @@ export function CreateShippingOptionsForm({
|
|||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onValueChange={(tab) => onTabChange(tab as Tab)}
|
onValueChange={(tab) => onTabChange(tab as Tab)}
|
||||||
>
|
>
|
||||||
<form className="flex h-full flex-col" onSubmit={handleSubmit}>
|
<KeyboundForm className="flex h-full flex-col" onSubmit={handleSubmit}>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
<ProgressTabs.List className="border-ui-border-base -my-2 ml-2 min-w-0 flex-1 border-l">
|
<ProgressTabs.List className="border-ui-border-base -my-2 ml-2 min-w-0 flex-1 border-l">
|
||||||
<ProgressTabs.Trigger
|
<ProgressTabs.Trigger
|
||||||
@@ -221,6 +222,25 @@ export function CreateShippingOptionsForm({
|
|||||||
</ProgressTabs.Trigger>
|
</ProgressTabs.Trigger>
|
||||||
)}
|
)}
|
||||||
</ProgressTabs.List>
|
</ProgressTabs.List>
|
||||||
|
</RouteFocusModal.Header>
|
||||||
|
|
||||||
|
<RouteFocusModal.Body className="size-full overflow-hidden">
|
||||||
|
<ProgressTabs.Content
|
||||||
|
value={Tab.DETAILS}
|
||||||
|
className="size-full overflow-y-auto"
|
||||||
|
>
|
||||||
|
<CreateShippingOptionDetailsForm
|
||||||
|
form={form}
|
||||||
|
zone={zone}
|
||||||
|
isReturn={isReturn}
|
||||||
|
locationId={locationId}
|
||||||
|
/>
|
||||||
|
</ProgressTabs.Content>
|
||||||
|
<ProgressTabs.Content value={Tab.PRICING} className="size-full">
|
||||||
|
<CreateShippingOptionsPricesForm form={form} />
|
||||||
|
</ProgressTabs.Content>
|
||||||
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
<RouteFocusModal.Close asChild>
|
||||||
<Button variant="secondary" size="small">
|
<Button variant="secondary" size="small">
|
||||||
@@ -250,25 +270,8 @@ export function CreateShippingOptionsForm({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
<RouteFocusModal.Body className="size-full overflow-hidden">
|
|
||||||
<ProgressTabs.Content
|
|
||||||
value={Tab.DETAILS}
|
|
||||||
className="size-full overflow-y-auto"
|
|
||||||
>
|
|
||||||
<CreateShippingOptionDetailsForm
|
|
||||||
form={form}
|
|
||||||
zone={zone}
|
|
||||||
isReturn={isReturn}
|
|
||||||
locationId={locationId}
|
|
||||||
/>
|
|
||||||
</ProgressTabs.Content>
|
|
||||||
<ProgressTabs.Content value={Tab.PRICING} className="size-full">
|
|
||||||
<CreateShippingOptionsPricesForm form={form} />
|
|
||||||
</ProgressTabs.Content>
|
|
||||||
</RouteFocusModal.Body>
|
|
||||||
</form>
|
|
||||||
</ProgressTabs>
|
</ProgressTabs>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-2
@@ -9,6 +9,7 @@ import { Form } from "../../../../../components/common/form"
|
|||||||
import { SwitchBox } from "../../../../../components/common/switch-box"
|
import { SwitchBox } from "../../../../../components/common/switch-box"
|
||||||
import { Combobox } from "../../../../../components/inputs/combobox"
|
import { Combobox } from "../../../../../components/inputs/combobox"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
import { useUpdateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
||||||
import { useComboboxData } from "../../../../../hooks/use-combobox-data"
|
import { useComboboxData } from "../../../../../hooks/use-combobox-data"
|
||||||
import { sdk } from "../../../../../lib/client"
|
import { sdk } from "../../../../../lib/client"
|
||||||
@@ -121,7 +122,7 @@ export const EditShippingOptionForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-8">
|
<div className="flex flex-col gap-y-8">
|
||||||
<div className="flex flex-col gap-y-8">
|
<div className="flex flex-col gap-y-8">
|
||||||
@@ -266,7 +267,7 @@ export const EditShippingOptionForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -12,6 +12,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals/index"
|
} from "../../../../../components/modals/index"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { usePricePreferences } from "../../../../../hooks/api/price-preferences"
|
import { usePricePreferences } from "../../../../../hooks/api/price-preferences"
|
||||||
import { useRegions } from "../../../../../hooks/api/regions"
|
import { useRegions } from "../../../../../hooks/api/regions"
|
||||||
import { useUpdateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
import { useUpdateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
||||||
@@ -225,7 +226,7 @@ export function EditShippingOptionsPricingForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -260,7 +261,7 @@ export function EditShippingOptionsPricingForm({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import * as z from "zod"
|
|||||||
|
|
||||||
import { Form } from "../../components/common/form"
|
import { Form } from "../../components/common/form"
|
||||||
import AvatarBox from "../../components/common/logo-box/avatar-box"
|
import AvatarBox from "../../components/common/logo-box/avatar-box"
|
||||||
|
import { KeyboundForm } from "../../components/utilities/keybound-form"
|
||||||
import { useDashboardExtension } from "../../extensions"
|
import { useDashboardExtension } from "../../extensions"
|
||||||
import { useSignInWithEmailPass } from "../../hooks/api"
|
import { useSignInWithEmailPass } from "../../hooks/api"
|
||||||
import { isFetchError } from "../../lib/is-fetch-error"
|
import { isFetchError } from "../../lib/is-fetch-error"
|
||||||
@@ -85,7 +86,7 @@ export const Login = () => {
|
|||||||
return <Component key={i} />
|
return <Component key={i} />
|
||||||
})}
|
})}
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex w-full flex-col gap-y-6"
|
className="flex w-full flex-col gap-y-6"
|
||||||
>
|
>
|
||||||
@@ -148,7 +149,7 @@ export const Login = () => {
|
|||||||
<Button className="w-full" type="submit" isLoading={isPending}>
|
<Button className="w-full" type="submit" isLoading={isPending}>
|
||||||
{t("actions.continueWithEmail")}
|
{t("actions.continueWithEmail")}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</Form>
|
</Form>
|
||||||
{getWidgets("login.after").map((Component, i) => {
|
{getWidgets("login.after").map((Component, i) => {
|
||||||
return <Component key={i} />
|
return <Component key={i} />
|
||||||
|
|||||||
+27
-25
@@ -7,17 +7,18 @@ import { AdminOrder, InventoryItemDTO, OrderLineItemDTO } from "@medusajs/types"
|
|||||||
import { Alert, Button, Heading, Input, Select, toast } from "@medusajs/ui"
|
import { Alert, Button, Heading, Input, Select, toast } from "@medusajs/ui"
|
||||||
import { useForm, useWatch } from "react-hook-form"
|
import { useForm, useWatch } from "react-hook-form"
|
||||||
|
|
||||||
|
import { Form } from "../../../../../components/common/form"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useStockLocations } from "../../../../../hooks/api/stock-locations"
|
|
||||||
import { useCreateReservationItem } from "../../../../../hooks/api/reservations"
|
|
||||||
import { OrderAllocateItemsItem } from "./order-allocate-items-item"
|
|
||||||
import { AllocateItemsSchema } from "./constants"
|
|
||||||
import { queryClient } from "../../../../../lib/query-client"
|
|
||||||
import { ordersQueryKeys } from "../../../../../hooks/api/orders"
|
import { ordersQueryKeys } from "../../../../../hooks/api/orders"
|
||||||
|
import { useCreateReservationItem } from "../../../../../hooks/api/reservations"
|
||||||
|
import { useStockLocations } from "../../../../../hooks/api/stock-locations"
|
||||||
|
import { queryClient } from "../../../../../lib/query-client"
|
||||||
|
import { AllocateItemsSchema } from "./constants"
|
||||||
|
import { OrderAllocateItemsItem } from "./order-allocate-items-item"
|
||||||
|
|
||||||
type OrderAllocateItemsFormProps = {
|
type OrderAllocateItemsFormProps = {
|
||||||
order: AdminOrder
|
order: AdminOrder
|
||||||
@@ -192,27 +193,11 @@ export function OrderAllocateItemsForm({ order }: OrderAllocateItemsFormProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
type="submit"
|
|
||||||
isLoading={isMutating}
|
|
||||||
disabled={!selectedLocationId || disableSubmit}
|
|
||||||
>
|
|
||||||
{t("orders.allocateItems.action")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex h-full w-full flex-col items-center divide-y overflow-y-auto">
|
<RouteFocusModal.Body className="flex h-full w-full flex-col items-center divide-y overflow-y-auto">
|
||||||
<div className="flex size-full flex-col items-center overflow-auto p-16">
|
<div className="flex size-full flex-col items-center overflow-auto p-16">
|
||||||
<div className="flex w-full max-w-[736px] flex-col justify-center px-2 pb-2">
|
<div className="flex w-full max-w-[736px] flex-col justify-center px-2 pb-2">
|
||||||
@@ -302,7 +287,24 @@ export function OrderAllocateItemsForm({ order }: OrderAllocateItemsFormProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="submit"
|
||||||
|
isLoading={isMutating}
|
||||||
|
disabled={!selectedLocationId || disableSubmit}
|
||||||
|
>
|
||||||
|
{t("orders.allocateItems.action")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -38,6 +38,7 @@ import { ClaimInboundItem } from "./claim-inbound-item.tsx"
|
|||||||
import { ClaimCreateSchema, CreateClaimSchemaType } from "./schema"
|
import { ClaimCreateSchema, CreateClaimSchemaType } from "./schema"
|
||||||
|
|
||||||
import { AdminReturn, HttpTypes } from "@medusajs/types"
|
import { AdminReturn, HttpTypes } from "@medusajs/types"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form/keybound-form.tsx"
|
||||||
import {
|
import {
|
||||||
useAddClaimInboundItems,
|
useAddClaimInboundItems,
|
||||||
useAddClaimInboundShipping,
|
useAddClaimInboundShipping,
|
||||||
@@ -430,7 +431,7 @@ export const ClaimCreateForm = ({
|
|||||||
(a) => a.action === "SHIPPING_ADD" && !!a.return_id
|
(a) => a.action === "SHIPPING_ADD" && !!a.return_id
|
||||||
)
|
)
|
||||||
|
|
||||||
return action && !!!action?.return_id
|
return action && !action?.return_id
|
||||||
})
|
})
|
||||||
|
|
||||||
const promises = inboundShippingMethods
|
const promises = inboundShippingMethods
|
||||||
@@ -557,9 +558,8 @@ export const ClaimCreateForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header />
|
||||||
|
|
||||||
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
||||||
<div className="mt-16 w-[720px] max-w-[100%] px-4 md:p-0">
|
<div className="mt-16 w-[720px] max-w-[100%] px-4 md:p-0">
|
||||||
<Heading level="h1">{t("orders.claims.create")}</Heading>
|
<Heading level="h1">{t("orders.claims.create")}</Heading>
|
||||||
@@ -676,7 +676,7 @@ export const ClaimCreateForm = ({
|
|||||||
)}
|
)}
|
||||||
{!showInboundItemsPlaceholder && (
|
{!showInboundItemsPlaceholder && (
|
||||||
<div className="mt-8 flex flex-col gap-y-4">
|
<div className="mt-8 flex flex-col gap-y-4">
|
||||||
{/*LOCATION*/}
|
{/* LOCATION*/}
|
||||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
<Form.Label>{t("orders.returns.location")}</Form.Label>
|
<Form.Label>{t("orders.returns.location")}</Form.Label>
|
||||||
@@ -713,7 +713,7 @@ export const ClaimCreateForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*INBOUND SHIPPING*/}
|
{/* INBOUND SHIPPING*/}
|
||||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
@@ -721,7 +721,7 @@ export const ClaimCreateForm = ({
|
|||||||
<Text
|
<Text
|
||||||
size="small"
|
size="small"
|
||||||
leading="compact"
|
leading="compact"
|
||||||
className="text-ui-fg-muted inline ml-1"
|
className="text-ui-fg-muted ml-1 inline"
|
||||||
>
|
>
|
||||||
({t("fields.optional")})
|
({t("fields.optional")})
|
||||||
</Text>
|
</Text>
|
||||||
@@ -732,7 +732,7 @@ export const ClaimCreateForm = ({
|
|||||||
</Form.Hint>
|
</Form.Hint>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/}
|
{/* TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/}
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="inbound_option_id"
|
name="inbound_option_id"
|
||||||
@@ -782,7 +782,7 @@ export const ClaimCreateForm = ({
|
|||||||
claim={claim}
|
claim={claim}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/*TOTALS SECTION*/}
|
{/* TOTALS SECTION*/}
|
||||||
<div className="mt-8 border-y border-dotted py-4">
|
<div className="mt-8 border-y border-dotted py-4">
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<span className="txt-small text-ui-fg-subtle">
|
<span className="txt-small text-ui-fg-subtle">
|
||||||
@@ -983,7 +983,7 @@ export const ClaimCreateForm = ({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/*SEND NOTIFICATION*/}
|
{/* SEND NOTIFICATION*/}
|
||||||
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -1044,7 +1044,7 @@ export const ClaimCreateForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+6
-5
@@ -10,6 +10,7 @@ import {
|
|||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
useCancelOrderEdit,
|
useCancelOrderEdit,
|
||||||
useRequestOrderEdit,
|
useRequestOrderEdit,
|
||||||
@@ -98,7 +99,7 @@ export const OrderEditCreateForm = ({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header />
|
||||||
|
|
||||||
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
||||||
@@ -107,7 +108,7 @@ export const OrderEditCreateForm = ({
|
|||||||
|
|
||||||
<OrderEditItemsSection preview={preview} order={order} />
|
<OrderEditItemsSection preview={preview} order={order} />
|
||||||
|
|
||||||
{/*TOTALS SECTION*/}
|
{/* TOTALS SECTION*/}
|
||||||
<div className="mt-8 border-y border-dotted py-4">
|
<div className="mt-8 border-y border-dotted py-4">
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<span className="txt-small text-ui-fg-subtle">
|
<span className="txt-small text-ui-fg-subtle">
|
||||||
@@ -142,7 +143,7 @@ export const OrderEditCreateForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*NOTE*/}
|
{/* NOTE*/}
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="note"
|
name="note"
|
||||||
@@ -167,7 +168,7 @@ export const OrderEditCreateForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/*SEND NOTIFICATION*/}
|
{/* SEND NOTIFICATION*/}
|
||||||
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -223,7 +224,7 @@ export const OrderEditCreateForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+5
-4
@@ -24,6 +24,7 @@ import { getStylizedAmount } from "../../../../../lib/money-amount-helpers"
|
|||||||
import { CreateExchangeSchemaType, ExchangeCreateSchema } from "./schema"
|
import { CreateExchangeSchemaType, ExchangeCreateSchema } from "./schema"
|
||||||
|
|
||||||
import { AdminReturn } from "@medusajs/types"
|
import { AdminReturn } from "@medusajs/types"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form/keybound-form.tsx"
|
||||||
import {
|
import {
|
||||||
useCancelExchangeRequest,
|
useCancelExchangeRequest,
|
||||||
useExchangeConfirmRequest,
|
useExchangeConfirmRequest,
|
||||||
@@ -253,7 +254,7 @@ export const ExchangeCreateForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header />
|
||||||
|
|
||||||
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
||||||
@@ -275,7 +276,7 @@ export const ExchangeCreateForm = ({
|
|||||||
exchange={exchange}
|
exchange={exchange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/*TOTALS SECTION*/}
|
{/* TOTALS SECTION*/}
|
||||||
<div className="mt-8 border-y border-dotted py-4">
|
<div className="mt-8 border-y border-dotted py-4">
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<span className="txt-small text-ui-fg-subtle">
|
<span className="txt-small text-ui-fg-subtle">
|
||||||
@@ -476,7 +477,7 @@ export const ExchangeCreateForm = ({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/*SEND NOTIFICATION*/}
|
{/* SEND NOTIFICATION*/}
|
||||||
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -538,7 +539,7 @@ export const ExchangeCreateForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+13
-18
@@ -14,6 +14,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateOrderFulfillment } from "../../../../../hooks/api/orders"
|
import { useCreateOrderFulfillment } from "../../../../../hooks/api/orders"
|
||||||
import { useStockLocations } from "../../../../../hooks/api/stock-locations"
|
import { useStockLocations } from "../../../../../hooks/api/stock-locations"
|
||||||
import { getFulfillableQuantity } from "../../../../../lib/order-item"
|
import { getFulfillableQuantity } from "../../../../../lib/order-item"
|
||||||
@@ -46,13 +47,10 @@ export function OrderCreateFulfillmentForm({
|
|||||||
|
|
||||||
const form = useForm<zod.infer<typeof CreateFulfillmentSchema>>({
|
const form = useForm<zod.infer<typeof CreateFulfillmentSchema>>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
quantity: fulfillableItems.reduce(
|
quantity: fulfillableItems.reduce((acc, item) => {
|
||||||
(acc, item) => {
|
acc[item.id] = getFulfillableQuantity(item)
|
||||||
acc[item.id] = getFulfillableQuantity(item)
|
return acc
|
||||||
return acc
|
}, {} as Record<string, number>),
|
||||||
},
|
|
||||||
{} as Record<string, number>
|
|
||||||
),
|
|
||||||
send_notification: !order.no_notification,
|
send_notification: !order.no_notification,
|
||||||
},
|
},
|
||||||
resolver: zodResolver(CreateFulfillmentSchema),
|
resolver: zodResolver(CreateFulfillmentSchema),
|
||||||
@@ -117,20 +115,17 @@ export function OrderCreateFulfillmentForm({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const quantityMap = itemsToFulfill.reduce(
|
const quantityMap = itemsToFulfill.reduce((acc, item) => {
|
||||||
(acc, item) => {
|
acc[item.id] = getFulfillableQuantity(item as OrderLineItemDTO)
|
||||||
acc[item.id] = getFulfillableQuantity(item as OrderLineItemDTO)
|
return acc
|
||||||
return acc
|
}, {} as Record<string, number>)
|
||||||
},
|
|
||||||
{} as Record<string, number>
|
|
||||||
)
|
|
||||||
|
|
||||||
form.setValue("quantity", quantityMap)
|
form.setValue("quantity", quantityMap)
|
||||||
}, [...fulfilledQuantityArray, requiresShipping])
|
}, [...fulfilledQuantityArray, requiresShipping])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -192,7 +187,7 @@ export function OrderCreateFulfillmentForm({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*<div className="py-8">*/}
|
{/* <div className="py-8">*/}
|
||||||
{/* <Form.Field*/}
|
{/* <Form.Field*/}
|
||||||
{/* control={form.control}*/}
|
{/* control={form.control}*/}
|
||||||
{/* name="shipping_option_id"*/}
|
{/* name="shipping_option_id"*/}
|
||||||
@@ -233,7 +228,7 @@ export function OrderCreateFulfillmentForm({
|
|||||||
{/* )*/}
|
{/* )*/}
|
||||||
{/* }}*/}
|
{/* }}*/}
|
||||||
{/* />*/}
|
{/* />*/}
|
||||||
{/*</div>*/}
|
{/* </div>*/}
|
||||||
<div>
|
<div>
|
||||||
<Form.Item className="mt-8">
|
<Form.Item className="mt-8">
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
@@ -302,7 +297,7 @@ export function OrderCreateFulfillmentForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+8
-4
@@ -15,6 +15,7 @@ import { useNavigate, useSearchParams } from "react-router-dom"
|
|||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useRefundPayment } from "../../../../../hooks/api"
|
import { useRefundPayment } from "../../../../../hooks/api"
|
||||||
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
||||||
import { formatCurrency } from "../../../../../lib/format-currency"
|
import { formatCurrency } from "../../../../../lib/format-currency"
|
||||||
@@ -95,8 +96,11 @@ export const CreateRefundForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm
|
||||||
<RouteDrawer.Body>
|
onSubmit={handleSubmit}
|
||||||
|
className="flex size-full flex-col overflow-hidden"
|
||||||
|
>
|
||||||
|
<RouteDrawer.Body className="flex-1 overflow-auto">
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
<Select
|
<Select
|
||||||
value={payment?.id}
|
value={payment?.id}
|
||||||
@@ -106,7 +110,7 @@ export const CreateRefundForm = ({
|
|||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Label className="font-sans txt-compact-small font-medium mb-[-6px]">
|
<Label className="txt-compact-small mb-[-6px] font-sans font-medium">
|
||||||
{t("orders.payment.selectPaymentToRefund")}
|
{t("orders.payment.selectPaymentToRefund")}
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
@@ -247,7 +251,7 @@ export const CreateRefundForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+10
-10
@@ -30,6 +30,7 @@ import {
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { Combobox } from "../../../../../components/inputs/combobox"
|
import { Combobox } from "../../../../../components/inputs/combobox"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
useAddReturnItem,
|
useAddReturnItem,
|
||||||
useAddReturnShipping,
|
useAddReturnShipping,
|
||||||
@@ -402,9 +403,8 @@ export const ReturnCreateForm = ({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header />
|
||||||
|
|
||||||
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
<RouteFocusModal.Body className="flex size-full justify-center overflow-y-auto">
|
||||||
<div className="mt-16 w-[720px] max-w-[100%] px-4 md:p-0">
|
<div className="mt-16 w-[720px] max-w-[100%] px-4 md:p-0">
|
||||||
<Heading level="h1">{t("orders.returns.create")}</Heading>
|
<Heading level="h1">{t("orders.returns.create")}</Heading>
|
||||||
@@ -508,7 +508,7 @@ export const ReturnCreateForm = ({
|
|||||||
))}
|
))}
|
||||||
{!showPlaceholder && (
|
{!showPlaceholder && (
|
||||||
<div className="mt-8 flex flex-col gap-y-4">
|
<div className="mt-8 flex flex-col gap-y-4">
|
||||||
{/*LOCATION*/}
|
{/* LOCATION*/}
|
||||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
<Form.Label>{t("orders.returns.location")}</Form.Label>
|
<Form.Label>{t("orders.returns.location")}</Form.Label>
|
||||||
@@ -545,7 +545,7 @@ export const ReturnCreateForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*INBOUND SHIPPING*/}
|
{/* INBOUND SHIPPING*/}
|
||||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
@@ -553,7 +553,7 @@ export const ReturnCreateForm = ({
|
|||||||
<Text
|
<Text
|
||||||
size="small"
|
size="small"
|
||||||
leading="compact"
|
leading="compact"
|
||||||
className="text-ui-fg-muted inline ml-1"
|
className="text-ui-fg-muted ml-1 inline"
|
||||||
>
|
>
|
||||||
({t("fields.optional")})
|
({t("fields.optional")})
|
||||||
</Text>
|
</Text>
|
||||||
@@ -564,7 +564,7 @@ export const ReturnCreateForm = ({
|
|||||||
</Form.Hint>
|
</Form.Hint>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/}
|
{/* TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/}
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="option_id"
|
name="option_id"
|
||||||
@@ -621,7 +621,7 @@ export const ReturnCreateForm = ({
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/*TOTALS SECTION*/}
|
{/* TOTALS SECTION*/}
|
||||||
<div className="mt-8 border-y border-dotted py-4">
|
<div className="mt-8 border-y border-dotted py-4">
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<span className="txt-small text-ui-fg-subtle">
|
<span className="txt-small text-ui-fg-subtle">
|
||||||
@@ -658,7 +658,7 @@ export const ReturnCreateForm = ({
|
|||||||
|
|
||||||
preview.shipping_methods.forEach((s) => {
|
preview.shipping_methods.forEach((s) => {
|
||||||
if (s.actions) {
|
if (s.actions) {
|
||||||
for (let a of s.actions) {
|
for (const a of s.actions) {
|
||||||
if (a.action === "SHIPPING_ADD") {
|
if (a.action === "SHIPPING_ADD") {
|
||||||
actionId = a.id
|
actionId = a.id
|
||||||
}
|
}
|
||||||
@@ -707,7 +707,7 @@ export const ReturnCreateForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*SEND NOTIFICATION*/}
|
{/* SEND NOTIFICATION*/}
|
||||||
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
<div className="bg-ui-bg-field mt-8 rounded-lg border py-2 pl-2 pr-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -763,7 +763,7 @@ export const ReturnCreateForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -11,6 +11,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateOrderShipment } from "../../../../../hooks/api"
|
import { useCreateOrderShipment } from "../../../../../hooks/api"
|
||||||
import { CreateShipmentSchema } from "./constants"
|
import { CreateShipmentSchema } from "./constants"
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ export function OrderCreateShipmentForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -163,7 +164,7 @@ export function OrderCreateShipmentForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -8,6 +8,7 @@ import { z } from "zod"
|
|||||||
import { AdminOrder } from "@medusajs/types"
|
import { AdminOrder } from "@medusajs/types"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
|
|
||||||
type OrderNoteFormProps = {
|
type OrderNoteFormProps = {
|
||||||
order: AdminOrder
|
order: AdminOrder
|
||||||
@@ -64,7 +65,7 @@ export const OrderNoteForm = ({ order }: OrderNoteFormProps) => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={handleSubmit}>
|
<KeyboundForm onSubmit={handleSubmit}>
|
||||||
<div className="bg-ui-bg-field shadow-borders-base flex flex-col gap-y-2 rounded-md px-2 py-1.5">
|
<div className="bg-ui-bg-field shadow-borders-base flex flex-col gap-y-2 rounded-md px-2 py-1.5">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -104,7 +105,7 @@ export const OrderNoteForm = ({ order }: OrderNoteFormProps) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-3
@@ -10,6 +10,7 @@ import * as zod from "zod"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useStockLocation } from "../../../../../hooks/api"
|
import { useStockLocation } from "../../../../../hooks/api"
|
||||||
import {
|
import {
|
||||||
useAddReceiveItems,
|
useAddReceiveItems,
|
||||||
@@ -209,7 +210,7 @@ export function OrderReceiveReturnForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form} onClose={onFormClose}>
|
<RouteDrawer.Form form={form} onClose={onFormClose}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -305,7 +306,7 @@ export function OrderReceiveReturnForm({
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{/*TOTALS*/}
|
{/* TOTALS*/}
|
||||||
|
|
||||||
<div className="my-6 border-b border-t border-dashed py-4">
|
<div className="my-6 border-b border-t border-dashed py-4">
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
@@ -378,7 +379,7 @@ export function OrderReceiveReturnForm({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -19,6 +19,7 @@ import { Form } from "../../../../../components/common/form"
|
|||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
import { StackedDrawer } from "../../../../../components/modals/stacked-drawer"
|
import { StackedDrawer } from "../../../../../components/modals/stacked-drawer"
|
||||||
import { useStackedModal } from "../../../../../components/modals/stacked-modal-provider"
|
import { useStackedModal } from "../../../../../components/modals/stacked-modal-provider"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdatePriceList } from "../../../../../hooks/api/price-lists"
|
import { useUpdatePriceList } from "../../../../../hooks/api/price-lists"
|
||||||
import { PriceListCustomerGroupRuleForm } from "../../../common/components/price-list-customer-group-rule-form"
|
import { PriceListCustomerGroupRuleForm } from "../../../common/components/price-list-customer-group-rule-form"
|
||||||
import { PricingCustomerGroupsArrayType } from "../../../price-list-create/components/price-list-create-form/schema"
|
import { PricingCustomerGroupsArrayType } from "../../../price-list-create/components/price-list-create-form/schema"
|
||||||
@@ -120,7 +121,7 @@ export const PriceListConfigurationForm = ({
|
|||||||
<RouteDrawer.Description className="sr-only">
|
<RouteDrawer.Description className="sr-only">
|
||||||
{t("priceLists.configuration.edit.description")}
|
{t("priceLists.configuration.edit.description")}
|
||||||
</RouteDrawer.Description>
|
</RouteDrawer.Description>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -304,7 +305,7 @@ export const PriceListConfigurationForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+7
-9
@@ -10,6 +10,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreatePriceList } from "../../../../../hooks/api/price-lists"
|
import { useCreatePriceList } from "../../../../../hooks/api/price-lists"
|
||||||
import { exctractPricesFromProducts } from "../../../common/utils"
|
import { exctractPricesFromProducts } from "../../../common/utils"
|
||||||
import { PriceListDetailsForm } from "./price-list-details-form"
|
import { PriceListDetailsForm } from "./price-list-details-form"
|
||||||
@@ -119,13 +120,10 @@ export const PriceListCreateForm = ({
|
|||||||
) => {
|
) => {
|
||||||
form.clearErrors(fields)
|
form.clearErrors(fields)
|
||||||
|
|
||||||
const values = fields.reduce(
|
const values = fields.reduce((acc, key) => {
|
||||||
(acc, key) => {
|
acc[key] = form.getValues(key)
|
||||||
acc[key] = form.getValues(key)
|
return acc
|
||||||
return acc
|
}, {} as Record<string, unknown>)
|
||||||
},
|
|
||||||
{} as Record<string, unknown>
|
|
||||||
)
|
|
||||||
|
|
||||||
const validationResult = schema.safeParse(values)
|
const validationResult = schema.safeParse(values)
|
||||||
|
|
||||||
@@ -252,7 +250,7 @@ export const PriceListCreateForm = ({
|
|||||||
onValueChange={(tab) => handleChangeTab(tab as Tab)}
|
onValueChange={(tab) => handleChangeTab(tab as Tab)}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
<div className="flex w-full items-center justify-between gap-x-4">
|
<div className="flex w-full items-center justify-between gap-x-4">
|
||||||
<div className="-my-2 w-full max-w-[600px] border-l">
|
<div className="-my-2 w-full max-w-[600px] border-l">
|
||||||
@@ -318,7 +316,7 @@ export const PriceListCreateForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</ProgressTabs>
|
</ProgressTabs>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-2
@@ -14,6 +14,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdatePriceList } from "../../../../../hooks/api/price-lists"
|
import { useUpdatePriceList } from "../../../../../hooks/api/price-lists"
|
||||||
import { PriceListStatus, PriceListType } from "../../../common/constants"
|
import { PriceListStatus, PriceListType } from "../../../common/constants"
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ export const PriceListEditForm = ({ priceList }: PriceListEditFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -177,7 +178,7 @@ export const PriceListEditForm = ({ priceList }: PriceListEditFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -10,6 +10,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useBatchPriceListPrices } from "../../../../../hooks/api/price-lists"
|
import { useBatchPriceListPrices } from "../../../../../hooks/api/price-lists"
|
||||||
import { exctractPricesFromProducts } from "../../../common/utils"
|
import { exctractPricesFromProducts } from "../../../common/utils"
|
||||||
import { PriceListPricesAddPricesForm } from "./price-list-prices-add-prices-form"
|
import { PriceListPricesAddPricesForm } from "./price-list-prices-add-prices-form"
|
||||||
@@ -199,7 +200,7 @@ export const PriceListPricesAddForm = ({
|
|||||||
onValueChange={(tab) => handleChangeTab(tab as Tab)}
|
onValueChange={(tab) => handleChangeTab(tab as Tab)}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
<div className="flex w-full items-center justify-between gap-x-4">
|
<div className="flex w-full items-center justify-between gap-x-4">
|
||||||
<div className="-my-2 w-full max-w-[600px] border-l">
|
<div className="-my-2 w-full max-w-[600px] border-l">
|
||||||
@@ -256,7 +257,7 @@ export const PriceListPricesAddForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</ProgressTabs>
|
</ProgressTabs>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
+15
-23
@@ -11,6 +11,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useBatchPriceListPrices } from "../../../../../hooks/api/price-lists"
|
import { useBatchPriceListPrices } from "../../../../../hooks/api/price-lists"
|
||||||
import { castNumber } from "../../../../../lib/cast-number"
|
import { castNumber } from "../../../../../lib/cast-number"
|
||||||
import { usePriceListGridColumns } from "../../../common/hooks/use-price-list-grid-columns"
|
import { usePriceListGridColumns } from "../../../common/hooks/use-price-list-grid-columns"
|
||||||
@@ -89,7 +90,7 @@ export const PriceListPricesEditForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex size-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex size-full flex-col">
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header />
|
||||||
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
||||||
<DataGrid
|
<DataGrid
|
||||||
@@ -116,7 +117,7 @@ export const PriceListPricesEditForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -185,13 +186,10 @@ function convertToPriceArray(
|
|||||||
) {
|
) {
|
||||||
const prices: PriceObject[] = []
|
const prices: PriceObject[] = []
|
||||||
|
|
||||||
const regionCurrencyMap = regions.reduce(
|
const regionCurrencyMap = regions.reduce((map, region) => {
|
||||||
(map, region) => {
|
map[region.id] = region.currency_code
|
||||||
map[region.id] = region.currency_code
|
return map
|
||||||
return map
|
}, {} as Record<string, string>)
|
||||||
},
|
|
||||||
{} as Record<string, string>
|
|
||||||
)
|
|
||||||
|
|
||||||
for (const [_productId, product] of Object.entries(data || {})) {
|
for (const [_productId, product] of Object.entries(data || {})) {
|
||||||
const { variants } = product || {}
|
const { variants } = product || {}
|
||||||
@@ -249,21 +247,15 @@ function comparePrices(initialPrices: PriceObject[], newPrices: PriceObject[]) {
|
|||||||
const pricesToCreate: HttpTypes.AdminCreatePriceListPrice[] = []
|
const pricesToCreate: HttpTypes.AdminCreatePriceListPrice[] = []
|
||||||
const pricesToDelete: string[] = []
|
const pricesToDelete: string[] = []
|
||||||
|
|
||||||
const initialPriceMap = initialPrices.reduce(
|
const initialPriceMap = initialPrices.reduce((map, price) => {
|
||||||
(map, price) => {
|
map[createMapKey(price)] = price
|
||||||
map[createMapKey(price)] = price
|
return map
|
||||||
return map
|
}, {} as Record<string, (typeof initialPrices)[0]>)
|
||||||
},
|
|
||||||
{} as Record<string, (typeof initialPrices)[0]>
|
|
||||||
)
|
|
||||||
|
|
||||||
const newPriceMap = newPrices.reduce(
|
const newPriceMap = newPrices.reduce((map, price) => {
|
||||||
(map, price) => {
|
map[createMapKey(price)] = price
|
||||||
map[createMapKey(price)] = price
|
return map
|
||||||
return map
|
}, {} as Record<string, (typeof newPrices)[0]>)
|
||||||
},
|
|
||||||
{} as Record<string, (typeof newPrices)[0]>
|
|
||||||
)
|
|
||||||
|
|
||||||
const keys = new Set([
|
const keys = new Set([
|
||||||
...Object.keys(initialPriceMap),
|
...Object.keys(initialPriceMap),
|
||||||
|
|||||||
+3
-2
@@ -8,6 +8,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateProductTag } from "../../../../../hooks/api"
|
import { useCreateProductTag } from "../../../../../hooks/api"
|
||||||
|
|
||||||
const ProductTagCreateSchema = z.object({
|
const ProductTagCreateSchema = z.object({
|
||||||
@@ -45,7 +46,7 @@ export const ProductTagCreateForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -93,7 +94,7 @@ export const ProductTagCreateForm = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -7,6 +7,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProductTag } from "../../../../../hooks/api"
|
import { useUpdateProductTag } from "../../../../../hooks/api"
|
||||||
|
|
||||||
type ProductTagEditFormProps = {
|
type ProductTagEditFormProps = {
|
||||||
@@ -48,7 +49,7 @@ export const ProductTagEditForm = ({ productTag }: ProductTagEditFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -81,7 +82,7 @@ export const ProductTagEditForm = ({ productTag }: ProductTagEditFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+6
-2
@@ -8,6 +8,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateProductType } from "../../../../../hooks/api/product-types"
|
import { useCreateProductType } from "../../../../../hooks/api/product-types"
|
||||||
|
|
||||||
const CreateProductTypeSchema = z.object({
|
const CreateProductTypeSchema = z.object({
|
||||||
@@ -48,7 +49,10 @@ export const CreateProductTypeForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-col overflow-hidden">
|
<KeyboundForm
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
className="flex flex-col overflow-hidden"
|
||||||
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
<RouteFocusModal.Close asChild>
|
||||||
@@ -93,7 +97,7 @@ export const CreateProductTypeForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProductType } from "../../../../../hooks/api/product-types"
|
import { useUpdateProductType } from "../../../../../hooks/api/product-types"
|
||||||
|
|
||||||
const EditProductTypeSchema = z.object({
|
const EditProductTypeSchema = z.object({
|
||||||
@@ -54,7 +55,7 @@ export const EditProductTypeForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -87,7 +88,7 @@ export const EditProductTypeForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+9
-8
@@ -10,6 +10,7 @@ import { Form } from "../../../../../components/common/form"
|
|||||||
import { Combobox } from "../../../../../components/inputs/combobox"
|
import { Combobox } from "../../../../../components/inputs/combobox"
|
||||||
import { CountrySelect } from "../../../../../components/inputs/country-select"
|
import { CountrySelect } from "../../../../../components/inputs/country-select"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProductVariant } from "../../../../../hooks/api/products"
|
import { useUpdateProductVariant } from "../../../../../hooks/api/products"
|
||||||
import {
|
import {
|
||||||
transformNullableFormData,
|
transformNullableFormData,
|
||||||
@@ -48,23 +49,23 @@ export const ProductEditVariantForm = ({
|
|||||||
}: ProductEditVariantFormProps) => {
|
}: ProductEditVariantFormProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { handleSuccess } = useRouteModal()
|
const { handleSuccess } = useRouteModal()
|
||||||
const defaultOptions = product.options.reduce((acc: any, option: any) => {
|
const defaultOptions = product.options?.reduce((acc: any, option: any) => {
|
||||||
const varOpt = variant.options.find((o: any) => o.option_id === option.id)
|
const varOpt = variant.options?.find((o: any) => o.option_id === option.id)
|
||||||
acc[option.title] = varOpt?.value
|
acc[option.title] = varOpt?.value
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof ProductEditVariantSchema>>({
|
const form = useForm<z.infer<typeof ProductEditVariantSchema>>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
title: variant.title,
|
title: variant.title || "",
|
||||||
material: variant.material || "",
|
material: variant.material || "",
|
||||||
sku: variant.sku || "",
|
sku: variant.sku || "",
|
||||||
ean: variant.ean || "",
|
ean: variant.ean || "",
|
||||||
upc: variant.upc || "",
|
upc: variant.upc || "",
|
||||||
barcode: variant.barcode || "",
|
barcode: variant.barcode || "",
|
||||||
inventory_quantity: variant.inventory_quantity || "",
|
inventory_quantity: variant.inventory_quantity || "",
|
||||||
manage_inventory: variant.manage_inventory,
|
manage_inventory: variant.manage_inventory || false,
|
||||||
allow_backorder: variant.allow_backorder,
|
allow_backorder: variant.allow_backorder || false,
|
||||||
weight: variant.weight || "",
|
weight: variant.weight || "",
|
||||||
height: variant.height || "",
|
height: variant.height || "",
|
||||||
width: variant.width || "",
|
width: variant.width || "",
|
||||||
@@ -124,7 +125,7 @@ export const ProductEditVariantForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -160,7 +161,7 @@ export const ProductEditVariantForm = ({
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{product.options.map((option: any) => {
|
{product.options?.map((option: any) => {
|
||||||
return (
|
return (
|
||||||
<Form.Field
|
<Form.Field
|
||||||
key={option.id}
|
key={option.id}
|
||||||
@@ -438,7 +439,7 @@ export const ProductEditVariantForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -13,6 +13,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
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 { sdk } from "../../../../../lib/client"
|
import { sdk } from "../../../../../lib/client"
|
||||||
@@ -151,7 +152,7 @@ export function ManageVariantInventoryItemsForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -302,7 +303,7 @@ export function ManageVariantInventoryItemsForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -5,6 +5,7 @@ import * as zod from "zod"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { CountrySelect } from "../../../../../components/inputs/country-select"
|
import { CountrySelect } from "../../../../../components/inputs/country-select"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
FormExtensionZone,
|
FormExtensionZone,
|
||||||
useDashboardExtension,
|
useDashboardExtension,
|
||||||
@@ -85,7 +86,7 @@ export const ProductAttributesForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex h-full flex-col gap-y-8">
|
<div className="flex h-full flex-col gap-y-8">
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col gap-y-4">
|
||||||
@@ -266,7 +267,7 @@ export const ProductAttributesForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -8,6 +8,7 @@ import { HttpTypes } from "@medusajs/types"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { ChipInput } from "../../../../../components/inputs/chip-input"
|
import { ChipInput } from "../../../../../components/inputs/chip-input"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateProductOption } from "../../../../../hooks/api/products"
|
import { useCreateProductOption } from "../../../../../hooks/api/products"
|
||||||
|
|
||||||
type EditProductOptionsFormProps = {
|
type EditProductOptionsFormProps = {
|
||||||
@@ -53,7 +54,7 @@ export const CreateProductOptionForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -115,7 +116,7 @@ export const CreateProductOptionForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+12
-14
@@ -1,8 +1,8 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import { Button, ProgressStatus, ProgressTabs, toast } from "@medusajs/ui"
|
import { Button, ProgressStatus, ProgressTabs, toast } from "@medusajs/ui"
|
||||||
|
import { useEffect, useMemo, useState } from "react"
|
||||||
import { useFieldArray, useForm, useWatch } from "react-hook-form"
|
import { useFieldArray, useForm, useWatch } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { useEffect, useMemo, useState } from "react"
|
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { AdminCreateProductVariantPrice, HttpTypes } from "@medusajs/types"
|
import { AdminCreateProductVariantPrice, HttpTypes } from "@medusajs/types"
|
||||||
@@ -11,7 +11,11 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
|
import { useRegions } from "../../../../../hooks/api"
|
||||||
import { useCreateProductVariant } from "../../../../../hooks/api/products"
|
import { useCreateProductVariant } from "../../../../../hooks/api/products"
|
||||||
|
import { castNumber } from "../../../../../lib/cast-number"
|
||||||
|
import { partialFormValidation } from "../../../../../lib/validation"
|
||||||
import {
|
import {
|
||||||
CreateProductVariantSchema,
|
CreateProductVariantSchema,
|
||||||
CreateVariantDetailsFields,
|
CreateVariantDetailsFields,
|
||||||
@@ -20,11 +24,8 @@ import {
|
|||||||
CreateVariantPriceSchema,
|
CreateVariantPriceSchema,
|
||||||
} from "./constants"
|
} from "./constants"
|
||||||
import DetailsTab from "./details-tab"
|
import DetailsTab from "./details-tab"
|
||||||
import PricingTab from "./pricing-tab"
|
|
||||||
import InventoryKitTab from "./inventory-kit-tab"
|
import InventoryKitTab from "./inventory-kit-tab"
|
||||||
import { castNumber } from "../../../../../lib/cast-number"
|
import PricingTab from "./pricing-tab"
|
||||||
import { useRegions } from "../../../../../hooks/api"
|
|
||||||
import { partialFormValidation } from "../../../../../lib/validation"
|
|
||||||
|
|
||||||
enum Tab {
|
enum Tab {
|
||||||
DETAIL = "detail",
|
DETAIL = "detail",
|
||||||
@@ -74,13 +75,10 @@ export const CreateProductVariantForm = ({
|
|||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return regions.reduce(
|
return regions.reduce((acc, reg) => {
|
||||||
(acc, reg) => {
|
acc[reg.id] = reg.currency_code
|
||||||
acc[reg.id] = reg.currency_code
|
return acc
|
||||||
return acc
|
}, {} as Record<string, string>)
|
||||||
},
|
|
||||||
{} as Record<string, string>
|
|
||||||
)
|
|
||||||
}, [regions])
|
}, [regions])
|
||||||
|
|
||||||
const isManageInventoryEnabled = useWatch({
|
const isManageInventoryEnabled = useWatch({
|
||||||
@@ -263,7 +261,7 @@ export const CreateProductVariantForm = ({
|
|||||||
onValueChange={(tab) => handleChangeTab(tab as Tab)}
|
onValueChange={(tab) => handleChangeTab(tab as Tab)}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -332,7 +330,7 @@ export const CreateProductVariantForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</ProgressTabs>
|
</ProgressTabs>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
+15
-6
@@ -7,6 +7,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
useDashboardExtension,
|
useDashboardExtension,
|
||||||
useExtendableForm,
|
useExtendableForm,
|
||||||
@@ -211,14 +212,22 @@ export const ProductCreateForm = ({
|
|||||||
return (
|
return (
|
||||||
<RouteFocusModal>
|
<RouteFocusModal>
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
// We want to continue to the next tab on enter instead of saving as draft immediately
|
// We want to continue to the next tab on enter instead of saving as draft immediately
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
if (tab !== Tab.VARIANTS) {
|
e.preventDefault()
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
if (e.metaKey || e.ctrlKey) {
|
||||||
onNext(tab)
|
if (tab !== Tab.VARIANTS) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
onNext(tab)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -332,7 +341,7 @@ export const ProductCreateForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
</RouteFocusModal>
|
</RouteFocusModal>
|
||||||
)
|
)
|
||||||
|
|||||||
-2
@@ -1,2 +0,0 @@
|
|||||||
export * from "./product-create-details-context"
|
|
||||||
export * from "./use-product-create-details-context"
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
import { createContext } from "react"
|
|
||||||
|
|
||||||
type ProductCreateDetailsContextValue = {
|
|
||||||
open: boolean
|
|
||||||
onOpenChange: (open: boolean) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ProductCreateDetailsContext =
|
|
||||||
createContext<ProductCreateDetailsContextValue | null>(null)
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
import { useContext } from "react"
|
|
||||||
import { ProductCreateDetailsContext } from "./product-create-details-context"
|
|
||||||
|
|
||||||
export const useProductCreateDetailsContext = () => {
|
|
||||||
const context = useContext(ProductCreateDetailsContext)
|
|
||||||
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"useProductCreateDetailsContext must be used within a ProductCreateDetailsContextProvider"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
+6
-10
@@ -6,11 +6,11 @@ import { ChipGroup } from "../../../../../../../components/common/chip-group"
|
|||||||
import { Form } from "../../../../../../../components/common/form"
|
import { Form } from "../../../../../../../components/common/form"
|
||||||
import { SwitchBox } from "../../../../../../../components/common/switch-box"
|
import { SwitchBox } from "../../../../../../../components/common/switch-box"
|
||||||
import { Combobox } from "../../../../../../../components/inputs/combobox"
|
import { Combobox } from "../../../../../../../components/inputs/combobox"
|
||||||
|
import { StackedFocusModal } from "../../../../../../../components/modals"
|
||||||
import { useComboboxData } from "../../../../../../../hooks/use-combobox-data"
|
import { useComboboxData } from "../../../../../../../hooks/use-combobox-data"
|
||||||
import { sdk } from "../../../../../../../lib/client"
|
import { sdk } from "../../../../../../../lib/client"
|
||||||
import { CategoryCombobox } from "../../../../../common/components/category-combobox"
|
import { CategoryCombobox } from "../../../../../common/components/category-combobox"
|
||||||
import { ProductCreateSchemaType } from "../../../../types"
|
import { ProductCreateSchemaType } from "../../../../types"
|
||||||
import { useProductCreateDetailsContext } from "../product-create-organize-context"
|
|
||||||
|
|
||||||
type ProductCreateOrganizationSectionProps = {
|
type ProductCreateOrganizationSectionProps = {
|
||||||
form: UseFormReturn<ProductCreateSchemaType>
|
form: UseFormReturn<ProductCreateSchemaType>
|
||||||
@@ -20,7 +20,6 @@ export const ProductCreateOrganizationSection = ({
|
|||||||
form,
|
form,
|
||||||
}: ProductCreateOrganizationSectionProps) => {
|
}: ProductCreateOrganizationSectionProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { onOpenChange } = useProductCreateDetailsContext()
|
|
||||||
|
|
||||||
const collections = useComboboxData({
|
const collections = useComboboxData({
|
||||||
queryKey: ["product_collections"],
|
queryKey: ["product_collections"],
|
||||||
@@ -178,14 +177,11 @@ export const ProductCreateOrganizationSection = ({
|
|||||||
<Trans i18nKey={"products.fields.sales_channels.hint"} />
|
<Trans i18nKey={"products.fields.sales_channels.hint"} />
|
||||||
</Form.Hint>
|
</Form.Hint>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<StackedFocusModal.Trigger asChild>
|
||||||
size="small"
|
<Button size="small" variant="secondary" type="button">
|
||||||
variant="secondary"
|
{t("actions.add")}
|
||||||
type="button"
|
</Button>
|
||||||
onClick={() => onOpenChange(true)}
|
</StackedFocusModal.Trigger>
|
||||||
>
|
|
||||||
{t("actions.add")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<Form.Control className="mt-0">
|
<Form.Control className="mt-0">
|
||||||
{fields.length > 0 && (
|
{fields.length > 0 && (
|
||||||
|
|||||||
File renamed without changes.
+31
-24
@@ -9,7 +9,10 @@ import { useEffect, useMemo, useState } from "react"
|
|||||||
import { UseFormReturn } from "react-hook-form"
|
import { UseFormReturn } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
import { SplitView } from "../../../../../../../components/layout/split-view"
|
import {
|
||||||
|
StackedFocusModal,
|
||||||
|
useStackedModal,
|
||||||
|
} from "../../../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../../../components/table/data-table"
|
||||||
import { useSalesChannels } from "../../../../../../../hooks/api/sales-channels"
|
import { useSalesChannels } from "../../../../../../../hooks/api/sales-channels"
|
||||||
import { useSalesChannelTableColumns } from "../../../../../../../hooks/table/columns/use-sales-channel-table-columns"
|
import { useSalesChannelTableColumns } from "../../../../../../../hooks/table/columns/use-sales-channel-table-columns"
|
||||||
@@ -17,28 +20,27 @@ import { useSalesChannelTableFilters } from "../../../../../../../hooks/table/fi
|
|||||||
import { useSalesChannelTableQuery } from "../../../../../../../hooks/table/query/use-sales-channel-table-query"
|
import { useSalesChannelTableQuery } from "../../../../../../../hooks/table/query/use-sales-channel-table-query"
|
||||||
import { useDataTable } from "../../../../../../../hooks/use-data-table"
|
import { useDataTable } from "../../../../../../../hooks/use-data-table"
|
||||||
import { ProductCreateSchemaType } from "../../../../types"
|
import { ProductCreateSchemaType } from "../../../../types"
|
||||||
import { useProductCreateDetailsContext } from "../product-create-organize-context"
|
import { SC_STACKED_MODAL_ID } from "../../constants"
|
||||||
|
|
||||||
type ProductCreateSalesChannelDrawerProps = {
|
type ProductCreateSalesChannelStackedModalProps = {
|
||||||
form: UseFormReturn<ProductCreateSchemaType>
|
form: UseFormReturn<ProductCreateSchemaType>
|
||||||
}
|
}
|
||||||
|
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 50
|
||||||
const PREFIX = "sc"
|
|
||||||
|
|
||||||
export const ProductCreateSalesChannelDrawer = ({
|
export const ProductCreateSalesChannelStackedModal = ({
|
||||||
form,
|
form,
|
||||||
}: ProductCreateSalesChannelDrawerProps) => {
|
}: ProductCreateSalesChannelStackedModalProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { open, onOpenChange } = useProductCreateDetailsContext()
|
|
||||||
const { getValues, setValue } = form
|
const { getValues, setValue } = form
|
||||||
|
const { setIsOpen, getIsOpen } = useStackedModal()
|
||||||
|
|
||||||
const [selection, setSelection] = useState<RowSelectionState>({})
|
const [selection, setSelection] = useState<RowSelectionState>({})
|
||||||
const [state, setState] = useState<{ id: string; name: string }[]>([])
|
const [state, setState] = useState<{ id: string; name: string }[]>([])
|
||||||
|
|
||||||
const { searchParams, raw } = useSalesChannelTableQuery({
|
const { searchParams, raw } = useSalesChannelTableQuery({
|
||||||
pageSize: PAGE_SIZE,
|
pageSize: PAGE_SIZE,
|
||||||
prefix: PREFIX,
|
prefix: SC_STACKED_MODAL_ID,
|
||||||
})
|
})
|
||||||
const { sales_channels, count, isLoading, isError, error } = useSalesChannels(
|
const { sales_channels, count, isLoading, isError, error } = useSalesChannels(
|
||||||
{
|
{
|
||||||
@@ -46,6 +48,8 @@ export const ProductCreateSalesChannelDrawer = ({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const open = getIsOpen(SC_STACKED_MODAL_ID)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
return
|
return
|
||||||
@@ -98,7 +102,7 @@ export const ProductCreateSalesChannelDrawer = ({
|
|||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldTouch: true,
|
shouldTouch: true,
|
||||||
})
|
})
|
||||||
onOpenChange(false)
|
setIsOpen(SC_STACKED_MODAL_ID, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = useSalesChannelTableFilters()
|
const filters = useSalesChannelTableFilters()
|
||||||
@@ -116,7 +120,7 @@ export const ProductCreateSalesChannelDrawer = ({
|
|||||||
state: selection,
|
state: selection,
|
||||||
updater,
|
updater,
|
||||||
},
|
},
|
||||||
prefix: PREFIX,
|
prefix: SC_STACKED_MODAL_ID,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
@@ -124,8 +128,9 @@ export const ProductCreateSalesChannelDrawer = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-1 flex-col overflow-hidden">
|
<StackedFocusModal.Content className="flex flex-col overflow-hidden">
|
||||||
<div className="flex-1">
|
<StackedFocusModal.Header />
|
||||||
|
<StackedFocusModal.Body className="flex-1 overflow-hidden">
|
||||||
<DataTable
|
<DataTable
|
||||||
table={table}
|
table={table}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@@ -138,20 +143,22 @@ export const ProductCreateSalesChannelDrawer = ({
|
|||||||
search
|
search
|
||||||
pagination
|
pagination
|
||||||
count={count}
|
count={count}
|
||||||
prefix={PREFIX}
|
prefix={SC_STACKED_MODAL_ID}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StackedFocusModal.Body>
|
||||||
<div className="flex items-center justify-end gap-x-2 border-t px-6 py-4">
|
<StackedFocusModal.Footer>
|
||||||
<SplitView.Close asChild>
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<Button size="small" variant="secondary" type="button">
|
<StackedFocusModal.Close asChild>
|
||||||
{t("actions.cancel")}
|
<Button size="small" variant="secondary" type="button">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</StackedFocusModal.Close>
|
||||||
|
<Button size="small" onClick={handleAdd} type="button">
|
||||||
|
{t("actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</SplitView.Close>
|
</div>
|
||||||
<Button size="small" onClick={handleAdd} type="button">
|
</StackedFocusModal.Footer>
|
||||||
{t("actions.add")}
|
</StackedFocusModal.Content>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
export const SC_STACKED_MODAL_ID = "sc"
|
||||||
+15
-25
@@ -1,45 +1,35 @@
|
|||||||
import { useState } from "react"
|
|
||||||
import { UseFormReturn } from "react-hook-form"
|
import { UseFormReturn } from "react-hook-form"
|
||||||
|
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
import { StackedFocusModal } from "../../../../../components/modals"
|
||||||
import {
|
import {
|
||||||
FormExtensionZone,
|
FormExtensionZone,
|
||||||
useDashboardExtension,
|
useDashboardExtension,
|
||||||
} from "../../../../../extensions"
|
} from "../../../../../extensions"
|
||||||
import { ProductCreateSchemaType } from "../../types"
|
import { ProductCreateSchemaType } from "../../types"
|
||||||
import { ProductCreateDetailsContext } from "./components/product-create-organize-context"
|
|
||||||
import { ProductCreateOrganizationSection } from "./components/product-create-organize-section"
|
import { ProductCreateOrganizationSection } from "./components/product-create-organize-section"
|
||||||
import { ProductCreateSalesChannelDrawer } from "./components/product-create-sales-channel-drawer"
|
import { ProductCreateSalesChannelStackedModal } from "./components/product-create-sales-channel-stacked-modal"
|
||||||
|
import { SC_STACKED_MODAL_ID } from "./constants"
|
||||||
|
|
||||||
type ProductAttributesProps = {
|
type ProductAttributesProps = {
|
||||||
form: UseFormReturn<ProductCreateSchemaType>
|
form: UseFormReturn<ProductCreateSchemaType>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProductCreateOrganizeForm = ({ form }: ProductAttributesProps) => {
|
export const ProductCreateOrganizeForm = ({ form }: ProductAttributesProps) => {
|
||||||
const [open, setOpen] = useState(false)
|
|
||||||
const { getFormFields } = useDashboardExtension()
|
const { getFormFields } = useDashboardExtension()
|
||||||
const fields = getFormFields("product", "create", "organize")
|
const fields = getFormFields("product", "create", "organize")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProductCreateDetailsContext.Provider
|
<StackedFocusModal id={SC_STACKED_MODAL_ID}>
|
||||||
value={{ open, onOpenChange: setOpen }}
|
<div className="flex flex-col items-center p-16">
|
||||||
>
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||||
<SplitView open={open} onOpenChange={setOpen}>
|
<ProductCreateOrganizationSection form={form} />
|
||||||
<SplitView.Content>
|
<FormExtensionZone fields={fields} form={form} />
|
||||||
<div className="flex flex-col items-center p-16">
|
{/* TODO: WHERE DO WE SET PRODUCT ATTRIBUTES? -> the plan is to moved that to Inventory UI */}
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
{/* <Divider />*/}
|
||||||
<ProductCreateOrganizationSection form={form} />
|
{/* <ProductCreateAttributeSection form={form} />*/}
|
||||||
<FormExtensionZone fields={fields} form={form} />
|
</div>
|
||||||
{/* TODO: WHERE DO WE SET PRODUCT ATTRIBUTES? -> the plan is to moved that to Inventory UI */}
|
</div>
|
||||||
{/* <Divider />*/}
|
<ProductCreateSalesChannelStackedModal form={form} />
|
||||||
{/* <ProductCreateAttributeSection form={form} />*/}
|
</StackedFocusModal>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SplitView.Content>
|
|
||||||
<SplitView.Drawer>
|
|
||||||
<ProductCreateSalesChannelDrawer form={form} />
|
|
||||||
</SplitView.Drawer>
|
|
||||||
</SplitView>
|
|
||||||
</ProductCreateDetailsContext.Provider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+4
-6
@@ -7,10 +7,8 @@ import { z } from "zod"
|
|||||||
import { HttpTypes } from "@medusajs/types"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { ChipInput } from "../../../../../components/inputs/chip-input"
|
import { ChipInput } from "../../../../../components/inputs/chip-input"
|
||||||
import {
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
RouteDrawer,
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
useRouteModal,
|
|
||||||
} from "../../../../../components/modals"
|
|
||||||
import { useUpdateProductOption } from "../../../../../hooks/api/products"
|
import { useUpdateProductOption } from "../../../../../hooks/api/products"
|
||||||
|
|
||||||
type EditProductOptionFormProps = {
|
type EditProductOptionFormProps = {
|
||||||
@@ -57,7 +55,7 @@ export const CreateProductOptionForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -119,7 +117,7 @@ export const CreateProductOptionForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -10,6 +10,7 @@ import { useExtendableForm } from "../../../../../extensions/forms/hooks"
|
|||||||
import { useUpdateProduct } from "../../../../../hooks/api/products"
|
import { useUpdateProduct } from "../../../../../hooks/api/products"
|
||||||
import { transformNullableFormData } from "../../../../../lib/form-helpers"
|
import { transformNullableFormData } from "../../../../../lib/form-helpers"
|
||||||
|
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
FormExtensionZone,
|
FormExtensionZone,
|
||||||
useDashboardExtension,
|
useDashboardExtension,
|
||||||
@@ -77,7 +78,7 @@ export const EditProductForm = ({ product }: EditProductFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -230,7 +231,7 @@ export const EditProductForm = ({ product }: EditProductFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+16
-11
@@ -11,6 +11,7 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProduct } from "../../../../../hooks/api/products"
|
import { useUpdateProduct } from "../../../../../hooks/api/products"
|
||||||
import { sdk } from "../../../../../lib/client"
|
import { sdk } from "../../../../../lib/client"
|
||||||
import { MediaGrid } from "../../../common/components/media-grid-view"
|
import { MediaGrid } from "../../../common/components/media-grid-view"
|
||||||
@@ -142,25 +143,17 @@ export const EditProductMediaForm = ({ product }: ProductMediaViewProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form blockSearch form={form}>
|
<RouteFocusModal.Form blockSearch form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header>
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button variant="secondary" size="small">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button variant="secondary" size="small" asChild>
|
<Button variant="secondary" size="small" asChild>
|
||||||
<Link to={{ pathname: ".", search: undefined }}>
|
<Link to={{ pathname: ".", search: undefined }}>
|
||||||
{t("products.media.galleryLabel")}
|
{t("products.media.galleryLabel")}
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" type="submit" isLoading={isPending}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
||||||
@@ -170,7 +163,7 @@ export const EditProductMediaForm = ({ product }: ProductMediaViewProps) => {
|
|||||||
onCheckedChange={handleCheckedChange}
|
onCheckedChange={handleCheckedChange}
|
||||||
selection={selection}
|
selection={selection}
|
||||||
/>
|
/>
|
||||||
<div className="bg-ui-bg-base border-b px-6 py-4 lg:border-b-0 lg:border-l">
|
<div className="bg-ui-bg-base overflow-auto border-b px-6 py-4 lg:border-b-0 lg:border-l">
|
||||||
<UploadMediaFormItem form={form} append={append} />
|
<UploadMediaFormItem form={form} append={append} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -200,7 +193,19 @@ export const EditProductMediaForm = ({ product }: ProductMediaViewProps) => {
|
|||||||
/>
|
/>
|
||||||
</CommandBar.Bar>
|
</CommandBar.Bar>
|
||||||
</CommandBar>
|
</CommandBar>
|
||||||
</form>
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button variant="secondary" size="small">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isPending}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@ import * as zod from "zod"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { Combobox } from "../../../../../components/inputs/combobox"
|
import { Combobox } from "../../../../../components/inputs/combobox"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import {
|
import {
|
||||||
FormExtensionZone,
|
FormExtensionZone,
|
||||||
useDashboardExtension,
|
useDashboardExtension,
|
||||||
@@ -107,7 +108,7 @@ export const ProductOrganizationForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex h-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex h-full flex-col gap-y-4">
|
<div className="flex h-full flex-col gap-y-4">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
@@ -211,7 +212,7 @@ export const ProductOrganizationForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
import { RouteFocusModal, useRouteModal } from "../../../components/modals"
|
import { RouteFocusModal, useRouteModal } from "../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../components/utilities/keybound-form"
|
||||||
import { useUpdateProductVariantsBatch } from "../../../hooks/api/products"
|
import { useUpdateProductVariantsBatch } from "../../../hooks/api/products"
|
||||||
import { useRegions } from "../../../hooks/api/regions"
|
import { useRegions } from "../../../hooks/api/regions"
|
||||||
import { castNumber } from "../../../lib/cast-number"
|
import { castNumber } from "../../../lib/cast-number"
|
||||||
@@ -120,7 +121,7 @@ export const PricingEdit = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex size-full flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex size-full flex-col">
|
||||||
<RouteFocusModal.Header />
|
<RouteFocusModal.Header />
|
||||||
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
<RouteFocusModal.Body className="flex flex-col overflow-hidden">
|
||||||
<VariantPricingForm form={form as any} />
|
<VariantPricingForm form={form as any} />
|
||||||
@@ -142,7 +143,7 @@ export const PricingEdit = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+17
-15
@@ -6,6 +6,7 @@ import * as zod from "zod"
|
|||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import { HttpTypes } from "@medusajs/types"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
|
import { keepPreviousData } from "@tanstack/react-query"
|
||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
@@ -69,7 +70,7 @@ export const EditSalesChannelsForm = ({
|
|||||||
...searchParams,
|
...searchParams,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ export const EditSalesChannelsForm = ({
|
|||||||
pageSize: PAGE_SIZE,
|
pageSize: PAGE_SIZE,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { mutateAsync, isLoading: isMutating } = useUpdateProduct(product.id)
|
const { mutateAsync, isPending: isMutating } = useUpdateProduct(product.id)
|
||||||
|
|
||||||
const handleSubmit = form.handleSubmit(async (data) => {
|
const handleSubmit = form.handleSubmit(async (data) => {
|
||||||
const arr = data.sales_channels ?? []
|
const arr = data.sales_channels ?? []
|
||||||
@@ -120,19 +121,8 @@ export const EditSalesChannelsForm = ({
|
|||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<div className="flex h-full flex-col overflow-hidden">
|
<div className="flex h-full flex-col overflow-hidden">
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
<RouteFocusModal.Body className="flex-1 overflow-hidden">
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" isLoading={isMutating} onClick={handleSubmit}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body>
|
|
||||||
<DataTable
|
<DataTable
|
||||||
table={table}
|
table={table}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@@ -147,6 +137,18 @@ export const EditSalesChannelsForm = ({
|
|||||||
layout="fill"
|
layout="fill"
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" isLoading={isMutating} onClick={handleSubmit}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-2
@@ -7,6 +7,7 @@ import * as zod from "zod"
|
|||||||
import { UserDTO } from "@medusajs/types"
|
import { UserDTO } from "@medusajs/types"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateUser } from "../../../../../hooks/api/users"
|
import { useUpdateUser } from "../../../../../hooks/api/users"
|
||||||
import { languages } from "../../../../../i18n/languages"
|
import { languages } from "../../../../../i18n/languages"
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ export const EditProfileForm = ({ user, usageInsights }: EditProfileProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
<KeyboundForm onSubmit={handleSubmit} className="flex flex-1 flex-col">
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<div className="flex flex-col gap-y-8">
|
<div className="flex flex-col gap-y-8">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
@@ -187,7 +188,7 @@ export const EditProfileForm = ({ user, usageInsights }: EditProfileProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+6
-2
@@ -5,6 +5,7 @@ import { useState } from "react"
|
|||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { RouteDrawer } from "../../../../../../components/modals"
|
import { RouteDrawer } from "../../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../../components/utilities/keybound-form"
|
||||||
import { RuleTypeValues } from "../../edit-rules"
|
import { RuleTypeValues } from "../../edit-rules"
|
||||||
import { RulesFormField } from "../rules-form-field"
|
import { RulesFormField } from "../rules-form-field"
|
||||||
import { EditRules, EditRulesType } from "./form-schema"
|
import { EditRules, EditRulesType } from "./form-schema"
|
||||||
@@ -35,7 +36,10 @@ export const EditRulesForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form onSubmit={handleFormSubmit} className="flex h-full flex-col">
|
<KeyboundForm
|
||||||
|
onSubmit={handleFormSubmit}
|
||||||
|
className="flex h-full flex-col"
|
||||||
|
>
|
||||||
<RouteDrawer.Body>
|
<RouteDrawer.Body>
|
||||||
<RulesFormField
|
<RulesFormField
|
||||||
form={form as any}
|
form={form as any}
|
||||||
@@ -59,7 +63,7 @@ export const EditRulesForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -7,6 +7,7 @@ import { Trans, useTranslation } from "react-i18next"
|
|||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
|
import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
|
||||||
import { CreateCampaignFormFields } from "../../../../campaigns/common/components/create-campaign-form-fields"
|
import { CreateCampaignFormFields } from "../../../../campaigns/common/components/create-campaign-form-fields"
|
||||||
import { CampaignDetails } from "./campaign-details"
|
import { CampaignDetails } from "./campaign-details"
|
||||||
@@ -213,7 +214,7 @@ export const AddCampaignPromotionForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex size-full flex-col overflow-hidden"
|
className="flex size-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -238,7 +239,7 @@ export const AddCampaignPromotionForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+6
-5
@@ -32,10 +32,11 @@ import {
|
|||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCampaigns } from "../../../../../hooks/api/campaigns"
|
import { useCampaigns } from "../../../../../hooks/api/campaigns"
|
||||||
import { useCreatePromotion } from "../../../../../hooks/api/promotions"
|
import { useCreatePromotion } from "../../../../../hooks/api/promotions"
|
||||||
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
||||||
import { defaultCampaignValues } from "../../../../campaigns/campaign-create/components/create-campaign-form"
|
import { DEFAULT_CAMPAIGN_VALUES } from "../../../../campaigns/common/constants"
|
||||||
import { RulesFormField } from "../../../common/edit-rules/components/rules-form-field"
|
import { RulesFormField } from "../../../common/edit-rules/components/rules-form-field"
|
||||||
import { AddCampaignPromotionFields } from "../../../promotion-add-campaign/components/add-campaign-promotion-form"
|
import { AddCampaignPromotionFields } from "../../../promotion-add-campaign/components/add-campaign-promotion-form"
|
||||||
import { Tab } from "./constants"
|
import { Tab } from "./constants"
|
||||||
@@ -319,9 +320,9 @@ export const CreatePromotionForm = () => {
|
|||||||
if (watchCampaignChoice === "new") {
|
if (watchCampaignChoice === "new") {
|
||||||
if (!formData.campaign || !formData.campaign?.budget?.type) {
|
if (!formData.campaign || !formData.campaign?.budget?.type) {
|
||||||
form.setValue("campaign", {
|
form.setValue("campaign", {
|
||||||
...defaultCampaignValues,
|
...DEFAULT_CAMPAIGN_VALUES,
|
||||||
budget: {
|
budget: {
|
||||||
...defaultCampaignValues.budget,
|
...DEFAULT_CAMPAIGN_VALUES.budget,
|
||||||
currency_code: formData.application_method.currency_code,
|
currency_code: formData.application_method.currency_code,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -350,7 +351,7 @@ export const CreatePromotionForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form className="flex h-full flex-col" onSubmit={handleSubmit}>
|
<KeyboundForm className="flex h-full flex-col" onSubmit={handleSubmit}>
|
||||||
<ProgressTabs
|
<ProgressTabs
|
||||||
value={tab}
|
value={tab}
|
||||||
onValueChange={(tab) => handleTabChange(tab as Tab)}
|
onValueChange={(tab) => handleTabChange(tab as Tab)}
|
||||||
@@ -875,7 +876,7 @@ export const CreatePromotionForm = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Footer>
|
</RouteFocusModal.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -8,6 +8,7 @@ import * as zod from "zod"
|
|||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { DeprecatedPercentageInput } from "../../../../../components/inputs/percentage-input"
|
import { DeprecatedPercentageInput } from "../../../../../components/inputs/percentage-input"
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
|
import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
|
||||||
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ export const EditPromotionDetailsForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteDrawer.Form form={form}>
|
<RouteDrawer.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex flex-1 flex-col overflow-hidden"
|
className="flex flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -277,7 +278,7 @@ export const EditPromotionDetailsForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Footer>
|
</RouteDrawer.Footer>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteDrawer.Form>
|
</RouteDrawer.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-2
@@ -16,6 +16,7 @@ import {
|
|||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateRegion } from "../../../../../hooks/api/regions"
|
import { useUpdateRegion } from "../../../../../hooks/api/regions"
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
import { countries as staticCountries } from "../../../../../lib/data/countries"
|
import { countries as staticCountries } from "../../../../../lib/data/countries"
|
||||||
@@ -124,7 +125,7 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -154,7 +155,7 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
prefix={PREFIX}
|
prefix={PREFIX}
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+217
-222
@@ -21,12 +21,14 @@ import { PaymentProviderDTO, RegionCountryDTO } from "@medusajs/types"
|
|||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { Combobox } from "../../../../../components/inputs/combobox"
|
import { Combobox } from "../../../../../components/inputs/combobox"
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
|
StackedFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
|
useStackedModal,
|
||||||
} from "../../../../../components/modals"
|
} from "../../../../../components/modals"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useCreateRegion } from "../../../../../hooks/api/regions"
|
import { useCreateRegion } from "../../../../../hooks/api/regions"
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
import { countries as staticCountries } from "../../../../../lib/data/countries"
|
import { countries as staticCountries } from "../../../../../lib/data/countries"
|
||||||
@@ -53,11 +55,13 @@ const CreateRegionSchema = zod.object({
|
|||||||
const PREFIX = "cr"
|
const PREFIX = "cr"
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 50
|
||||||
|
|
||||||
|
const STACKED_MODAL_ID = "countries-modal"
|
||||||
|
|
||||||
export const CreateRegionForm = ({
|
export const CreateRegionForm = ({
|
||||||
currencies,
|
currencies,
|
||||||
paymentProviders,
|
paymentProviders,
|
||||||
}: CreateRegionFormProps) => {
|
}: CreateRegionFormProps) => {
|
||||||
const [open, setOpen] = useState(false)
|
const { setIsOpen } = useStackedModal()
|
||||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
||||||
const { handleSuccess } = useRouteModal()
|
const { handleSuccess } = useRouteModal()
|
||||||
|
|
||||||
@@ -155,22 +159,7 @@ export const CreateRegionForm = ({
|
|||||||
{ shouldDirty: true, shouldTouch: true }
|
{ shouldDirty: true, shouldTouch: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
setOpen(false)
|
setIsOpen(STACKED_MODAL_ID, false)
|
||||||
}
|
|
||||||
|
|
||||||
const onOpenChange = (open: boolean) => {
|
|
||||||
setOpen(open)
|
|
||||||
|
|
||||||
if (!open) {
|
|
||||||
const ids = selectedCountries.reduce((acc, c) => {
|
|
||||||
acc[c.code] = true
|
|
||||||
return acc
|
|
||||||
}, {} as RowSelectionState)
|
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
setRowSelection(ids)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeCountry = (code: string) => {
|
const removeCountry = (code: string) => {
|
||||||
@@ -193,7 +182,7 @@ export const CreateRegionForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<form
|
<KeyboundForm
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
@@ -210,233 +199,239 @@ export const CreateRegionForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="flex overflow-hidden">
|
<RouteFocusModal.Body className="flex overflow-hidden">
|
||||||
<SplitView open={open} onOpenChange={onOpenChange}>
|
<div
|
||||||
<SplitView.Content>
|
className={clx(
|
||||||
<div
|
"flex h-full w-full flex-col items-center overflow-y-auto p-16"
|
||||||
className={clx(
|
)}
|
||||||
"flex h-full w-full flex-col items-center overflow-y-auto p-16"
|
id="form-section"
|
||||||
)}
|
>
|
||||||
id="form-section"
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||||
>
|
<div>
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
<Heading>{t("regions.createRegion")}</Heading>
|
||||||
<div>
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
<Heading>{t("regions.createRegion")}</Heading>
|
{t("regions.createRegionHint")}
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
</Text>
|
||||||
{t("regions.createRegionHint")}
|
</div>
|
||||||
</Text>
|
<div className="flex flex-col gap-y-4">
|
||||||
</div>
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
<div className="flex flex-col gap-y-4">
|
|
||||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
||||||
<Form.Field
|
|
||||||
control={form.control}
|
|
||||||
name="name"
|
|
||||||
render={({ field }) => {
|
|
||||||
return (
|
|
||||||
<Form.Item>
|
|
||||||
<Form.Label>{t("fields.name")}</Form.Label>
|
|
||||||
<Form.Control>
|
|
||||||
<Input {...field} />
|
|
||||||
</Form.Control>
|
|
||||||
<Form.ErrorMessage />
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Form.Field
|
|
||||||
control={form.control}
|
|
||||||
name="currency_code"
|
|
||||||
render={({ field: { onChange, ref, ...field } }) => {
|
|
||||||
return (
|
|
||||||
<Form.Item>
|
|
||||||
<Form.Label>{t("fields.currency")}</Form.Label>
|
|
||||||
<Form.Control>
|
|
||||||
<Select {...field} onValueChange={onChange}>
|
|
||||||
<Select.Trigger ref={ref}>
|
|
||||||
<Select.Value />
|
|
||||||
</Select.Trigger>
|
|
||||||
<Select.Content>
|
|
||||||
{currencies.map((currency) => (
|
|
||||||
<Select.Item
|
|
||||||
value={currency.code}
|
|
||||||
key={currency.code}
|
|
||||||
>
|
|
||||||
{currency.name}
|
|
||||||
</Select.Item>
|
|
||||||
))}
|
|
||||||
</Select.Content>
|
|
||||||
</Select>
|
|
||||||
</Form.Control>
|
|
||||||
<Form.ErrorMessage />
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="automatic_taxes"
|
name="name"
|
||||||
render={({ field: { value, onChange, ...field } }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<div>
|
<Form.Label>{t("fields.name")}</Form.Label>
|
||||||
<div className="flex items-start justify-between">
|
<Form.Control>
|
||||||
<Form.Label>
|
<Input {...field} />
|
||||||
{t("fields.automaticTaxes")}
|
</Form.Control>
|
||||||
</Form.Label>
|
<Form.ErrorMessage />
|
||||||
<Form.Control>
|
|
||||||
<Switch
|
|
||||||
{...field}
|
|
||||||
checked={value}
|
|
||||||
onCheckedChange={onChange}
|
|
||||||
/>
|
|
||||||
</Form.Control>
|
|
||||||
</div>
|
|
||||||
<Form.Hint>
|
|
||||||
{t("regions.automaticTaxesHint")}
|
|
||||||
</Form.Hint>
|
|
||||||
<Form.ErrorMessage />
|
|
||||||
</div>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="is_tax_inclusive"
|
name="currency_code"
|
||||||
render={({ field: { value, onChange, ...field } }) => {
|
render={({ field: { onChange, ref, ...field } }) => {
|
||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<div>
|
<Form.Label>{t("fields.currency")}</Form.Label>
|
||||||
<div className="flex items-start justify-between">
|
<Form.Control>
|
||||||
<Form.Label>
|
<Select {...field} onValueChange={onChange}>
|
||||||
{t("fields.taxInclusivePricing")}
|
<Select.Trigger ref={ref}>
|
||||||
</Form.Label>
|
<Select.Value />
|
||||||
<Form.Control>
|
</Select.Trigger>
|
||||||
<Switch
|
<Select.Content>
|
||||||
{...field}
|
{currencies.map((currency) => (
|
||||||
checked={value}
|
<Select.Item
|
||||||
onCheckedChange={onChange}
|
value={currency.code}
|
||||||
/>
|
key={currency.code}
|
||||||
</Form.Control>
|
>
|
||||||
</div>
|
{currency.name}
|
||||||
<Form.Hint>
|
</Select.Item>
|
||||||
{t("regions.taxInclusiveHint")}
|
))}
|
||||||
</Form.Hint>
|
</Select.Content>
|
||||||
<Form.ErrorMessage />
|
</Select>
|
||||||
</div>
|
</Form.Control>
|
||||||
|
<Form.ErrorMessage />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<div className="bg-ui-border-base h-px w-full" />
|
</div>
|
||||||
<div className="flex flex-col gap-y-4">
|
<Form.Field
|
||||||
<div>
|
control={form.control}
|
||||||
<Text size="small" leading="compact" weight="plus">
|
name="automatic_taxes"
|
||||||
{t("fields.countries")}
|
render={({ field: { value, onChange, ...field } }) => {
|
||||||
</Text>
|
return (
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
<Form.Item>
|
||||||
{t("regions.countriesHint")}
|
<div>
|
||||||
</Text>
|
<div className="flex items-start justify-between">
|
||||||
</div>
|
<Form.Label>{t("fields.automaticTaxes")}</Form.Label>
|
||||||
{selectedCountries.length > 0 && (
|
<Form.Control>
|
||||||
<div className="flex flex-wrap gap-2">
|
<Switch
|
||||||
{selectedCountries.map((country) => (
|
{...field}
|
||||||
<CountryTag
|
checked={value}
|
||||||
key={country.code}
|
onCheckedChange={onChange}
|
||||||
country={country}
|
/>
|
||||||
onRemove={removeCountry}
|
</Form.Control>
|
||||||
/>
|
</div>
|
||||||
))}
|
<Form.Hint>{t("regions.automaticTaxesHint")}</Form.Hint>
|
||||||
<Button
|
<Form.ErrorMessage />
|
||||||
variant="transparent"
|
|
||||||
size="small"
|
|
||||||
className="text-ui-fg-muted hover:text-ui-fg-subtle"
|
|
||||||
onClick={clearCountries}
|
|
||||||
>
|
|
||||||
{t("actions.clearAll")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
</Form.Item>
|
||||||
<div className="flex items-center justify-end">
|
)
|
||||||
<Button
|
}}
|
||||||
variant="secondary"
|
/>
|
||||||
size="small"
|
|
||||||
onClick={() => setOpen(true)}
|
<Form.Field
|
||||||
type="button"
|
control={form.control}
|
||||||
>
|
name="is_tax_inclusive"
|
||||||
|
render={({ field: { value, onChange, ...field } }) => {
|
||||||
|
return (
|
||||||
|
<Form.Item>
|
||||||
|
<div>
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<Form.Label>
|
||||||
|
{t("fields.taxInclusivePricing")}
|
||||||
|
</Form.Label>
|
||||||
|
<Form.Control>
|
||||||
|
<Switch
|
||||||
|
{...field}
|
||||||
|
checked={value}
|
||||||
|
onCheckedChange={onChange}
|
||||||
|
/>
|
||||||
|
</Form.Control>
|
||||||
|
</div>
|
||||||
|
<Form.Hint>{t("regions.taxInclusiveHint")}</Form.Hint>
|
||||||
|
<Form.ErrorMessage />
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="bg-ui-border-base h-px w-full" />
|
||||||
|
<div className="flex flex-col gap-y-4">
|
||||||
|
<div>
|
||||||
|
<Text size="small" leading="compact" weight="plus">
|
||||||
|
{t("fields.countries")}
|
||||||
|
</Text>
|
||||||
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
|
{t("regions.countriesHint")}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
{selectedCountries.length > 0 && (
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{selectedCountries.map((country) => (
|
||||||
|
<CountryTag
|
||||||
|
key={country.code}
|
||||||
|
country={country}
|
||||||
|
onRemove={removeCountry}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
variant="transparent"
|
||||||
|
size="small"
|
||||||
|
className="text-ui-fg-muted hover:text-ui-fg-subtle"
|
||||||
|
onClick={clearCountries}
|
||||||
|
>
|
||||||
|
{t("actions.clearAll")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<StackedFocusModal id={STACKED_MODAL_ID}>
|
||||||
|
<div className="flex items-center justify-end">
|
||||||
|
<StackedFocusModal.Trigger asChild>
|
||||||
|
<Button variant="secondary" size="small">
|
||||||
{t("regions.addCountries")}
|
{t("regions.addCountries")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</StackedFocusModal.Trigger>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-ui-border-base h-px w-full" />
|
<StackedFocusModal.Content>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex size-full flex-col overflow-hidden">
|
||||||
<div>
|
<StackedFocusModal.Header>
|
||||||
<Text size="small" leading="compact" weight="plus">
|
<StackedFocusModal.Title asChild>
|
||||||
{t("fields.providers")}
|
<span className="sr-only">
|
||||||
</Text>
|
{t("regions.addCountries")}
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
</span>
|
||||||
{t("regions.providersHint")}
|
</StackedFocusModal.Title>
|
||||||
</Text>
|
</StackedFocusModal.Header>
|
||||||
|
<StackedFocusModal.Body className="overflow-hidden">
|
||||||
|
<DataTable
|
||||||
|
table={table}
|
||||||
|
columns={columns}
|
||||||
|
count={count}
|
||||||
|
pageSize={PAGE_SIZE}
|
||||||
|
orderBy={["name", "code"]}
|
||||||
|
pagination
|
||||||
|
search="autofocus"
|
||||||
|
layout="fill"
|
||||||
|
queryObject={raw}
|
||||||
|
prefix={PREFIX}
|
||||||
|
/>
|
||||||
|
</StackedFocusModal.Body>
|
||||||
|
<StackedFocusModal.Footer>
|
||||||
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
|
<StackedFocusModal.Close asChild>
|
||||||
|
<Button variant="secondary" size="small">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</StackedFocusModal.Close>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="button"
|
||||||
|
onClick={saveCountries}
|
||||||
|
>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</StackedFocusModal.Footer>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
</StackedFocusModal.Content>
|
||||||
<Form.Field
|
</StackedFocusModal>
|
||||||
control={form.control}
|
</div>
|
||||||
name="payment_providers"
|
<div className="bg-ui-border-base h-px w-full" />
|
||||||
render={({ field }) => {
|
<div className="flex flex-col gap-y-4">
|
||||||
return (
|
<div>
|
||||||
<Form.Item>
|
<Text size="small" leading="compact" weight="plus">
|
||||||
<Form.Label>
|
{t("fields.providers")}
|
||||||
{t("fields.paymentProviders")}
|
</Text>
|
||||||
</Form.Label>
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
<Form.Control>
|
{t("regions.providersHint")}
|
||||||
<Combobox
|
</Text>
|
||||||
options={paymentProviders.map((pp) => ({
|
</div>
|
||||||
label: formatProvider(pp.id),
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
value: pp.id,
|
<Form.Field
|
||||||
}))}
|
control={form.control}
|
||||||
{...field}
|
name="payment_providers"
|
||||||
/>
|
render={({ field }) => {
|
||||||
</Form.Control>
|
return (
|
||||||
<Form.ErrorMessage />
|
<Form.Item>
|
||||||
</Form.Item>
|
<Form.Label>
|
||||||
)
|
{t("fields.paymentProviders")}
|
||||||
}}
|
</Form.Label>
|
||||||
/>
|
<Form.Control>
|
||||||
</div>
|
<Combobox
|
||||||
</div>
|
options={paymentProviders.map((pp) => ({
|
||||||
|
label: formatProvider(pp.id),
|
||||||
|
value: pp.id,
|
||||||
|
}))}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</Form.Control>
|
||||||
|
<Form.ErrorMessage />
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SplitView.Content>
|
</div>
|
||||||
<SplitView.Drawer>
|
</div>
|
||||||
<div className="flex size-full flex-col overflow-hidden">
|
|
||||||
<DataTable
|
|
||||||
table={table}
|
|
||||||
columns={columns}
|
|
||||||
count={count}
|
|
||||||
pageSize={PAGE_SIZE}
|
|
||||||
orderBy={["name", "code"]}
|
|
||||||
pagination
|
|
||||||
search="autofocus"
|
|
||||||
layout="fill"
|
|
||||||
queryObject={raw}
|
|
||||||
prefix={PREFIX}
|
|
||||||
/>
|
|
||||||
<div className="flex items-center justify-end gap-x-2 border-t p-4">
|
|
||||||
<SplitView.Close type="button">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</SplitView.Close>
|
|
||||||
<Button size="small" type="button" onClick={saveCountries}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SplitView.Drawer>
|
|
||||||
</SplitView>
|
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
</form>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Loaded 100 of 120 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user