feat(dashboard,admin-shared): Add injection zones to regions, shipping profiles, and locations (#7467)
This commit is contained in:
1 parent
ebc4215f16
commit
0b0e210f67
63 files changed
+418
-267
No files matched your search
@@ -85,6 +85,29 @@ const GIFT_CARD_INJECTION_ZONES = [
|
|||||||
"custom_gift_card.after",
|
"custom_gift_card.after",
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
|
const REGION_INJECTION_ZONES = [
|
||||||
|
"region.details.before",
|
||||||
|
"region.details.after",
|
||||||
|
"region.list.before",
|
||||||
|
"region.list.after",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const SHIPPING_PROFILE_INJECTION_ZONES = [
|
||||||
|
"shipping_profile.details.before",
|
||||||
|
"shipping_profile.details.after",
|
||||||
|
"shipping_profile.list.before",
|
||||||
|
"shipping_profile.list.after",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const LOCATION_INJECTION_ZONES = [
|
||||||
|
"location.details.before",
|
||||||
|
"location.details.after",
|
||||||
|
"location.details.side.before",
|
||||||
|
"location.details.side.after",
|
||||||
|
"location.list.before",
|
||||||
|
"location.list.after",
|
||||||
|
] as const
|
||||||
|
|
||||||
const LOGIN_INJECTION_ZONES = ["login.before", "login.after"] as const
|
const LOGIN_INJECTION_ZONES = ["login.before", "login.after"] as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,5 +126,8 @@ export const INJECTION_ZONES = [
|
|||||||
...DISCOUNT_INJECTION_ZONES,
|
...DISCOUNT_INJECTION_ZONES,
|
||||||
...PROMOTION_INJECTION_ZONES,
|
...PROMOTION_INJECTION_ZONES,
|
||||||
...GIFT_CARD_INJECTION_ZONES,
|
...GIFT_CARD_INJECTION_ZONES,
|
||||||
|
...REGION_INJECTION_ZONES,
|
||||||
|
...SHIPPING_PROFILE_INJECTION_ZONES,
|
||||||
|
...LOCATION_INJECTION_ZONES,
|
||||||
...LOGIN_INJECTION_ZONES,
|
...LOGIN_INJECTION_ZONES,
|
||||||
] as const
|
] as const
|
||||||
+2
-2
@@ -54,8 +54,8 @@ const useSettingRoutes = (): NavItemProps[] => {
|
|||||||
to: "/settings/shipping-profiles",
|
to: "/settings/shipping-profiles",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("shipping.domain"),
|
label: t("location.domain"),
|
||||||
to: "/settings/shipping",
|
to: "/settings/locations",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[t]
|
[t]
|
||||||
|
|||||||
@@ -675,8 +675,8 @@
|
|||||||
"invalidEmail": "Email must be a valid email address."
|
"invalidEmail": "Email must be a valid email address."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shipping": {
|
"location": {
|
||||||
"title": "Location & Shipping",
|
"title": "Locations & Shipping",
|
||||||
"domain": "Location & Shipping",
|
"domain": "Location & Shipping",
|
||||||
"description": "Choose where you ship and how much you charge for shipping at checkout. Define shipping options specific for your locations.",
|
"description": "Choose where you ship and how much you charge for shipping at checkout. Define shipping options specific for your locations.",
|
||||||
"createLocation": "Create location",
|
"createLocation": "Create location",
|
||||||
|
|||||||
@@ -682,33 +682,33 @@ export const RouteMap: RouteObject[] = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "shipping",
|
path: "locations",
|
||||||
element: <Outlet />,
|
element: <Outlet />,
|
||||||
handle: {
|
handle: {
|
||||||
crumb: () => "Location & Shipping",
|
crumb: () => "Locations & Shipping",
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
lazy: () => import("../../routes/shipping/location-list"),
|
lazy: () => import("../../routes/locations/location-list"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "create",
|
path: "create",
|
||||||
lazy: () => import("../../routes/shipping/location-create"),
|
lazy: () => import("../../routes/locations/location-create"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ":location_id",
|
path: ":location_id",
|
||||||
lazy: () => import("../../routes/shipping/location-details"),
|
lazy: () => import("../../routes/locations/location-details"),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "edit",
|
path: "edit",
|
||||||
lazy: () => import("../../routes/shipping/location-edit"),
|
lazy: () => import("../../routes/locations/location-edit"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "sales-channels/edit",
|
path: "sales-channels/edit",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import(
|
import(
|
||||||
"../../routes/shipping/location-add-sales-channels"
|
"../../routes/locations/location-add-sales-channels"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -717,7 +717,7 @@ export const RouteMap: RouteObject[] = [
|
|||||||
{
|
{
|
||||||
path: "service-zones/create",
|
path: "service-zones/create",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import("../../routes/shipping/service-zone-create"),
|
import("../../routes/locations/service-zone-create"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "service-zone/:zone_id",
|
path: "service-zone/:zone_id",
|
||||||
@@ -725,13 +725,15 @@ export const RouteMap: RouteObject[] = [
|
|||||||
{
|
{
|
||||||
path: "edit",
|
path: "edit",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import("../../routes/shipping/service-zone-edit"),
|
import(
|
||||||
|
"../../routes/locations/service-zone-edit"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "edit-areas",
|
path: "edit-areas",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import(
|
import(
|
||||||
"../../routes/shipping/service-zone-areas-edit"
|
"../../routes/locations/service-zone-areas-edit"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -741,7 +743,7 @@ export const RouteMap: RouteObject[] = [
|
|||||||
path: "create",
|
path: "create",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import(
|
import(
|
||||||
"../../routes/shipping/shipping-options-create"
|
"../../routes/locations/shipping-options-create"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -751,14 +753,14 @@ export const RouteMap: RouteObject[] = [
|
|||||||
path: "edit",
|
path: "edit",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import(
|
import(
|
||||||
"../../routes/shipping/shipping-option-edit"
|
"../../routes/locations/shipping-option-edit"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "edit-pricing",
|
path: "edit-pricing",
|
||||||
lazy: () =>
|
lazy: () =>
|
||||||
import(
|
import(
|
||||||
"../../routes/shipping/shipping-options-edit-pricing"
|
"../../routes/locations/shipping-options-edit-pricing"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-3
@@ -55,7 +55,7 @@ export const CreateLocationForm = () => {
|
|||||||
address: values.address,
|
address: values.address,
|
||||||
})
|
})
|
||||||
|
|
||||||
handleSuccess("/settings/shipping")
|
handleSuccess("/settings/locations")
|
||||||
|
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("general.success"), {
|
||||||
description: t("locations.toast.create"),
|
description: t("locations.toast.create"),
|
||||||
@@ -92,10 +92,10 @@ export const CreateLocationForm = () => {
|
|||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16">
|
||||||
<div>
|
<div>
|
||||||
<Heading className="capitalize">
|
<Heading className="capitalize">
|
||||||
{t("shipping.createLocation")}
|
{t("location.createLocation")}
|
||||||
</Heading>
|
</Heading>
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
{t("shipping.createLocationDetailsHint")}
|
{t("location.createLocationDetailsHint")}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+44
-44
@@ -1,12 +1,3 @@
|
|||||||
import { useNavigate } from "react-router-dom"
|
|
||||||
import { useTranslation } from "react-i18next"
|
|
||||||
import { useMemo, useState } from "react"
|
|
||||||
import {
|
|
||||||
FulfillmentSetDTO,
|
|
||||||
ServiceZoneDTO,
|
|
||||||
ShippingOptionDTO,
|
|
||||||
StockLocationDTO,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import {
|
import {
|
||||||
ChevronDownMini,
|
ChevronDownMini,
|
||||||
CurrencyDollar,
|
CurrencyDollar,
|
||||||
@@ -15,6 +6,12 @@ import {
|
|||||||
Plus,
|
Plus,
|
||||||
Trash,
|
Trash,
|
||||||
} from "@medusajs/icons"
|
} from "@medusajs/icons"
|
||||||
|
import {
|
||||||
|
FulfillmentSetDTO,
|
||||||
|
ServiceZoneDTO,
|
||||||
|
ShippingOptionDTO,
|
||||||
|
StockLocationDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
@@ -25,19 +22,22 @@ import {
|
|||||||
toast,
|
toast,
|
||||||
usePrompt,
|
usePrompt,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
|
import { useMemo, useState } from "react"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { useNavigate } from "react-router-dom"
|
||||||
|
|
||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { countries as staticCountries } from "../../../../../lib/countries"
|
import { NoRecords } from "../../../../../components/common/empty-table-content"
|
||||||
|
import { ListSummary } from "../../../../../components/common/list-summary"
|
||||||
|
import { useDeleteShippingOption } from "../../../../../hooks/api/shipping-options"
|
||||||
import {
|
import {
|
||||||
useCreateFulfillmentSet,
|
useCreateFulfillmentSet,
|
||||||
useDeleteFulfillmentSet,
|
useDeleteFulfillmentSet,
|
||||||
useDeleteServiceZone,
|
useDeleteServiceZone,
|
||||||
useDeleteStockLocation,
|
useDeleteStockLocation,
|
||||||
} from "../../../../../hooks/api/stock-locations"
|
} from "../../../../../hooks/api/stock-locations"
|
||||||
import { useDeleteShippingOption } from "../../../../../hooks/api/shipping-options"
|
import { countries as staticCountries } from "../../../../../lib/countries"
|
||||||
import { formatProvider } from "../../../../../lib/format-provider"
|
import { formatProvider } from "../../../../../lib/format-provider"
|
||||||
import { NoRecords } from "../../../../../components/common/empty-table-content"
|
|
||||||
import { ListSummary } from "../../../../../components/common/list-summary"
|
|
||||||
import {
|
import {
|
||||||
isOptionEnabledInStore,
|
isOptionEnabledInStore,
|
||||||
isReturnOption,
|
isReturnOption,
|
||||||
@@ -103,7 +103,7 @@ function ShippingOption({
|
|||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
const res = await prompt({
|
const res = await prompt({
|
||||||
title: t("general.areYouSure"),
|
title: t("general.areYouSure"),
|
||||||
description: t("shipping.shippingOptions.deleteWarning", {
|
description: t("location.shippingOptions.deleteWarning", {
|
||||||
name: option.name,
|
name: option.name,
|
||||||
}),
|
}),
|
||||||
confirmText: t("actions.delete"),
|
confirmText: t("actions.delete"),
|
||||||
@@ -118,7 +118,7 @@ function ShippingOption({
|
|||||||
await deleteOption()
|
await deleteOption()
|
||||||
|
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("general.success"), {
|
||||||
description: t("shipping.shippingOptions.toast.delete", {
|
description: t("location.shippingOptions.toast.delete", {
|
||||||
name: option.name,
|
name: option.name,
|
||||||
}),
|
}),
|
||||||
dismissLabel: t("actions.close"),
|
dismissLabel: t("actions.close"),
|
||||||
@@ -141,7 +141,7 @@ function ShippingOption({
|
|||||||
</div>
|
</div>
|
||||||
{isInStore && (
|
{isInStore && (
|
||||||
<Badge className="mr-4" color="purple">
|
<Badge className="mr-4" color="purple">
|
||||||
{t("shipping.shippingOptions.inStore")}
|
{t("location.shippingOptions.inStore")}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
@@ -150,13 +150,13 @@ function ShippingOption({
|
|||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
icon: <PencilSquare />,
|
icon: <PencilSquare />,
|
||||||
label: t("shipping.serviceZone.editOption"),
|
label: t("location.serviceZone.editOption"),
|
||||||
to: `/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${option.service_zone_id}/shipping-option/${option.id}/edit`,
|
to: `/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${option.service_zone_id}/shipping-option/${option.id}/edit`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("shipping.serviceZone.editPrices"),
|
label: t("location.serviceZone.editPrices"),
|
||||||
icon: <CurrencyDollar />,
|
icon: <CurrencyDollar />,
|
||||||
to: `/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${option.service_zone_id}/shipping-option/${option.id}/edit-pricing`,
|
to: `/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${option.service_zone_id}/shipping-option/${option.id}/edit-pricing`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("actions.delete"),
|
label: t("actions.delete"),
|
||||||
@@ -196,18 +196,18 @@ function ServiceZoneOptions({
|
|||||||
<div className="mt-4 flex flex-col border-t border-dashed px-6 py-4">
|
<div className="mt-4 flex flex-col border-t border-dashed px-6 py-4">
|
||||||
<div className="item-center flex justify-between">
|
<div className="item-center flex justify-between">
|
||||||
<span className="text-ui-fg-subtle txt-small self-center font-medium">
|
<span className="text-ui-fg-subtle txt-small self-center font-medium">
|
||||||
{t("shipping.serviceZone.shippingOptions")}
|
{t("location.serviceZone.shippingOptions")}
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
className="text-ui-fg-interactive txt-small px-0 font-medium hover:bg-transparent active:bg-transparent"
|
className="text-ui-fg-interactive txt-small px-0 font-medium hover:bg-transparent active:bg-transparent"
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(
|
navigate(
|
||||||
`/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/shipping-option/create`
|
`/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/shipping-option/create`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("shipping.serviceZone.addOption")}
|
{t("location.serviceZone.addOption")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -228,18 +228,18 @@ function ServiceZoneOptions({
|
|||||||
<div className="-mb-4 flex flex-col border-t border-dashed px-6 py-4">
|
<div className="-mb-4 flex flex-col border-t border-dashed px-6 py-4">
|
||||||
<div className="item-center flex justify-between">
|
<div className="item-center flex justify-between">
|
||||||
<span className="text-ui-fg-subtle txt-small self-center font-medium">
|
<span className="text-ui-fg-subtle txt-small self-center font-medium">
|
||||||
{t("shipping.serviceZone.returnOptions")}
|
{t("location.serviceZone.returnOptions")}
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
className="text-ui-fg-interactive txt-small px-0 font-medium hover:bg-transparent active:bg-transparent"
|
className="text-ui-fg-interactive txt-small px-0 font-medium hover:bg-transparent active:bg-transparent"
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(
|
navigate(
|
||||||
`/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/shipping-option/create?is_return`
|
`/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/shipping-option/create?is_return`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("shipping.serviceZone.addOption")}
|
{t("location.serviceZone.addOption")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
|
|||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
const res = await prompt({
|
const res = await prompt({
|
||||||
title: t("general.areYouSure"),
|
title: t("general.areYouSure"),
|
||||||
description: t("shipping.serviceZone.deleteWarning", {
|
description: t("location.serviceZone.deleteWarning", {
|
||||||
name: zone.name,
|
name: zone.name,
|
||||||
}),
|
}),
|
||||||
confirmText: t("actions.delete"),
|
confirmText: t("actions.delete"),
|
||||||
@@ -295,7 +295,7 @@ function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
|
|||||||
await deleteZone()
|
await deleteZone()
|
||||||
|
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("general.success"), {
|
||||||
description: t("shipping.serviceZone.toast.delete", {
|
description: t("location.serviceZone.toast.delete", {
|
||||||
name: zone.name,
|
name: zone.name,
|
||||||
}),
|
}),
|
||||||
dismissLabel: t("actions.close"),
|
dismissLabel: t("actions.close"),
|
||||||
@@ -350,14 +350,14 @@ function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
|
|||||||
<span>·</span>
|
<span>·</span>
|
||||||
<Text className="text-ui-fg-subtle txt-small">
|
<Text className="text-ui-fg-subtle txt-small">
|
||||||
{shippingOptionsCount}{" "}
|
{shippingOptionsCount}{" "}
|
||||||
{t("shipping.serviceZone.optionsLength", {
|
{t("location.serviceZone.optionsLength", {
|
||||||
count: shippingOptionsCount,
|
count: shippingOptionsCount,
|
||||||
})}
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
<span>·</span>
|
<span>·</span>
|
||||||
<Text className="text-ui-fg-subtle txt-small">
|
<Text className="text-ui-fg-subtle txt-small">
|
||||||
{returnOptionsCount}{" "}
|
{returnOptionsCount}{" "}
|
||||||
{t("shipping.serviceZone.returnOptionsLength", {
|
{t("location.serviceZone.returnOptionsLength", {
|
||||||
count: returnOptionsCount,
|
count: returnOptionsCount,
|
||||||
})}
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -389,12 +389,12 @@ function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
|
|||||||
{
|
{
|
||||||
label: t("actions.edit"),
|
label: t("actions.edit"),
|
||||||
icon: <PencilSquare />,
|
icon: <PencilSquare />,
|
||||||
to: `/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/edit`,
|
to: `/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/edit`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("shipping.serviceZone.areas.manage"),
|
label: t("location.serviceZone.areas.manage"),
|
||||||
icon: <Map />,
|
icon: <Map />,
|
||||||
to: `/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/edit-areas`,
|
to: `/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/edit-areas`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("actions.delete"),
|
label: t("actions.delete"),
|
||||||
@@ -469,7 +469,7 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
const res = await prompt({
|
const res = await prompt({
|
||||||
title: t("general.areYouSure"),
|
title: t("general.areYouSure"),
|
||||||
description: t("shipping.fulfillmentSet.disableWarning", {
|
description: t("location.fulfillmentSet.disableWarning", {
|
||||||
name: fulfillmentSet?.name,
|
name: fulfillmentSet?.name,
|
||||||
}),
|
}),
|
||||||
confirmText: t("actions.delete"),
|
confirmText: t("actions.delete"),
|
||||||
@@ -484,7 +484,7 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
await deleteFulfillmentSet()
|
await deleteFulfillmentSet()
|
||||||
|
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("general.success"), {
|
||||||
description: t("shipping.fulfillmentSet.toast.disable", {
|
description: t("location.fulfillmentSet.toast.disable", {
|
||||||
name: fulfillmentSet?.name,
|
name: fulfillmentSet?.name,
|
||||||
}),
|
}),
|
||||||
dismissLabel: t("actions.close"),
|
dismissLabel: t("actions.close"),
|
||||||
@@ -502,7 +502,7 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
<div className="flex flex-col divide-y">
|
<div className="flex flex-col divide-y">
|
||||||
<div className="flex items-center justify-between px-6 py-4">
|
<div className="flex items-center justify-between px-6 py-4">
|
||||||
<Text size="large" weight="plus" className="flex-1" as="div">
|
<Text size="large" weight="plus" className="flex-1" as="div">
|
||||||
{t(`shipping.fulfillmentSet.${type}.offers`)}
|
{t(`location.fulfillmentSet.${type}.offers`)}
|
||||||
</Text>
|
</Text>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<StatusBadge color={fulfillmentSetExists ? "green" : "red"}>
|
<StatusBadge color={fulfillmentSetExists ? "green" : "red"}>
|
||||||
@@ -517,10 +517,10 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
icon: <Plus />,
|
icon: <Plus />,
|
||||||
label: t("shipping.fulfillmentSet.addZone"),
|
label: t("location.fulfillmentSet.addZone"),
|
||||||
onClick: () =>
|
onClick: () =>
|
||||||
navigate(
|
navigate(
|
||||||
`/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSet.id}/service-zones/create`
|
`/settings/locations/${locationId}/fulfillment-set/${fulfillmentSet.id}/service-zones/create`
|
||||||
),
|
),
|
||||||
disabled: !fulfillmentSetExists,
|
disabled: !fulfillmentSetExists,
|
||||||
},
|
},
|
||||||
@@ -543,7 +543,7 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
{fulfillmentSetExists && !hasServiceZones && (
|
{fulfillmentSetExists && !hasServiceZones && (
|
||||||
<div className="text-ui-fg-muted txt-medium flex flex-col items-center justify-center gap-y-4 py-8">
|
<div className="text-ui-fg-muted txt-medium flex flex-col items-center justify-center gap-y-4 py-8">
|
||||||
<NoRecords
|
<NoRecords
|
||||||
message={t("shipping.fulfillmentSet.placeholder")}
|
message={t("location.fulfillmentSet.placeholder")}
|
||||||
className="h-fit"
|
className="h-fit"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -551,11 +551,11 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(
|
navigate(
|
||||||
`/settings/shipping/${locationId}/fulfillment-set/${fulfillmentSet.id}/service-zones/create`
|
`/settings/locations/${locationId}/fulfillment-set/${fulfillmentSet.id}/service-zones/create`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("shipping.fulfillmentSet.addZone")}
|
{t("location.fulfillmentSet.addZone")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -586,7 +586,7 @@ const Actions = ({ location }: { location: StockLocationDTO }) => {
|
|||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
const res = await prompt({
|
const res = await prompt({
|
||||||
title: t("general.areYouSure"),
|
title: t("general.areYouSure"),
|
||||||
description: t("shipping.deleteLocationWarning", {
|
description: t("location.deleteLocationWarning", {
|
||||||
name: location.name,
|
name: location.name,
|
||||||
}),
|
}),
|
||||||
verificationText: location.name,
|
verificationText: location.name,
|
||||||
@@ -602,7 +602,7 @@ const Actions = ({ location }: { location: StockLocationDTO }) => {
|
|||||||
try {
|
try {
|
||||||
await mutateAsync(undefined)
|
await mutateAsync(undefined)
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("general.success"), {
|
||||||
description: t("shipping.toast.delete"),
|
description: t("location.toast.delete"),
|
||||||
dismissLabel: t("actions.close"),
|
dismissLabel: t("actions.close"),
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -611,7 +611,7 @@ const Actions = ({ location }: { location: StockLocationDTO }) => {
|
|||||||
dismissLabel: t("actions.close"),
|
dismissLabel: t("actions.close"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
navigate("/settings/shipping", { replace: true })
|
navigate("/settings/locations", { replace: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
File renamed without changes.
+5
-5
@@ -1,11 +1,11 @@
|
|||||||
|
import { Channels, PencilSquare } from "@medusajs/icons"
|
||||||
|
import { StockLocationDTO } from "@medusajs/types"
|
||||||
import { Heading, Text } from "@medusajs/ui"
|
import { Heading, Text } from "@medusajs/ui"
|
||||||
import { Trans, useTranslation } from "react-i18next"
|
import { Trans, useTranslation } from "react-i18next"
|
||||||
import { StockLocationDTO } from "@medusajs/types"
|
|
||||||
import { Channels, PencilSquare } from "@medusajs/icons"
|
|
||||||
|
|
||||||
import { useSalesChannels } from "../../../../../hooks/api/sales-channels"
|
|
||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { ListSummary } from "../../../../../components/common/list-summary"
|
import { ListSummary } from "../../../../../components/common/list-summary"
|
||||||
|
import { useSalesChannels } from "../../../../../hooks/api/sales-channels"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
location: StockLocationDTO
|
location: StockLocationDTO
|
||||||
@@ -20,7 +20,7 @@ function LocationsSalesChannelsSection({ location }: Props) {
|
|||||||
return (
|
return (
|
||||||
<div className="shadow-elevation-card-rest bg-ui-bg-base rounded-md p-4">
|
<div className="shadow-elevation-card-rest bg-ui-bg-base rounded-md p-4">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
<Heading level="h2">{t("shipping.salesChannels.title")}</Heading>
|
<Heading level="h2">{t("location.salesChannels.title")}</Heading>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
groups={[
|
groups={[
|
||||||
{
|
{
|
||||||
@@ -43,7 +43,7 @@ function LocationsSalesChannelsSection({ location }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
{noChannels ? (
|
{noChannels ? (
|
||||||
<Text size="small" leading="compact" className="text-ui-fg-subtle">
|
<Text size="small" leading="compact" className="text-ui-fg-subtle">
|
||||||
{t("shipping.salesChannels.placeholder")}
|
{t("location.salesChannels.placeholder")}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<ListSummary
|
<ListSummary
|
||||||
File renamed without changes.
File renamed without changes.
+92
@@ -0,0 +1,92 @@
|
|||||||
|
import { Outlet, useLoaderData, useParams } from "react-router-dom"
|
||||||
|
|
||||||
|
import { JsonViewSection } from "../../../components/common/json-view-section"
|
||||||
|
import { useStockLocation } from "../../../hooks/api/stock-locations"
|
||||||
|
import { LocationGeneralSection } from "./components/location-general-section"
|
||||||
|
import LocationsSalesChannelsSection from "./components/location-sales-channels-section/locations-sales-channels-section"
|
||||||
|
import { locationLoader } from "./loader"
|
||||||
|
|
||||||
|
import after from "virtual:medusa/widgets/location/details/after"
|
||||||
|
import before from "virtual:medusa/widgets/location/details/before"
|
||||||
|
import sideAfter from "virtual:medusa/widgets/location/details/side/after"
|
||||||
|
import sideBefore from "virtual:medusa/widgets/location/details/side/before"
|
||||||
|
|
||||||
|
export const LocationDetails = () => {
|
||||||
|
const initialData = useLoaderData() as Awaited<
|
||||||
|
ReturnType<typeof locationLoader>
|
||||||
|
>
|
||||||
|
|
||||||
|
const { location_id } = useParams()
|
||||||
|
const {
|
||||||
|
stock_location: location,
|
||||||
|
isPending: isLoading,
|
||||||
|
isError,
|
||||||
|
error,
|
||||||
|
} = useStockLocation(
|
||||||
|
location_id!,
|
||||||
|
{
|
||||||
|
fields:
|
||||||
|
"name,*sales_channels,address.city,address.country_code,fulfillment_sets.type,fulfillment_sets.name,*fulfillment_sets.service_zones.geo_zones,*fulfillment_sets.service_zones,*fulfillment_sets.service_zones.shipping_options,*fulfillment_sets.service_zones.shipping_options.rules,*fulfillment_sets.service_zones.shipping_options.shipping_profile",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
initialData,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: Move to loading.tsx and set as Suspense fallback for the route
|
||||||
|
if (isLoading || !location) {
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-y-3">
|
||||||
|
{before.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={location} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<div className="flex flex-col gap-x-4 lg:flex-row xl:items-start">
|
||||||
|
<div className="flex w-full flex-col gap-y-2">
|
||||||
|
<LocationGeneralSection location={location} />
|
||||||
|
{after.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={location} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<div className="hidden xl:block">
|
||||||
|
<JsonViewSection data={location} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
||||||
|
{sideBefore.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={location} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<LocationsSalesChannelsSection location={location} />
|
||||||
|
{sideAfter.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={location} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<div className="xl:hidden">
|
||||||
|
<JsonViewSection data={location} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+15
-15
@@ -1,3 +1,9 @@
|
|||||||
|
import { Buildings, PencilSquare, Trash } from "@medusajs/icons"
|
||||||
|
import {
|
||||||
|
FulfillmentSetDTO,
|
||||||
|
SalesChannelDTO,
|
||||||
|
StockLocationDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Container,
|
Container,
|
||||||
@@ -6,19 +12,13 @@ import {
|
|||||||
toast,
|
toast,
|
||||||
usePrompt,
|
usePrompt,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
import {
|
|
||||||
FulfillmentSetDTO,
|
|
||||||
SalesChannelDTO,
|
|
||||||
StockLocationDTO,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { Buildings, PencilSquare, Trash } from "@medusajs/icons"
|
|
||||||
import { useNavigate } from "react-router-dom"
|
import { useNavigate } from "react-router-dom"
|
||||||
|
|
||||||
import { countries } from "../../../../../lib/countries"
|
|
||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { useDeleteStockLocation } from "../../../../../hooks/api/stock-locations"
|
|
||||||
import { BadgeListSummary } from "../../../../../components/common/badge-list-summary"
|
import { BadgeListSummary } from "../../../../../components/common/badge-list-summary"
|
||||||
|
import { useDeleteStockLocation } from "../../../../../hooks/api/stock-locations"
|
||||||
|
import { countries } from "../../../../../lib/countries"
|
||||||
|
|
||||||
type SalesChannelsProps = {
|
type SalesChannelsProps = {
|
||||||
salesChannels?: SalesChannelDTO[]
|
salesChannels?: SalesChannelDTO[]
|
||||||
@@ -37,7 +37,7 @@ function SalesChannels(props: SalesChannelsProps) {
|
|||||||
className="text-ui-fg-subtle flex-1"
|
className="text-ui-fg-subtle flex-1"
|
||||||
as="div"
|
as="div"
|
||||||
>
|
>
|
||||||
{t(`shipping.fulfillmentSet.salesChannels`)}
|
{t(`location.fulfillmentSet.salesChannels`)}
|
||||||
</Text>
|
</Text>
|
||||||
<div className="flex-1 text-left">
|
<div className="flex-1 text-left">
|
||||||
{salesChannels?.length ? (
|
{salesChannels?.length ? (
|
||||||
@@ -80,7 +80,7 @@ function FulfillmentSet(props: FulfillmentSetProps) {
|
|||||||
className="text-ui-fg-subtle flex-1"
|
className="text-ui-fg-subtle flex-1"
|
||||||
as="div"
|
as="div"
|
||||||
>
|
>
|
||||||
{t(`shipping.fulfillmentSet.${type}.title`)}
|
{t(`location.fulfillmentSet.${type}.title`)}
|
||||||
</Text>
|
</Text>
|
||||||
<div className="flex-1 text-left">
|
<div className="flex-1 text-left">
|
||||||
<StatusBadge color={fulfillmentSetExists ? "green" : "red"}>
|
<StatusBadge color={fulfillmentSetExists ? "green" : "red"}>
|
||||||
@@ -107,7 +107,7 @@ function Location(props: LocationProps) {
|
|||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
const result = await prompt({
|
const result = await prompt({
|
||||||
title: t("general.areYouSure"),
|
title: t("general.areYouSure"),
|
||||||
description: t("shipping.deleteLocation.confirm", {
|
description: t("location.deleteLocation.confirm", {
|
||||||
name: location.name,
|
name: location.name,
|
||||||
}),
|
}),
|
||||||
confirmText: t("actions.remove"),
|
confirmText: t("actions.remove"),
|
||||||
@@ -122,7 +122,7 @@ function Location(props: LocationProps) {
|
|||||||
await deleteLocation()
|
await deleteLocation()
|
||||||
|
|
||||||
toast.success(t("general.success"), {
|
toast.success(t("general.success"), {
|
||||||
description: t("shipping.deleteLocation.success", {
|
description: t("location.deleteLocation.success", {
|
||||||
name: location.name,
|
name: location.name,
|
||||||
}),
|
}),
|
||||||
dismissLabel: t("general.close"),
|
dismissLabel: t("general.close"),
|
||||||
@@ -169,10 +169,10 @@ function Location(props: LocationProps) {
|
|||||||
{
|
{
|
||||||
label: t("actions.edit"),
|
label: t("actions.edit"),
|
||||||
icon: <PencilSquare />,
|
icon: <PencilSquare />,
|
||||||
to: `/settings/shipping/${location.id}/edit`,
|
to: `/settings/locations/${location.id}/edit`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("shipping.deleteLocation.label"),
|
label: t("location.deleteLocation.label"),
|
||||||
icon: <Trash />,
|
icon: <Trash />,
|
||||||
onClick: handleDelete,
|
onClick: handleDelete,
|
||||||
},
|
},
|
||||||
@@ -182,7 +182,7 @@ function Location(props: LocationProps) {
|
|||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
className="text-ui-fg-interactive rounded-none pl-5 hover:bg-transparent active:bg-transparent"
|
className="text-ui-fg-interactive rounded-none pl-5 hover:bg-transparent active:bg-transparent"
|
||||||
onClick={() => navigate(`/settings/shipping/${location.id}`)}
|
onClick={() => navigate(`/settings/locations/${location.id}`)}
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
>
|
>
|
||||||
{t("actions.viewDetails")}
|
{t("actions.viewDetails")}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,62 @@
|
|||||||
|
import { Button, Container, Heading, Text } from "@medusajs/ui"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { Link, Outlet, useLoaderData } from "react-router-dom"
|
||||||
|
|
||||||
|
import { useStockLocations } from "../../../hooks/api/stock-locations"
|
||||||
|
import Location from "./components/location/location"
|
||||||
|
import { locationListFields } from "./const"
|
||||||
|
import { shippingListLoader } from "./loader"
|
||||||
|
|
||||||
|
import after from "virtual:medusa/widgets/location/list/after"
|
||||||
|
import before from "virtual:medusa/widgets/location/list/before"
|
||||||
|
|
||||||
|
export function LocationList() {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const initialData = useLoaderData() as Awaited<
|
||||||
|
ReturnType<typeof shippingListLoader>
|
||||||
|
>
|
||||||
|
|
||||||
|
const { stock_locations: stockLocations = [], isPending } = useStockLocations(
|
||||||
|
{
|
||||||
|
fields: locationListFields,
|
||||||
|
},
|
||||||
|
{ initialData }
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-y-3">
|
||||||
|
{before.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<Container className="flex h-fit items-center justify-between p-8">
|
||||||
|
<div>
|
||||||
|
<Heading className="mb-2">{t("location.title")}</Heading>
|
||||||
|
<Text className="text-ui-fg-subtle txt-small">
|
||||||
|
{t("location.description")}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<Button size="small" variant="secondary" asChild>
|
||||||
|
<Link to="create">{t("location.createLocation")}</Link>
|
||||||
|
</Button>
|
||||||
|
</Container>
|
||||||
|
<div className="flex flex-col gap-3 lg:col-span-2">
|
||||||
|
{stockLocations.map((location) => (
|
||||||
|
<Location key={location.id} location={location} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{after.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
+16
-16
@@ -1,12 +1,14 @@
|
|||||||
import { useForm } from "react-hook-form"
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import {
|
import {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
createColumnHelper,
|
createColumnHelper,
|
||||||
RowSelectionState,
|
RowSelectionState,
|
||||||
} from "@tanstack/react-table"
|
} from "@tanstack/react-table"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
|
import { XMarkMini } from "@medusajs/icons"
|
||||||
|
import { HttpTypes, ServiceZoneDTO } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Badge,
|
Badge,
|
||||||
@@ -17,23 +19,21 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
toast,
|
toast,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
import { ServiceZoneDTO, HttpTypes } from "@medusajs/types"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { XMarkMini } from "@medusajs/icons"
|
|
||||||
|
|
||||||
|
import { useEffect, useMemo, useState } from "react"
|
||||||
|
import { SplitView } from "../../../../../components/layout/split-view"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/route-modal"
|
} from "../../../../../components/route-modal"
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
|
||||||
import { useUpdateServiceZone } from "../../../../../hooks/api/stock-locations"
|
|
||||||
import { useEffect, useMemo, useState } from "react"
|
|
||||||
import { useCountryTableQuery } from "../../../../regions/common/hooks/use-country-table-query"
|
|
||||||
import { useCountries } from "../../../../regions/common/hooks/use-countries"
|
|
||||||
import { countries as staticCountries } from "../../../../../lib/countries"
|
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
|
||||||
import { useCountryTableColumns } from "../../../../regions/common/hooks/use-country-table-columns"
|
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { useUpdateServiceZone } from "../../../../../hooks/api/stock-locations"
|
||||||
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
|
import { countries as staticCountries } from "../../../../../lib/countries"
|
||||||
|
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"
|
||||||
|
|
||||||
const PREFIX = "ac"
|
const PREFIX = "ac"
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 50
|
||||||
@@ -215,7 +215,7 @@ export function EditServiceZoneAreasForm({
|
|||||||
<SplitView.Content className="mx-auto max-w-[720px]">
|
<SplitView.Content className="mx-auto max-w-[720px]">
|
||||||
<div className="container w-fit px-1 py-8">
|
<div className="container w-fit px-1 py-8">
|
||||||
<Heading className="mt-8 text-2xl">
|
<Heading className="mt-8 text-2xl">
|
||||||
{t("shipping.serviceZone.editAreasTitle", {
|
{t("location.serviceZone.editAreasTitle", {
|
||||||
zone: zone.name,
|
zone: zone.name,
|
||||||
})}
|
})}
|
||||||
</Heading>
|
</Heading>
|
||||||
@@ -224,10 +224,10 @@ export function EditServiceZoneAreasForm({
|
|||||||
<div className="container flex items-center justify-between py-8 pr-1">
|
<div className="container flex items-center justify-between py-8 pr-1">
|
||||||
<div>
|
<div>
|
||||||
<Text weight="plus">
|
<Text weight="plus">
|
||||||
{t("shipping.serviceZone.areas.title")}
|
{t("location.serviceZone.areas.title")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-ui-fg-subtle mt-2">
|
<Text className="text-ui-fg-subtle mt-2">
|
||||||
{t("shipping.serviceZone.areas.description")}
|
{t("location.serviceZone.areas.description")}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@@ -235,7 +235,7 @@ export function EditServiceZoneAreasForm({
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
{t("shipping.serviceZone.areas.manage")}
|
{t("location.serviceZone.areas.manage")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{!!selectedCountries.length && (
|
{!!selectedCountries.length && (
|
||||||
@@ -268,7 +268,7 @@ export function EditServiceZoneAreasForm({
|
|||||||
)}
|
)}
|
||||||
{showAreasError && (
|
{showAreasError && (
|
||||||
<Alert dismissible variant="error">
|
<Alert dismissible variant="error">
|
||||||
{t("shipping.serviceZone.areas.error")}
|
{t("location.serviceZone.areas.error")}
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
</SplitView.Content>
|
</SplitView.Content>
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+20
-20
@@ -1,12 +1,14 @@
|
|||||||
import { useForm } from "react-hook-form"
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import {
|
import {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
createColumnHelper,
|
createColumnHelper,
|
||||||
RowSelectionState,
|
RowSelectionState,
|
||||||
} from "@tanstack/react-table"
|
} from "@tanstack/react-table"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
|
import { XMarkMini } from "@medusajs/icons"
|
||||||
|
import { FulfillmentSetDTO, HttpTypes } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Badge,
|
Badge,
|
||||||
@@ -18,24 +20,22 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
toast,
|
toast,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
import { FulfillmentSetDTO, HttpTypes } from "@medusajs/types"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { XMarkMini } from "@medusajs/icons"
|
|
||||||
|
|
||||||
|
import { useEffect, useMemo, useState } from "react"
|
||||||
|
import { Form } from "../../../../../components/common/form"
|
||||||
|
import { SplitView } from "../../../../../components/layout/split-view"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/route-modal"
|
} from "../../../../../components/route-modal"
|
||||||
import { Form } from "../../../../../components/common/form"
|
|
||||||
import { SplitView } from "../../../../../components/layout/split-view"
|
|
||||||
import { useCreateServiceZone } from "../../../../../hooks/api/stock-locations"
|
|
||||||
import { useEffect, useMemo, useState } from "react"
|
|
||||||
import { useCountryTableQuery } from "../../../../regions/common/hooks/use-country-table-query"
|
|
||||||
import { useCountries } from "../../../../regions/common/hooks/use-countries"
|
|
||||||
import { countries as staticCountries } from "../../../../../lib/countries"
|
|
||||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
|
||||||
import { useCountryTableColumns } from "../../../../regions/common/hooks/use-country-table-columns"
|
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { useCreateServiceZone } from "../../../../../hooks/api/stock-locations"
|
||||||
|
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||||
|
import { countries as staticCountries } from "../../../../../lib/countries"
|
||||||
|
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"
|
||||||
|
|
||||||
const PREFIX = "ac"
|
const PREFIX = "ac"
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 50
|
||||||
@@ -211,7 +211,7 @@ export function CreateServiceZoneForm({
|
|||||||
<SplitView.Content className="mx-auto max-w-[720px]">
|
<SplitView.Content className="mx-auto max-w-[720px]">
|
||||||
<div className="container w-fit px-1 py-8">
|
<div className="container w-fit px-1 py-8">
|
||||||
<Heading className="mb-12 mt-8 text-2xl">
|
<Heading className="mb-12 mt-8 text-2xl">
|
||||||
{t("shipping.fulfillmentSet.create.title", {
|
{t("location.fulfillmentSet.create.title", {
|
||||||
fulfillmentSet: fulfillmentSet.name,
|
fulfillmentSet: fulfillmentSet.name,
|
||||||
})}
|
})}
|
||||||
</Heading>
|
</Heading>
|
||||||
@@ -224,7 +224,7 @@ export function CreateServiceZoneForm({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.serviceZone.create.zoneName")}
|
{t("location.serviceZone.create.zoneName")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Input placeholder={t("fields.name")} {...field} />
|
<Input placeholder={t("fields.name")} {...field} />
|
||||||
@@ -239,10 +239,10 @@ export function CreateServiceZoneForm({
|
|||||||
|
|
||||||
<Alert>
|
<Alert>
|
||||||
<Text weight="plus">
|
<Text weight="plus">
|
||||||
{t("shipping.serviceZone.create.subtitle")}
|
{t("location.serviceZone.create.subtitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-ui-fg-subtle mt-2">
|
<Text className="text-ui-fg-subtle mt-2">
|
||||||
{t("shipping.serviceZone.create.description")}
|
{t("location.serviceZone.create.description")}
|
||||||
</Text>
|
</Text>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
@@ -250,10 +250,10 @@ export function CreateServiceZoneForm({
|
|||||||
<div className="container flex items-center justify-between py-8 pr-1">
|
<div className="container flex items-center justify-between py-8 pr-1">
|
||||||
<div>
|
<div>
|
||||||
<Text weight="plus">
|
<Text weight="plus">
|
||||||
{t("shipping.serviceZone.areas.title")}
|
{t("location.serviceZone.areas.title")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-ui-fg-subtle mt-2">
|
<Text className="text-ui-fg-subtle mt-2">
|
||||||
{t("shipping.serviceZone.areas.description")}
|
{t("location.serviceZone.areas.description")}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@@ -261,7 +261,7 @@ export function CreateServiceZoneForm({
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
{t("shipping.serviceZone.areas.manage")}
|
{t("location.serviceZone.areas.manage")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{!!selectedCountries.length && (
|
{!!selectedCountries.length && (
|
||||||
@@ -294,7 +294,7 @@ export function CreateServiceZoneForm({
|
|||||||
)}
|
)}
|
||||||
{showAreasError && (
|
{showAreasError && (
|
||||||
<Alert dismissible variant="error">
|
<Alert dismissible variant="error">
|
||||||
{t("shipping.serviceZone.areas.error")}
|
{t("location.serviceZone.areas.error")}
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
</SplitView.Content>
|
</SplitView.Content>
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
|
import { ServiceZoneDTO } from "@medusajs/types"
|
||||||
import { Alert, Button, Input, Text, toast } from "@medusajs/ui"
|
import { Alert, Button, Input, Text, toast } from "@medusajs/ui"
|
||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
import { ServiceZoneDTO } from "@medusajs/types"
|
|
||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import {
|
import {
|
||||||
@@ -88,10 +88,10 @@ export const EditServiceZoneForm = ({
|
|||||||
</div>
|
</div>
|
||||||
<Alert>
|
<Alert>
|
||||||
<Text weight="plus">
|
<Text weight="plus">
|
||||||
{t("shipping.serviceZone.create.subtitle")}
|
{t("location.serviceZone.create.subtitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-ui-fg-subtle mt-2">
|
<Text className="text-ui-fg-subtle mt-2">
|
||||||
{t("shipping.serviceZone.create.description")}
|
{t("location.serviceZone.create.description")}
|
||||||
</Text>
|
</Text>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
File renamed without changes.
File renamed without changes.
+2
-2
@@ -3,8 +3,8 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { json, useParams } from "react-router-dom"
|
import { json, useParams } from "react-router-dom"
|
||||||
|
|
||||||
import { RouteDrawer } from "../../../components/route-modal"
|
import { RouteDrawer } from "../../../components/route-modal"
|
||||||
import { EditServiceZoneForm } from "./components/edit-region-form"
|
|
||||||
import { useStockLocation } from "../../../hooks/api/stock-locations"
|
import { useStockLocation } from "../../../hooks/api/stock-locations"
|
||||||
|
import { EditServiceZoneForm } from "./components/edit-region-form"
|
||||||
|
|
||||||
export const ServiceZoneEdit = () => {
|
export const ServiceZoneEdit = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@@ -36,7 +36,7 @@ export const ServiceZoneEdit = () => {
|
|||||||
return (
|
return (
|
||||||
<RouteDrawer>
|
<RouteDrawer>
|
||||||
<RouteDrawer.Header>
|
<RouteDrawer.Header>
|
||||||
<Heading>{t("shipping.serviceZone.edit.title")}</Heading>
|
<Heading>{t("location.serviceZone.edit.title")}</Heading>
|
||||||
</RouteDrawer.Header>
|
</RouteDrawer.Header>
|
||||||
{!isPending && zone && (
|
{!isPending && zone && (
|
||||||
<EditServiceZoneForm
|
<EditServiceZoneForm
|
||||||
+12
-12
@@ -9,12 +9,12 @@ import {
|
|||||||
RouteDrawer,
|
RouteDrawer,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/route-modal"
|
} from "../../../../../components/route-modal"
|
||||||
import { useShippingProfiles } from "../../../../../hooks/api/shipping-profiles"
|
|
||||||
import { useUpdateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
|
||||||
import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers"
|
import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers"
|
||||||
import { isOptionEnabledInStore } from "../../../../../lib/shipping-options"
|
import { useUpdateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
||||||
import { formatProvider } from "../../../../../lib/format-provider"
|
import { useShippingProfiles } from "../../../../../hooks/api/shipping-profiles"
|
||||||
import { pick } from "../../../../../lib/common"
|
import { pick } from "../../../../../lib/common"
|
||||||
|
import { formatProvider } from "../../../../../lib/format-provider"
|
||||||
|
import { isOptionEnabledInStore } from "../../../../../lib/shipping-options"
|
||||||
|
|
||||||
enum ShippingAllocation {
|
enum ShippingAllocation {
|
||||||
FlatRate = "flat",
|
FlatRate = "flat",
|
||||||
@@ -118,26 +118,26 @@ export const EditShippingOptionForm = ({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.create.allocation")}
|
{t("location.shippingOptions.create.allocation")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<RadioGroup {...field} onValueChange={field.onChange}>
|
<RadioGroup {...field} onValueChange={field.onChange}>
|
||||||
<RadioGroup.ChoiceBox
|
<RadioGroup.ChoiceBox
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
value={ShippingAllocation.FlatRate}
|
value={ShippingAllocation.FlatRate}
|
||||||
label={t("shipping.shippingOptions.create.fixed")}
|
label={t("location.shippingOptions.create.fixed")}
|
||||||
description={t(
|
description={t(
|
||||||
"shipping.shippingOptions.create.fixedDescription"
|
"location.shippingOptions.create.fixedDescription"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<RadioGroup.ChoiceBox
|
<RadioGroup.ChoiceBox
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
value={ShippingAllocation.Calculated}
|
value={ShippingAllocation.Calculated}
|
||||||
label={t(
|
label={t(
|
||||||
"shipping.shippingOptions.create.calculated"
|
"location.shippingOptions.create.calculated"
|
||||||
)}
|
)}
|
||||||
description={t(
|
description={t(
|
||||||
"shipping.shippingOptions.create.calculatedDescription"
|
"location.shippingOptions.create.calculatedDescription"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
@@ -173,7 +173,7 @@ export const EditShippingOptionForm = ({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.create.profile")}
|
{t("location.shippingOptions.create.profile")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Select {...field} onValueChange={onChange}>
|
<Select {...field} onValueChange={onChange}>
|
||||||
@@ -203,7 +203,7 @@ export const EditShippingOptionForm = ({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.edit.provider")}
|
{t("location.shippingOptions.edit.provider")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Select {...field} onValueChange={onChange}>
|
<Select {...field} onValueChange={onChange}>
|
||||||
@@ -236,7 +236,7 @@ export const EditShippingOptionForm = ({
|
|||||||
<Form.Item>
|
<Form.Item>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.create.enable")}
|
{t("location.shippingOptions.create.enable")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Switch
|
<Switch
|
||||||
File renamed without changes.
File renamed without changes.
+2
-2
@@ -3,8 +3,8 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { json, useParams, useSearchParams } from "react-router-dom"
|
import { json, useParams, useSearchParams } from "react-router-dom"
|
||||||
|
|
||||||
import { RouteDrawer } from "../../../components/route-modal"
|
import { RouteDrawer } from "../../../components/route-modal"
|
||||||
import { EditShippingOptionForm } from "./components/edit-region-form"
|
|
||||||
import { useShippingOptions } from "../../../hooks/api/shipping-options"
|
import { useShippingOptions } from "../../../hooks/api/shipping-options"
|
||||||
|
import { EditShippingOptionForm } from "./components/edit-region-form"
|
||||||
|
|
||||||
export const ShippingOptionEdit = () => {
|
export const ShippingOptionEdit = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@@ -31,7 +31,7 @@ export const ShippingOptionEdit = () => {
|
|||||||
return (
|
return (
|
||||||
<RouteDrawer>
|
<RouteDrawer>
|
||||||
<RouteDrawer.Header>
|
<RouteDrawer.Header>
|
||||||
<Heading>{t("shipping.shippingOptions.edit.title")}</Heading>
|
<Heading>{t("location.shippingOptions.edit.title")}</Heading>
|
||||||
</RouteDrawer.Header>
|
</RouteDrawer.Header>
|
||||||
{!isPending && shippingOption && (
|
{!isPending && shippingOption && (
|
||||||
<EditShippingOptionForm
|
<EditShippingOptionForm
|
||||||
+22
-22
@@ -1,8 +1,9 @@
|
|||||||
import { useForm } from "react-hook-form"
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import React, { useEffect } from "react"
|
import React, { useEffect } from "react"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
|
import { ServiceZoneDTO } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Heading,
|
Heading,
|
||||||
@@ -10,26 +11,25 @@ import {
|
|||||||
ProgressStatus,
|
ProgressStatus,
|
||||||
ProgressTabs,
|
ProgressTabs,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
|
Select,
|
||||||
Switch,
|
Switch,
|
||||||
Text,
|
Text,
|
||||||
clx,
|
clx,
|
||||||
Select,
|
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
import { ServiceZoneDTO } from "@medusajs/types"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
|
import { Form } from "../../../../../components/common/form"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
useRouteModal,
|
useRouteModal,
|
||||||
} from "../../../../../components/route-modal"
|
} from "../../../../../components/route-modal"
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers"
|
||||||
import { CreateShippingOptionsPricesForm } from "./create-shipping-options-prices-form"
|
import { useRegions } from "../../../../../hooks/api/regions"
|
||||||
import { useCreateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
import { useCreateShippingOptions } from "../../../../../hooks/api/shipping-options"
|
||||||
import { useShippingProfiles } from "../../../../../hooks/api/shipping-profiles"
|
import { useShippingProfiles } from "../../../../../hooks/api/shipping-profiles"
|
||||||
import { getDbAmount } from "../../../../../lib/money-amount-helpers"
|
|
||||||
import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers"
|
|
||||||
import { formatProvider } from "../../../../../lib/format-provider"
|
import { formatProvider } from "../../../../../lib/format-provider"
|
||||||
import { useRegions } from "../../../../../hooks/api/regions"
|
import { getDbAmount } from "../../../../../lib/money-amount-helpers"
|
||||||
|
import { CreateShippingOptionsPricesForm } from "./create-shipping-options-prices-form"
|
||||||
|
|
||||||
enum Tab {
|
enum Tab {
|
||||||
DETAILS = "details",
|
DETAILS = "details",
|
||||||
@@ -230,7 +230,7 @@ export function CreateShippingOptionsForm({
|
|||||||
className="w-full max-w-[200px]"
|
className="w-full max-w-[200px]"
|
||||||
>
|
>
|
||||||
<span className="w-full cursor-auto overflow-hidden text-ellipsis whitespace-nowrap">
|
<span className="w-full cursor-auto overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
{t("shipping.shippingOptions.create.details")}
|
{t("location.shippingOptions.create.details")}
|
||||||
</span>
|
</span>
|
||||||
</ProgressTabs.Trigger>
|
</ProgressTabs.Trigger>
|
||||||
{!isCalculatedPriceType && (
|
{!isCalculatedPriceType && (
|
||||||
@@ -241,7 +241,7 @@ export function CreateShippingOptionsForm({
|
|||||||
disabled={!canMoveToPricing}
|
disabled={!canMoveToPricing}
|
||||||
>
|
>
|
||||||
<span className="w-full overflow-hidden text-ellipsis whitespace-nowrap">
|
<span className="w-full overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
{t("shipping.shippingOptions.create.pricing")}
|
{t("location.shippingOptions.create.pricing")}
|
||||||
</span>
|
</span>
|
||||||
</ProgressTabs.Trigger>
|
</ProgressTabs.Trigger>
|
||||||
)}
|
)}
|
||||||
@@ -286,7 +286,7 @@ export function CreateShippingOptionsForm({
|
|||||||
<div className="container mx-auto w-[720px] px-1 py-8">
|
<div className="container mx-auto w-[720px] px-1 py-8">
|
||||||
<Heading className="mb-12 mt-8 text-2xl">
|
<Heading className="mb-12 mt-8 text-2xl">
|
||||||
{t(
|
{t(
|
||||||
`shipping.${
|
`location.${
|
||||||
isReturn ? "returnOptions" : "shippingOptions"
|
isReturn ? "returnOptions" : "shippingOptions"
|
||||||
}.create.title`,
|
}.create.title`,
|
||||||
{
|
{
|
||||||
@@ -298,10 +298,10 @@ export function CreateShippingOptionsForm({
|
|||||||
{!isReturn && (
|
{!isReturn && (
|
||||||
<div>
|
<div>
|
||||||
<Text weight="plus">
|
<Text weight="plus">
|
||||||
{t("shipping.shippingOptions.create.subtitle")}
|
{t("location.shippingOptions.create.subtitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-ui-fg-subtle mb-8 mt-2">
|
<Text className="text-ui-fg-subtle mb-8 mt-2">
|
||||||
{t("shipping.shippingOptions.create.description")}
|
{t("location.shippingOptions.create.description")}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -313,7 +313,7 @@ export function CreateShippingOptionsForm({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.create.allocation")}
|
{t("location.shippingOptions.create.allocation")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
@@ -324,19 +324,19 @@ export function CreateShippingOptionsForm({
|
|||||||
<RadioGroup.ChoiceBox
|
<RadioGroup.ChoiceBox
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
value={ShippingAllocation.FlatRate}
|
value={ShippingAllocation.FlatRate}
|
||||||
label={t("shipping.shippingOptions.create.fixed")}
|
label={t("location.shippingOptions.create.fixed")}
|
||||||
description={t(
|
description={t(
|
||||||
"shipping.shippingOptions.create.fixedDescription"
|
"location.shippingOptions.create.fixedDescription"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<RadioGroup.ChoiceBox
|
<RadioGroup.ChoiceBox
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
value={ShippingAllocation.Calculated}
|
value={ShippingAllocation.Calculated}
|
||||||
label={t(
|
label={t(
|
||||||
"shipping.shippingOptions.create.calculated"
|
"location.shippingOptions.create.calculated"
|
||||||
)}
|
)}
|
||||||
description={t(
|
description={t(
|
||||||
"shipping.shippingOptions.create.calculatedDescription"
|
"location.shippingOptions.create.calculatedDescription"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
@@ -374,7 +374,7 @@ export function CreateShippingOptionsForm({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.create.profile")}
|
{t("location.shippingOptions.create.profile")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Select {...field} onValueChange={onChange}>
|
<Select {...field} onValueChange={onChange}>
|
||||||
@@ -405,7 +405,7 @@ export function CreateShippingOptionsForm({
|
|||||||
return (
|
return (
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.edit.provider")}
|
{t("location.shippingOptions.edit.provider")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Select {...field} onValueChange={onChange}>
|
<Select {...field} onValueChange={onChange}>
|
||||||
@@ -437,7 +437,7 @@ export function CreateShippingOptionsForm({
|
|||||||
<Form.Item>
|
<Form.Item>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
{t("shipping.shippingOptions.create.enable")}
|
{t("location.shippingOptions.create.enable")}
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<Switch
|
<Switch
|
||||||
@@ -449,7 +449,7 @@ export function CreateShippingOptionsForm({
|
|||||||
</div>
|
</div>
|
||||||
<Form.Hint className="!mt-1">
|
<Form.Hint className="!mt-1">
|
||||||
{t(
|
{t(
|
||||||
"shipping.shippingOptions.create.enableDescription"
|
"location.shippingOptions.create.enableDescription"
|
||||||
)}
|
)}
|
||||||
</Form.Hint>
|
</Form.Hint>
|
||||||
<Form.ErrorMessage />
|
<Form.ErrorMessage />
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+4
-4
@@ -11,8 +11,8 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
StatusBadge,
|
StatusBadge,
|
||||||
Text,
|
Text,
|
||||||
toast,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
toast,
|
||||||
usePrompt,
|
usePrompt,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
import { format } from "date-fns"
|
import { format } from "date-fns"
|
||||||
@@ -21,10 +21,10 @@ import { Link } from "react-router-dom"
|
|||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { Skeleton } from "../../../../../components/common/skeleton"
|
import { Skeleton } from "../../../../../components/common/skeleton"
|
||||||
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
||||||
|
import { useCancelFulfillment } from "../../../../../hooks/api/fulfillment"
|
||||||
|
import { useStockLocation } from "../../../../../hooks/api/stock-locations"
|
||||||
import { formatProvider } from "../../../../../lib/format-provider"
|
import { formatProvider } from "../../../../../lib/format-provider"
|
||||||
import { getLocaleAmount } from "../../../../../lib/money-amount-helpers"
|
import { getLocaleAmount } from "../../../../../lib/money-amount-helpers"
|
||||||
import { useStockLocation } from "../../../../../hooks/api/stock-locations"
|
|
||||||
import { useCancelFulfillment } from "../../../../../hooks/api/fulfillment"
|
|
||||||
|
|
||||||
type OrderFulfillmentSectionProps = {
|
type OrderFulfillmentSectionProps = {
|
||||||
order: OrderDTO & { fulfillments: FulfillmentDTO[] }
|
order: OrderDTO & { fulfillments: FulfillmentDTO[] }
|
||||||
@@ -285,7 +285,7 @@ const Fulfillment = ({
|
|||||||
</Text>
|
</Text>
|
||||||
{stock_location ? (
|
{stock_location ? (
|
||||||
<Link
|
<Link
|
||||||
to={`/settings/shipping/${stock_location.id}`}
|
to={`/settings/locations/${stock_location.id}`}
|
||||||
className="text-ui-fg-interactive hover:text-ui-fg-interactive-hover transition-fg"
|
className="text-ui-fg-interactive hover:text-ui-fg-interactive-hover transition-fg"
|
||||||
>
|
>
|
||||||
<Text size="small" leading="compact">
|
<Text size="small" leading="compact">
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import { RegionCountrySection } from "./components/region-country-section"
|
|||||||
import { RegionGeneralSection } from "./components/region-general-section"
|
import { RegionGeneralSection } from "./components/region-general-section"
|
||||||
import { regionLoader } from "./loader"
|
import { regionLoader } from "./loader"
|
||||||
|
|
||||||
|
import after from "virtual:medusa/widgets/region/details/after"
|
||||||
|
import before from "virtual:medusa/widgets/region/details/before"
|
||||||
|
|
||||||
export const RegionDetail = () => {
|
export const RegionDetail = () => {
|
||||||
const initialData = useLoaderData() as Awaited<
|
const initialData = useLoaderData() as Awaited<
|
||||||
ReturnType<typeof regionLoader>
|
ReturnType<typeof regionLoader>
|
||||||
@@ -36,8 +39,22 @@ export const RegionDetail = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-y-2">
|
||||||
|
{before.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={region} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<RegionGeneralSection region={region} />
|
<RegionGeneralSection region={region} />
|
||||||
<RegionCountrySection region={region} />
|
<RegionCountrySection region={region} />
|
||||||
|
{after.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={region} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<JsonViewSection data={region} />
|
<JsonViewSection data={region} />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,28 @@
|
|||||||
import { Outlet } from "react-router-dom"
|
import { Outlet } from "react-router-dom"
|
||||||
|
|
||||||
import { RegionListTable } from "./components/region-list-table"
|
import { RegionListTable } from "./components/region-list-table"
|
||||||
|
|
||||||
|
import after from "virtual:medusa/widgets/region/list/after"
|
||||||
|
import before from "virtual:medusa/widgets/region/list/before"
|
||||||
|
|
||||||
export const RegionList = () => {
|
export const RegionList = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-y-2">
|
||||||
|
{before.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<RegionListTable />
|
<RegionListTable />
|
||||||
|
{after.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
+18
@@ -1,4 +1,5 @@
|
|||||||
import { useParams } from "react-router-dom"
|
import { useParams } from "react-router-dom"
|
||||||
|
|
||||||
import { JsonViewSection } from "../../../components/common/json-view-section"
|
import { JsonViewSection } from "../../../components/common/json-view-section"
|
||||||
import {
|
import {
|
||||||
GeneralSectionSkeleton,
|
GeneralSectionSkeleton,
|
||||||
@@ -7,6 +8,9 @@ import {
|
|||||||
import { useShippingProfile } from "../../../hooks/api/shipping-profiles"
|
import { useShippingProfile } from "../../../hooks/api/shipping-profiles"
|
||||||
import { ShippingProfileGeneralSection } from "./components/shipping-profile-general-section"
|
import { ShippingProfileGeneralSection } from "./components/shipping-profile-general-section"
|
||||||
|
|
||||||
|
import after from "virtual:medusa/widgets/shipping_profile/details/after"
|
||||||
|
import before from "virtual:medusa/widgets/shipping_profile/details/before"
|
||||||
|
|
||||||
export const ShippingProfileDetail = () => {
|
export const ShippingProfileDetail = () => {
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
|
|
||||||
@@ -29,7 +33,21 @@ export const ShippingProfileDetail = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-y-2">
|
||||||
|
{before.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={shipping_profile} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<ShippingProfileGeneralSection profile={shipping_profile} />
|
<ShippingProfileGeneralSection profile={shipping_profile} />
|
||||||
|
{after.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component data={shipping_profile} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<JsonViewSection data={shipping_profile} />
|
<JsonViewSection data={shipping_profile} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
+18
@@ -1,10 +1,28 @@
|
|||||||
import { Outlet } from "react-router-dom"
|
import { Outlet } from "react-router-dom"
|
||||||
|
|
||||||
import { ShippingProfileListTable } from "./components/shipping-profile-list-table"
|
import { ShippingProfileListTable } from "./components/shipping-profile-list-table"
|
||||||
|
|
||||||
|
import after from "virtual:medusa/widgets/shipping_profile/list/after"
|
||||||
|
import before from "virtual:medusa/widgets/shipping_profile/list/before"
|
||||||
|
|
||||||
export const ShippingProfileList = () => {
|
export const ShippingProfileList = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-y-2">
|
||||||
|
{before.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<ShippingProfileListTable />
|
<ShippingProfileListTable />
|
||||||
|
{after.widgets.map((w, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
|
<w.Component />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
-55
@@ -1,55 +0,0 @@
|
|||||||
import { Outlet, useLoaderData, useParams } from "react-router-dom"
|
|
||||||
|
|
||||||
import { JsonViewSection } from "../../../components/common/json-view-section"
|
|
||||||
import { LocationGeneralSection } from "./components/location-general-section"
|
|
||||||
import { useStockLocation } from "../../../hooks/api/stock-locations"
|
|
||||||
import LocationsSalesChannelsSection from "./components/location-sales-channels-section/locations-sales-channels-section"
|
|
||||||
import { locationLoader } from "./loader"
|
|
||||||
|
|
||||||
export const LocationDetails = () => {
|
|
||||||
const initialData = useLoaderData() as Awaited<
|
|
||||||
ReturnType<typeof locationLoader>
|
|
||||||
>
|
|
||||||
|
|
||||||
const { location_id } = useParams()
|
|
||||||
const {
|
|
||||||
stock_location: location,
|
|
||||||
isPending: isLoading,
|
|
||||||
isError,
|
|
||||||
error,
|
|
||||||
} = useStockLocation(
|
|
||||||
location_id!,
|
|
||||||
{
|
|
||||||
fields:
|
|
||||||
"name,*sales_channels,address.city,address.country_code,fulfillment_sets.type,fulfillment_sets.name,*fulfillment_sets.service_zones.geo_zones,*fulfillment_sets.service_zones,*fulfillment_sets.service_zones.shipping_options,*fulfillment_sets.service_zones.shipping_options.rules,*fulfillment_sets.service_zones.shipping_options.shipping_profile",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
initialData,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Move to loading.tsx and set as Suspense fallback for the route
|
|
||||||
if (isLoading || !location) {
|
|
||||||
return <div>Loading...</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isError) {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
|
|
||||||
<div className="flex w-full flex-col gap-y-2">
|
|
||||||
<LocationGeneralSection location={location} />
|
|
||||||
<div className="flex w-full flex-col gap-y-2 xl:hidden">
|
|
||||||
<LocationsSalesChannelsSection location={location} />
|
|
||||||
</div>
|
|
||||||
<JsonViewSection data={location} />
|
|
||||||
</div>
|
|
||||||
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
|
||||||
<LocationsSalesChannelsSection location={location} />
|
|
||||||
</div>
|
|
||||||
<Outlet />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import { Button, Container, Heading, Text } from "@medusajs/ui"
|
|
||||||
import { useTranslation } from "react-i18next"
|
|
||||||
import { Link, Outlet, useLoaderData } from "react-router-dom"
|
|
||||||
|
|
||||||
import { shippingListLoader } from "./loader"
|
|
||||||
import { useStockLocations } from "../../../hooks/api/stock-locations"
|
|
||||||
import Location from "./components/location/location"
|
|
||||||
import { locationListFields } from "./const"
|
|
||||||
|
|
||||||
export function LocationList() {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
const initialData = useLoaderData() as Awaited<
|
|
||||||
ReturnType<typeof shippingListLoader>
|
|
||||||
>
|
|
||||||
|
|
||||||
let { stock_locations: stockLocations = [], isPending } = useStockLocations(
|
|
||||||
{
|
|
||||||
fields: locationListFields,
|
|
||||||
},
|
|
||||||
{ initialData }
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="py-4">
|
|
||||||
<Container className="mb-4 flex h-fit items-center justify-between p-8">
|
|
||||||
<div>
|
|
||||||
<Heading className="mb-2">{t("shipping.title")}</Heading>
|
|
||||||
<Text className="text-ui-fg-subtle txt-small">
|
|
||||||
{t("shipping.description")}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<Button size="small" variant="secondary" asChild>
|
|
||||||
<Link to="create">{t("shipping.createLocation")}</Link>
|
|
||||||
</Button>
|
|
||||||
</Container>
|
|
||||||
<div className="flex flex-col gap-4 lg:col-span-2">
|
|
||||||
{stockLocations.map((location) => (
|
|
||||||
<Location key={location.id} location={location} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Outlet />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user