feat(dashboard): Price List configurations section (#6663)
**What** - Adds section for displaying price list configurations. Closes CORE-1857
This commit is contained in:
1 parent
6af8f9be6d
commit
1b2e0b4031
8 files changed
+117
-54
No files matched your search
@@ -848,6 +848,8 @@
|
|||||||
"label": "Label",
|
"label": "Label",
|
||||||
"rate": "Rate",
|
"rate": "Rate",
|
||||||
"requiresShipping": "Requires shipping",
|
"requiresShipping": "Requires shipping",
|
||||||
|
"startDate": "Start date",
|
||||||
|
"endDate": "End date",
|
||||||
"draft": "Draft"
|
"draft": "Draft"
|
||||||
},
|
},
|
||||||
"dateTime": {
|
"dateTime": {
|
||||||
|
|||||||
+4
-4
@@ -40,12 +40,12 @@ export const DiscountDetail = () => {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<div className="grid grid-cols-1 gap-x-4 lg:grid-cols-[1fr,400px]">
|
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex w-full flex-col gap-y-2">
|
||||||
<DiscountGeneralSection discount={discount} />
|
<DiscountGeneralSection discount={discount} />
|
||||||
<DiscountConfigurationSection discount={discount} />
|
<DiscountConfigurationSection discount={discount} />
|
||||||
<DiscountConditionsSection discount={discount} />
|
<DiscountConditionsSection discount={discount} />
|
||||||
<div className="flex flex-col gap-y-2 lg:hidden">
|
<div className="flex w-full flex-col gap-y-2 xl:hidden">
|
||||||
<RedemptionsSection redemptions={discount.usage_count} />
|
<RedemptionsSection redemptions={discount.usage_count} />
|
||||||
<DetailsSection discount={discount} />
|
<DetailsSection discount={discount} />
|
||||||
</div>
|
</div>
|
||||||
@@ -58,7 +58,7 @@ export const DiscountDetail = () => {
|
|||||||
})}
|
})}
|
||||||
<JsonViewSection data={discount} />
|
<JsonViewSection data={discount} />
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden flex-col gap-y-2 lg:flex">
|
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
||||||
<RedemptionsSection redemptions={discount.usage_count} />
|
<RedemptionsSection redemptions={discount.usage_count} />
|
||||||
<DetailsSection discount={discount} />
|
<DetailsSection discount={discount} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,18 +33,18 @@ export const OrderDetail = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 gap-x-4 xl:grid-cols-[1fr,400px]">
|
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex w-full flex-col gap-y-2">
|
||||||
<OrderGeneralSection order={order} />
|
<OrderGeneralSection order={order} />
|
||||||
<OrderSummarySection order={order} />
|
<OrderSummarySection order={order} />
|
||||||
<OrderPaymentSection order={order} />
|
<OrderPaymentSection order={order} />
|
||||||
<OrderFulfillmentSection order={order} />
|
<OrderFulfillmentSection order={order} />
|
||||||
<div className="flex flex-col gap-y-2 lg:hidden">
|
<div className="flex flex-col gap-y-2 xl:hidden">
|
||||||
<OrderCustomerSection order={order} />
|
<OrderCustomerSection order={order} />
|
||||||
</div>
|
</div>
|
||||||
<JsonViewSection data={order} />
|
<JsonViewSection data={order} />
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden flex-col gap-y-2 lg:flex">
|
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
||||||
<OrderCustomerSection order={order} />
|
<OrderCustomerSection order={order} />
|
||||||
</div>
|
</div>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
export * from "./pricing-configuration-section"
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
import { PencilSquare } from "@medusajs/icons"
|
||||||
|
import { PriceList } from "@medusajs/medusa"
|
||||||
|
import { Container, Heading, Text, Tooltip } from "@medusajs/ui"
|
||||||
|
import { format } from "date-fns"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
|
|
||||||
|
type PricingConfigurationSectionProps = {
|
||||||
|
priceList: PriceList
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PricingConfigurationSection = ({
|
||||||
|
priceList,
|
||||||
|
}: PricingConfigurationSectionProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const firstCustomerGroups = priceList.customer_groups?.slice(0, 3)
|
||||||
|
const remainingCustomerGroups = priceList.customer_groups?.slice(3)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container className="divide-y p-0">
|
||||||
|
<div className="flex items-center justify-between px-6 py-4">
|
||||||
|
<Heading level="h2">{t("fields.configurations")}</Heading>
|
||||||
|
<ActionMenu
|
||||||
|
groups={[
|
||||||
|
{
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: t("actions.edit"),
|
||||||
|
to: "configurations/edit",
|
||||||
|
icon: <PencilSquare />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-ui-fg-subtle grid grid-cols-2 items-center px-6 py-4">
|
||||||
|
<Text leading="compact" size="small" weight="plus">
|
||||||
|
{t("fields.startDate")}
|
||||||
|
</Text>
|
||||||
|
<Text size="small" className="text-pretty">
|
||||||
|
{priceList.starts_at
|
||||||
|
? format(new Date(priceList.starts_at), "dd MMM yyyy")
|
||||||
|
: "-"}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="text-ui-fg-subtle grid grid-cols-2 items-center px-6 py-4">
|
||||||
|
<Text leading="compact" size="small" weight="plus">
|
||||||
|
{t("fields.endDate")}
|
||||||
|
</Text>
|
||||||
|
<Text size="small" className="text-pretty">
|
||||||
|
{priceList.ends_at
|
||||||
|
? format(new Date(priceList.ends_at), "dd MMM yyyy")
|
||||||
|
: "-"}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="text-ui-fg-subtle grid grid-cols-2 items-center px-6 py-4">
|
||||||
|
<Text leading="compact" size="small" weight="plus">
|
||||||
|
{t("pricing.settings.customerGroupsLabel")}
|
||||||
|
</Text>
|
||||||
|
<Text size="small" className="text-pretty">
|
||||||
|
<span>
|
||||||
|
{firstCustomerGroups.length > 0
|
||||||
|
? firstCustomerGroups.join(", ")
|
||||||
|
: "-"}
|
||||||
|
</span>
|
||||||
|
{remainingCustomerGroups.length > 0 && (
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
<ul>
|
||||||
|
{remainingCustomerGroups.map((cg) => (
|
||||||
|
<li key={cg.id}>{cg.name}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className="text-ui-fg-muted">
|
||||||
|
{" "}
|
||||||
|
{t("general.plusCountMore", {
|
||||||
|
count: remainingCustomerGroups.length,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
+1
-40
@@ -1,13 +1,6 @@
|
|||||||
import { PencilSquare, Trash } from "@medusajs/icons"
|
import { PencilSquare, Trash } from "@medusajs/icons"
|
||||||
import { PriceList } from "@medusajs/medusa"
|
import { PriceList } from "@medusajs/medusa"
|
||||||
import {
|
import { Container, Heading, StatusBadge, Text, usePrompt } from "@medusajs/ui"
|
||||||
Container,
|
|
||||||
Heading,
|
|
||||||
StatusBadge,
|
|
||||||
Text,
|
|
||||||
Tooltip,
|
|
||||||
usePrompt,
|
|
||||||
} from "@medusajs/ui"
|
|
||||||
import { useAdminDeletePriceList } from "medusa-react"
|
import { useAdminDeletePriceList } from "medusa-react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { useNavigate } from "react-router-dom"
|
import { useNavigate } from "react-router-dom"
|
||||||
@@ -28,8 +21,6 @@ export const PricingGeneralSection = ({
|
|||||||
const { mutateAsync } = useAdminDeletePriceList(priceList.id)
|
const { mutateAsync } = useAdminDeletePriceList(priceList.id)
|
||||||
|
|
||||||
const overrideCount = priceList.prices?.length || 0
|
const overrideCount = priceList.prices?.length || 0
|
||||||
const firstCustomerGroups = priceList.customer_groups?.slice(0, 3)
|
|
||||||
const remainingCustomerGroups = priceList.customer_groups?.slice(3)
|
|
||||||
|
|
||||||
const { color, text } = getPriceListStatus(t, priceList)
|
const { color, text } = getPriceListStatus(t, priceList)
|
||||||
|
|
||||||
@@ -105,36 +96,6 @@ export const PricingGeneralSection = ({
|
|||||||
{priceList.description}
|
{priceList.description}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-ui-fg-subtle grid grid-cols-2 items-center px-6 py-4">
|
|
||||||
<Text leading="compact" size="small" weight="plus">
|
|
||||||
{t("pricing.settings.customerGroupsLabel")}
|
|
||||||
</Text>
|
|
||||||
<Text size="small" className="text-pretty">
|
|
||||||
<span>
|
|
||||||
{firstCustomerGroups.length > 0
|
|
||||||
? firstCustomerGroups.join(", ")
|
|
||||||
: "-"}
|
|
||||||
</span>
|
|
||||||
{remainingCustomerGroups.length > 0 && (
|
|
||||||
<Tooltip
|
|
||||||
content={
|
|
||||||
<ul>
|
|
||||||
{remainingCustomerGroups.map((cg) => (
|
|
||||||
<li key={cg.id}>{cg.name}</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span className="text-ui-fg-muted">
|
|
||||||
{" "}
|
|
||||||
{t("general.plusCountMore", {
|
|
||||||
count: remainingCustomerGroups.length,
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<div className="text-ui-fg-subtle grid grid-cols-2 items-center px-6 py-4">
|
<div className="text-ui-fg-subtle grid grid-cols-2 items-center px-6 py-4">
|
||||||
<Text leading="compact" size="small" weight="plus">
|
<Text leading="compact" size="small" weight="plus">
|
||||||
{t("pricing.settings.priceOverridesLabel")}
|
{t("pricing.settings.priceOverridesLabel")}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useAdminPriceList } from "medusa-react"
|
import { useAdminPriceList } from "medusa-react"
|
||||||
import { Outlet, useParams } from "react-router-dom"
|
import { Outlet, useParams } from "react-router-dom"
|
||||||
import { JsonViewSection } from "../../../components/common/json-view-section"
|
import { JsonViewSection } from "../../../components/common/json-view-section"
|
||||||
|
import { PricingConfigurationSection } from "./components/pricing-configuration-section"
|
||||||
import { PricingGeneralSection } from "./components/pricing-general-section"
|
import { PricingGeneralSection } from "./components/pricing-general-section"
|
||||||
import { PricingProductSection } from "./components/pricing-product-section"
|
import { PricingProductSection } from "./components/pricing-product-section"
|
||||||
|
|
||||||
@@ -18,10 +19,18 @@ export const PricingDetail = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
|
||||||
<PricingGeneralSection priceList={price_list} />
|
<div className="flex w-full flex-col gap-y-2">
|
||||||
<PricingProductSection priceList={price_list} />
|
<PricingGeneralSection priceList={price_list} />
|
||||||
<JsonViewSection data={price_list} />
|
<PricingProductSection priceList={price_list} />
|
||||||
|
<div className="flex w-full flex-col gap-y-2 xl:hidden">
|
||||||
|
<PricingConfigurationSection priceList={price_list} />
|
||||||
|
</div>
|
||||||
|
<JsonViewSection data={price_list} />
|
||||||
|
</div>
|
||||||
|
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
||||||
|
<PricingConfigurationSection priceList={price_list} />
|
||||||
|
</div>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const ProductDetail = () => {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<div className="grid grid-cols-1 gap-x-4 xl:grid-cols-[1fr,400px]">
|
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
|
||||||
<div className="flex flex-col gap-y-2">
|
<div className="flex flex-col gap-y-2">
|
||||||
<ProductGeneralSection product={product} />
|
<ProductGeneralSection product={product} />
|
||||||
<ProductMediaSection product={product} />
|
<ProductMediaSection product={product} />
|
||||||
@@ -81,7 +81,7 @@ export const ProductDetail = () => {
|
|||||||
})}
|
})}
|
||||||
<JsonViewSection data={product} root="product" />
|
<JsonViewSection data={product} root="product" />
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden flex-col gap-y-2 xl:flex">
|
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
||||||
{sideBefore.widgets.map((w, i) => {
|
{sideBefore.widgets.map((w, i) => {
|
||||||
return (
|
return (
|
||||||
<div key={i}>
|
<div key={i}>
|
||||||
|
|||||||
Reference in new issue
Block a user