feat(dashboard): Price List configurations section (#6663)

**What**
- Adds section for displaying price list configurations.

Closes CORE-1857
This commit is contained in:
Kasper Fabricius Kristensen authored and GitHub committed 2024-03-25 11:07:47 +00:00
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": {
@@ -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 />
@@ -0,0 +1 @@
export * from "./pricing-configuration-section"
@@ -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,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}>