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