feat(admin-next) discounts list page (#6490)
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
import type { Discount } from "@medusajs/medusa"
|
||||
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
type DiscountCellProps = {
|
||||
discount: Discount
|
||||
}
|
||||
|
||||
export const CodeCell = ({ discount }: DiscountCellProps) => {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center gap-x-3 overflow-hidden">
|
||||
{/*// TODO: border color inversion*/}
|
||||
<span className="bg-ui-tag-neutral-bg truncate rounded-md border border-neutral-200 p-1 text-xs">
|
||||
{discount.code}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const CodeHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className=" flex h-full w-full items-center ">
|
||||
<span>{t("fields.description")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from "./code-cell"
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import type { Discount } from "@medusajs/medusa"
|
||||
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
type DiscountCellProps = {
|
||||
discount: Discount
|
||||
}
|
||||
|
||||
export const DescriptionCell = ({ discount }: DiscountCellProps) => {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center gap-x-3 overflow-hidden">
|
||||
<span className="truncate">{discount.rule.description}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const DescriptionHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className=" flex h-full w-full items-center ">
|
||||
<span>{t("fields.description")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from "./description-cell"
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from "./redemption-cell.tsx"
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
type DiscountCellProps = {
|
||||
redemptions: number
|
||||
}
|
||||
|
||||
export const RedemptionCell = ({ redemptions }: DiscountCellProps) => {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-end gap-x-3 text-right">
|
||||
<span>{redemptions}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const RedemptionHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-end text-right">
|
||||
<span className="truncate">{t("fields.totalRedemptions")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from "./status-cell"
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
import { Discount } from "@medusajs/medusa"
|
||||
import { end, parse } from "iso8601-duration"
|
||||
|
||||
import { StatusCell as StatusCell_ } from "../../common/status-cell"
|
||||
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
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()
|
||||
|
||||
const [color, text] = {
|
||||
[PromotionStatus.DISABLED]: [
|
||||
"grey",
|
||||
t("discounts.discountStatus.disabled"),
|
||||
],
|
||||
[PromotionStatus.ACTIVE]: ["green", t("discounts.discountStatus.active")],
|
||||
[PromotionStatus.SCHEDULED]: [
|
||||
"orange",
|
||||
t("discounts.discountStatus.scheduled"),
|
||||
],
|
||||
[PromotionStatus.EXPIRED]: ["red", t("discounts.discountStatus.expired")],
|
||||
}[getDiscountStatus(discount)] as [
|
||||
"grey" | "orange" | "green" | "red",
|
||||
string
|
||||
]
|
||||
|
||||
return <StatusCell_ color={color}>{text}</StatusCell_>
|
||||
}
|
||||
|
||||
export const StatusHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className=" flex h-full w-full items-center ">
|
||||
<span>{t("fields.status")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from "./value-cell.tsx"
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { DiscountRule } from "@medusajs/medusa"
|
||||
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { MoneyAmountCell } from "../../common/money-amount-cell"
|
||||
|
||||
type DiscountCellProps = {
|
||||
rule: DiscountRule
|
||||
currencyCode: string
|
||||
}
|
||||
|
||||
export const ValueCell = ({ currencyCode, rule }: DiscountCellProps) => {
|
||||
const isFixed = rule.type === "fixed"
|
||||
const isPercentage = rule.type === "percentage"
|
||||
const isFreeShipping = rule.type === "free_shipping"
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full items-center gap-x-3 overflow-hidden">
|
||||
{isFreeShipping && <span>Free shipping</span>}
|
||||
{isPercentage && <span className="">{rule.value}%</span>}
|
||||
{isFixed && (
|
||||
<MoneyAmountCell currencyCode={currencyCode} amount={rule.value} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const ValueHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className=" flex h-full w-full items-center ">
|
||||
<span>{t("fields.value")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user