feat(promotion,dashboard,types,utils,medusa): Add statuses to promotions (#10950)

what:

- adds a status column to promotion table
- introduce active promotion query
- scope revert, register and compute actions to active promotions
- admin to create and update promotion with statuses

RESOLVES CMRC-845
RESOLVES CMRC-846
RESOLVES CMRC-847
RESOLVES CMRC-848
RESOLVES CMRC-849
RESOLVES CMRC-850
This commit is contained in:
Riqwan Thamir
2025-01-16 19:17:22 +00:00
committed by GitHub
parent effee5c8bb
commit 5eab9e7399
35 changed files with 1208 additions and 1743 deletions
@@ -1,4 +1,12 @@
import { zodResolver } from "@hookform/resolvers/zod"
import {
ApplicationMethodAllocationValues,
ApplicationMethodTargetTypeValues,
ApplicationMethodTypeValues,
PromotionRuleOperatorValues,
PromotionStatusValues,
PromotionTypeValues,
} from "@medusajs/types"
import {
Alert,
Badge,
@@ -17,14 +25,6 @@ import { useEffect, useMemo, useState } from "react"
import { useForm, useWatch } from "react-hook-form"
import { Trans, useTranslation } from "react-i18next"
import { z } from "zod"
import {
ApplicationMethodAllocationValues,
ApplicationMethodTargetTypeValues,
ApplicationMethodTypeValues,
PromotionRuleOperatorValues,
PromotionTypeValues,
} from "@medusajs/types"
import { Divider } from "../../../../../components/common/divider"
import { Form } from "../../../../../components/common/form"
import { DeprecatedPercentageInput } from "../../../../../components/inputs/percentage-input"
@@ -50,6 +50,7 @@ const defaultValues = {
is_automatic: "false",
code: "",
type: "standard" as PromotionTypeValues,
status: "draft" as PromotionStatusValues,
rules: [],
application_method: {
allocation: "each" as ApplicationMethodAllocationValues,
@@ -508,6 +509,48 @@ export const CreatePromotionForm = () => {
}}
/>
<Form.Field
control={form.control}
name="status"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t("promotions.form.status.label")}
</Form.Label>
<Form.Control>
<RadioGroup
className="flex gap-y-3"
{...field}
value={field.value}
onValueChange={field.onChange}
>
<RadioGroup.ChoiceBox
value={"draft"}
label={t("promotions.form.status.draft.title")}
description={t(
"promotions.form.status.draft.description"
)}
className={clx("basis-1/2")}
/>
<RadioGroup.ChoiceBox
value={"active"}
label={t("promotions.form.status.active.title")}
description={t(
"promotions.form.status.active.description"
)}
className={clx("basis-1/2")}
/>
</RadioGroup>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
<div className="flex gap-y-4">
<Form.Field
control={form.control}
@@ -25,6 +25,7 @@ export const CreatePromotionSchema = z
is_automatic: z.string().toLowerCase(),
code: z.string().min(1),
type: z.enum(["buyget", "standard"]),
status: z.enum(["draft", "active", "inactive"]),
rules: RuleSchema,
application_method: z.object({
allocation: z.enum(["each", "across"]),
@@ -16,10 +16,7 @@ import { ActionMenu } from "../../../../../components/common/action-menu"
import { useDeletePromotion } from "../../../../../hooks/api/promotions"
import { formatCurrency } from "../../../../../lib/format-currency"
import { formatPercentage } from "../../../../../lib/percentage-helpers"
import {
getPromotionStatus,
PromotionStatus,
} from "../../../../../lib/promotions"
import { getPromotionStatus } from "../../../../../lib/promotions"
type PromotionGeneralSectionProps = {
promotion: HttpTypes.AdminPromotion
@@ -78,16 +75,7 @@ export const PromotionGeneralSection = ({
})
}
const [color, text] = {
[PromotionStatus.DISABLED]: ["grey", t("statuses.disabled")],
[PromotionStatus.ACTIVE]: ["green", t("statuses.active")],
[PromotionStatus.SCHEDULED]: ["orange", t("statuses.scheduled")],
[PromotionStatus.EXPIRED]: ["red", t("statuses.expired")],
}[getPromotionStatus(promotion)] as [
"grey" | "orange" | "green" | "red",
string
]
const [color, text] = getPromotionStatus(promotion)
const displayValue = getDisplayValue(promotion)
return (
@@ -1,5 +1,5 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { PromotionDTO } from "@medusajs/types"
import { AdminPromotion } from "@medusajs/types"
import { Button, CurrencyInput, Input, RadioGroup, Text } from "@medusajs/ui"
import { useForm, useWatch } from "react-hook-form"
import { Trans, useTranslation } from "react-i18next"
@@ -13,12 +13,13 @@ import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
type EditPromotionFormProps = {
promotion: PromotionDTO
promotion: AdminPromotion
}
const EditPromotionSchema = zod.object({
is_automatic: zod.string().toLowerCase(),
code: zod.string().min(1),
status: zod.enum(["active", "inactive", "draft"]),
value_type: zod.enum(["fixed", "percentage"]),
value: zod.number(),
allocation: zod.enum(["each", "across"]),
@@ -34,6 +35,7 @@ export const EditPromotionDetailsForm = ({
defaultValues: {
is_automatic: promotion.is_automatic!.toString(),
code: promotion.code,
status: promotion.status,
value: promotion.application_method!.value,
allocation: promotion.application_method!.allocation,
value_type: promotion.application_method!.type,
@@ -55,6 +57,7 @@ export const EditPromotionDetailsForm = ({
{
is_automatic: data.is_automatic === "true",
code: data.code,
status: data.status,
application_method: {
value: data.value,
type: data.value_type as any,
@@ -77,6 +80,51 @@ export const EditPromotionDetailsForm = ({
>
<RouteDrawer.Body className="flex flex-1 flex-col gap-y-8 overflow-y-auto">
<div className="flex flex-col gap-y-8">
<Form.Field
control={form.control}
name="status"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>{t("promotions.form.status.label")}</Form.Label>
<Form.Control>
<RadioGroup
className="flex-col gap-y-3"
{...field}
value={field.value}
onValueChange={field.onChange}
>
<RadioGroup.ChoiceBox
value={"draft"}
label={t("promotions.form.status.draft.title")}
description={t(
"promotions.form.status.draft.description"
)}
/>
<RadioGroup.ChoiceBox
value={"active"}
label={t("promotions.form.status.active.title")}
description={t(
"promotions.form.status.active.description"
)}
/>
<RadioGroup.ChoiceBox
value={"inactive"}
label={t("promotions.form.status.inactive.title")}
description={t(
"promotions.form.status.inactive.description"
)}
/>
</RadioGroup>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
<Form.Field
control={form.control}
name="is_automatic"