feat(dashboard): Discounts details + edits (#6547)

**What**
- Discounts details page
- Edit discount details
- Edit discount configurations
- `ListSummary` component

**NOTE**
- conditions edit form will be implemented in a separate PR
- edit details from is missing metadata component which will be added later

---


https://github.com/medusajs/medusa/assets/16856471/c878af4a-48c2-4c45-b824-662784c7a139
This commit is contained in:
Frane Polić
2024-03-06 15:08:15 +01:00
committed by GitHub
parent a5a2395622
commit fcb03d60ea
43 changed files with 1783 additions and 131 deletions
@@ -62,7 +62,7 @@ export const NoRecords = ({
<Text size="small" leading="compact" weight="plus">
{title ?? t("general.noRecordsTitle")}
</Text>
<Text size="small" className="text-ui-fg-subtle">
<Text size="small" className="text-ui-fg-muted">
{message ?? t("general.noRecordsMessage")}
</Text>
</div>
@@ -0,0 +1 @@
export { ListSummary } from "./list-summary"
@@ -0,0 +1,58 @@
import { Text, Tooltip, clx } from "@medusajs/ui"
import { useTranslation } from "react-i18next"
type ListSummaryProps = {
/**
* Number of initial items to display
* @default 2
*/
n?: number
/**
* List of strings to display as abbreviated list
*/
list: string[]
/**
* Is hte summary displayed inline.
* Determines whether the center text is truncated if there is no space in the container
*/
inline?: boolean
}
export const ListSummary = ({ list, inline, n = 2 }: ListSummaryProps) => {
const { t } = useTranslation()
return (
<div
className={clx("text-ui-fg-subtle gap-x-2", {
"inline-flex": inline,
flex: !inline,
})}
>
<Text as="span" leading="compact" size="small" className="truncate">
{list.slice(0, n).join(", ")}
</Text>
{list.length > n && (
<Tooltip
content={
<ul>
{list.slice(n).map((c) => (
<li key={c}>{c}</li>
))}
</ul>
}
>
<Text
as="span"
size="small"
weight="plus"
leading="compact"
className="cursor-default whitespace-nowrap"
>
{t("general.plusCountMore", {
count: list.length - n,
})}
</Text>
</Tooltip>
)}
</div>
)
}
@@ -1,44 +1,17 @@
import { Discount } from "@medusajs/medusa"
import { end, parse } from "iso8601-duration"
import { StatusCell as StatusCell_ } from "../../common/status-cell"
import { useTranslation } from "react-i18next"
import {
getDiscountStatus,
PromotionStatus,
} from "../../../../../lib/discounts.ts"
type DiscountCellProps = {
discount: Discount
}
enum PromotionStatus {
SCHEDULED = "SCHEDULED",
EXPIRED = "EXPIRED",
ACTIVE = "ACTIVE",
DISABLED = "DISABLED",
}
const getDiscountStatus = (discount: Discount) => {
if (discount.is_disabled) {
return PromotionStatus.DISABLED
}
const date = new Date()
if (new Date(discount.starts_at) > date) {
return PromotionStatus.SCHEDULED
}
if (
(discount.ends_at && new Date(discount.ends_at) < date) ||
(discount.valid_duration &&
date >
end(parse(discount.valid_duration), new Date(discount.starts_at))) ||
discount.usage_count === discount.usage_limit
) {
return PromotionStatus.EXPIRED
}
return PromotionStatus.ACTIVE
}
export const StatusCell = ({ discount }: DiscountCellProps) => {
const { t } = useTranslation()
@@ -29,7 +29,7 @@ export const FulfillmentStatusCell = ({
],
returned: [t("orders.fulfillment.status.returned"), "green"],
canceled: [t("orders.fulfillment.status.canceled"), "red"],
requires_action: [t("orders.fulfillment.status.requresAction"), "orange"],
requires_action: [t("orders.fulfillment.status.requiresAction"), "orange"],
}[status] as [string, "red" | "orange" | "green"]
return <StatusCell color={color}>{label}</StatusCell>
@@ -19,7 +19,7 @@ export const PaymentStatusCell = ({ status }: PaymentStatusCellProps) => {
"orange",
],
canceled: [t("orders.payment.status.canceled"), "red"],
requires_action: [t("orders.payment.status.requresAction"), "orange"],
requires_action: [t("orders.payment.status.requiresAction"), "orange"],
}[status] as [string, "red" | "orange" | "green"]
return <StatusCell color={color}>{label}</StatusCell>