feat(dashboard,core,modules): free shipping promotion in dashboard (#13263)
* feat(dashboard,core,modules): free shipping promotion in dashboard * self-review * adapt for edit to work * changeset * integration tests * across for each * remove only from tests * remove console log * revert to across * update wording for shipping promotions * modify changeset * suggestion frane * fix i18n schema
This commit is contained in:
+7
-1
@@ -28,7 +28,13 @@ export const EditRulesForm = ({
|
||||
const [rulesToRemove, setRulesToRemove] = useState([])
|
||||
|
||||
const form = useForm<EditRulesType>({
|
||||
defaultValues: { rules: [], type: promotion.type },
|
||||
defaultValues: {
|
||||
rules: [],
|
||||
type: promotion.type,
|
||||
application_method: {
|
||||
target_type: promotion.application_method?.target_type,
|
||||
},
|
||||
},
|
||||
resolver: zodResolver(EditRules),
|
||||
})
|
||||
|
||||
|
||||
+3
@@ -24,6 +24,9 @@ export const EditRules = z.object({
|
||||
field_type: z.string().optional(),
|
||||
})
|
||||
),
|
||||
application_method: z.object({
|
||||
target_type: z.enum(["order", "shipping_methods", "items"]),
|
||||
}),
|
||||
})
|
||||
|
||||
export type EditRulesType = z.infer<typeof EditRules>
|
||||
|
||||
+10
-3
@@ -1,9 +1,13 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import {
|
||||
ApplicationMethodTargetTypeValues,
|
||||
HttpTypes,
|
||||
RuleTypeValues,
|
||||
} from "@medusajs/types"
|
||||
import { Input } from "@medusajs/ui"
|
||||
import { useWatch } from "react-hook-form"
|
||||
import { Form } from "../../../../../../components/common/form"
|
||||
import { Combobox } from "../../../../../../components/inputs/combobox"
|
||||
import { useStore } from "../../../../../../hooks/api/store"
|
||||
import { useStore } from "../../../../../../hooks/api"
|
||||
import { useComboboxData } from "../../../../../../hooks/use-combobox-data"
|
||||
import { sdk } from "../../../../../../lib/client"
|
||||
|
||||
@@ -18,7 +22,8 @@ type RuleValueFormFieldType = {
|
||||
operator: string
|
||||
fieldRule: any
|
||||
attributes: HttpTypes.AdminRuleAttributeOption[]
|
||||
ruleType: "rules" | "target-rules" | "buy-rules"
|
||||
ruleType: RuleTypeValues
|
||||
applicationMethodTargetType: ApplicationMethodTargetTypeValues | undefined
|
||||
}
|
||||
|
||||
const buildFilters = (attribute?: string, store?: HttpTypes.AdminStore) => {
|
||||
@@ -44,6 +49,7 @@ export const RuleValueFormField = ({
|
||||
fieldRule,
|
||||
attributes,
|
||||
ruleType,
|
||||
applicationMethodTargetType,
|
||||
}: RuleValueFormFieldType) => {
|
||||
const attribute = attributes?.find(
|
||||
(attr) => attr.value === fieldRule.attribute
|
||||
@@ -59,6 +65,7 @@ export const RuleValueFormField = ({
|
||||
{
|
||||
...params,
|
||||
...buildFilters(attribute?.id, store!),
|
||||
application_method_target_type: applicationMethodTargetType,
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
+23
-3
@@ -41,7 +41,11 @@ export const RulesFormField = ({
|
||||
}: RulesFormFieldType) => {
|
||||
const { t } = useTranslation()
|
||||
const formData = form.getValues()
|
||||
const { attributes } = usePromotionRuleAttributes(ruleType, formData.type)
|
||||
const { attributes } = usePromotionRuleAttributes(
|
||||
ruleType,
|
||||
formData.type,
|
||||
formData.application_method?.target_type
|
||||
)
|
||||
|
||||
const { fields, append, remove, update, replace } = useFieldArray({
|
||||
control: form.control,
|
||||
@@ -61,10 +65,17 @@ export const RulesFormField = ({
|
||||
defaultValue: promotion?.application_method?.type,
|
||||
})
|
||||
|
||||
const applicationMethodTargetType = useWatch({
|
||||
control: form.control,
|
||||
name: "application_method.target_type",
|
||||
defaultValue: promotion?.application_method?.target_type,
|
||||
})
|
||||
|
||||
const query: Record<string, string> = promotionType
|
||||
? {
|
||||
promotion_type: promotionType,
|
||||
application_method_type: applicationMethodType,
|
||||
application_method_target_type: applicationMethodTargetType,
|
||||
}
|
||||
: {}
|
||||
|
||||
@@ -121,11 +132,19 @@ export const RulesFormField = ({
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<Heading level="h2" className="mb-2">
|
||||
{t(`promotions.fields.conditions.${ruleType}.title`)}
|
||||
{t(
|
||||
ruleType === "target-rules"
|
||||
? `promotions.fields.conditions.${ruleType}.${applicationMethodTargetType}.title`
|
||||
: `promotions.fields.conditions.${ruleType}.title`
|
||||
)}
|
||||
</Heading>
|
||||
|
||||
<Text className="text-ui-fg-subtle txt-small mb-6">
|
||||
{t(`promotions.fields.conditions.${ruleType}.description`)}
|
||||
{t(
|
||||
ruleType === "target-rules"
|
||||
? `promotions.fields.conditions.${ruleType}.${applicationMethodTargetType}.description`
|
||||
: `promotions.fields.conditions.${ruleType}.description`
|
||||
)}
|
||||
</Text>
|
||||
|
||||
{fields.map((fieldRule, index) => {
|
||||
@@ -307,6 +326,7 @@ export const RulesFormField = ({
|
||||
fieldRule={fieldRule}
|
||||
attributes={attributes}
|
||||
ruleType={ruleType}
|
||||
applicationMethodTargetType={applicationMethodTargetType}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+90
-87
@@ -678,60 +678,62 @@ export const CreatePromotionForm = () => {
|
||||
|
||||
<RulesFormField form={form} ruleType={"rules"} />
|
||||
|
||||
<Divider />
|
||||
|
||||
{!currentTemplate?.hiddenFields?.includes(
|
||||
"application_method.type"
|
||||
) && (
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="application_method.type"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("promotions.fields.value_type")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<RadioGroup
|
||||
className="flex gap-y-3"
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"fixed"}
|
||||
label={t(
|
||||
"promotions.form.value_type.fixed.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.fixed.description"
|
||||
)}
|
||||
className={clx("basis-1/2")}
|
||||
/>
|
||||
<>
|
||||
<Divider />
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="application_method.type"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("promotions.fields.value_type")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<RadioGroup
|
||||
className="flex gap-y-3"
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"fixed"}
|
||||
label={t(
|
||||
"promotions.form.value_type.fixed.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.fixed.description"
|
||||
)}
|
||||
className={clx("basis-1/2")}
|
||||
/>
|
||||
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"percentage"}
|
||||
label={t(
|
||||
"promotions.form.value_type.percentage.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.percentage.description"
|
||||
)}
|
||||
className={clx("basis-1/2")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"percentage"}
|
||||
label={t(
|
||||
"promotions.form.value_type.percentage.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.percentage.description"
|
||||
)}
|
||||
className={clx("basis-1/2")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex gap-x-2 gap-y-4">
|
||||
{!currentTemplate?.hiddenFields?.includes(
|
||||
"application_method.value"
|
||||
) && (
|
||||
{!currentTemplate?.hiddenFields?.includes(
|
||||
"application_method.value"
|
||||
) && (
|
||||
<>
|
||||
<Divider />
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="application_method.value"
|
||||
@@ -806,48 +808,48 @@ export const CreatePromotionForm = () => {
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{isTypeStandard && watchAllocation === "each" && (
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="application_method.max_quantity"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item className="basis-1/2">
|
||||
<Form.Label>
|
||||
{t("promotions.form.max_quantity.title")}
|
||||
</Form.Label>
|
||||
{isTypeStandard && watchAllocation === "each" && (
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="application_method.max_quantity"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item className="basis-1/2">
|
||||
<Form.Label>
|
||||
{t("promotions.form.max_quantity.title")}
|
||||
</Form.Label>
|
||||
|
||||
<Form.Control>
|
||||
<Input
|
||||
{...form.register(
|
||||
"application_method.max_quantity",
|
||||
{ valueAsNumber: true }
|
||||
)}
|
||||
type="number"
|
||||
min={1}
|
||||
placeholder="3"
|
||||
/>
|
||||
</Form.Control>
|
||||
<Form.Control>
|
||||
<Input
|
||||
{...form.register(
|
||||
"application_method.max_quantity",
|
||||
{ valueAsNumber: true }
|
||||
)}
|
||||
type="number"
|
||||
min={1}
|
||||
placeholder="3"
|
||||
/>
|
||||
</Form.Control>
|
||||
|
||||
<Text
|
||||
size="small"
|
||||
leading="compact"
|
||||
className="text-ui-fg-subtle"
|
||||
>
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey="promotions.form.max_quantity.description"
|
||||
components={[<br key="break" />]}
|
||||
/>
|
||||
</Text>
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Text
|
||||
size="small"
|
||||
leading="compact"
|
||||
className="text-ui-fg-subtle"
|
||||
>
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey="promotions.form.max_quantity.description"
|
||||
components={[<br key="break" />]}
|
||||
/>
|
||||
</Text>
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isTypeStandard &&
|
||||
!currentTemplate?.hiddenFields?.includes(
|
||||
@@ -901,6 +903,7 @@ export const CreatePromotionForm = () => {
|
||||
|
||||
{!isTypeStandard && (
|
||||
<>
|
||||
<Divider />
|
||||
<RulesFormField
|
||||
form={form}
|
||||
ruleType={"buy-rules"}
|
||||
|
||||
+23
@@ -22,6 +22,12 @@ const buyGetHiddenFields = [
|
||||
"is_tax_inclusive",
|
||||
]
|
||||
|
||||
const freeShippingHiddenFields = [
|
||||
...commonHiddenFields,
|
||||
"application_method.value",
|
||||
"is_tax_inclusive",
|
||||
]
|
||||
|
||||
export const templates = [
|
||||
{
|
||||
id: "amount_off_products",
|
||||
@@ -104,4 +110,21 @@ export const templates = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "shipping_discount",
|
||||
type: "standard",
|
||||
title: "Free shipping",
|
||||
description: "Applies a 100% discount to shipping fees",
|
||||
hiddenFields: freeShippingHiddenFields,
|
||||
defaults: {
|
||||
is_automatic: "false",
|
||||
type: "standard",
|
||||
application_method: {
|
||||
allocation: "across",
|
||||
target_type: "shipping_methods",
|
||||
type: "percentage",
|
||||
value: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
import { PencilSquare } from "@medusajs/icons"
|
||||
import { HttpTypes, PromotionRuleTypes } from "@medusajs/types"
|
||||
import { ApplicationMethodTargetTypeValues, HttpTypes, PromotionRuleTypes, } from "@medusajs/types"
|
||||
import { Badge, Container, Heading } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
@@ -44,11 +44,13 @@ function RuleBlock({ rule }: RuleProps) {
|
||||
type PromotionConditionsSectionProps = {
|
||||
rules: HttpTypes.AdminPromotionRule[]
|
||||
ruleType: PromotionRuleTypes
|
||||
applicationMethodTargetType: ApplicationMethodTargetTypeValues
|
||||
}
|
||||
|
||||
export const PromotionConditionsSection = ({
|
||||
rules,
|
||||
ruleType,
|
||||
applicationMethodTargetType,
|
||||
}: PromotionConditionsSectionProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -57,7 +59,11 @@ export const PromotionConditionsSection = ({
|
||||
<div className="flex items-center justify-between px-6 py-4">
|
||||
<div className="flex flex-col">
|
||||
<Heading>
|
||||
{t(`promotions.fields.conditions.${ruleType}.title`)}
|
||||
{t(
|
||||
ruleType === "target-rules"
|
||||
? `promotions.fields.conditions.${ruleType}.${applicationMethodTargetType}.title`
|
||||
: `promotions.fields.conditions.${ruleType}.title`
|
||||
)}
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -52,11 +52,15 @@ export const PromotionDetail = () => {
|
||||
<PromotionConditionsSection
|
||||
rules={targetRules || []}
|
||||
ruleType={"target-rules"}
|
||||
applicationMethodTargetType={
|
||||
promotion.application_method.target_type || "items"
|
||||
}
|
||||
/>
|
||||
{promotion.type === "buyget" && (
|
||||
<PromotionConditionsSection
|
||||
rules={buyRules || []}
|
||||
ruleType={"buy-rules"}
|
||||
applicationMethodTargetType={"items"}
|
||||
/>
|
||||
)}
|
||||
</TwoColumnPage.Main>
|
||||
|
||||
+132
-126
@@ -1,13 +1,6 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { AdminPromotion } from "@medusajs/types"
|
||||
import {
|
||||
Button,
|
||||
CurrencyInput,
|
||||
Input,
|
||||
RadioGroup,
|
||||
Switch,
|
||||
Text,
|
||||
} from "@medusajs/ui"
|
||||
import { Button, CurrencyInput, Input, RadioGroup, Text } from "@medusajs/ui"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import { Trans, useTranslation } from "react-i18next"
|
||||
import { useEffect } from "react"
|
||||
@@ -33,6 +26,7 @@ const EditPromotionSchema = zod.object({
|
||||
value_type: zod.enum(["fixed", "percentage"]),
|
||||
value: zod.number(),
|
||||
allocation: zod.enum(["each", "across"]),
|
||||
target_type: zod.enum(["order", "shipping_methods", "items"]),
|
||||
})
|
||||
|
||||
export const EditPromotionDetailsForm = ({
|
||||
@@ -50,6 +44,7 @@ export const EditPromotionDetailsForm = ({
|
||||
value: promotion.application_method!.value,
|
||||
allocation: promotion.application_method!.allocation,
|
||||
value_type: promotion.application_method!.type,
|
||||
target_type: promotion.application_method!.target_type,
|
||||
},
|
||||
resolver: zodResolver(EditPromotionSchema),
|
||||
})
|
||||
@@ -223,128 +218,139 @@ export const EditPromotionDetailsForm = ({
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="value_type"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>{t("promotions.fields.value_type")}</Form.Label>
|
||||
<Form.Control>
|
||||
<RadioGroup
|
||||
className="flex-col gap-y-3"
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"fixed"}
|
||||
label={t("promotions.form.value_type.fixed.title")}
|
||||
description={t(
|
||||
"promotions.form.value_type.fixed.description"
|
||||
)}
|
||||
/>
|
||||
{promotion.application_method?.target_type !==
|
||||
"shipping_methods" && (
|
||||
<>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="value_type"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("promotions.fields.value_type")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<RadioGroup
|
||||
className="flex-col gap-y-3"
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"fixed"}
|
||||
label={t(
|
||||
"promotions.form.value_type.fixed.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.fixed.description"
|
||||
)}
|
||||
/>
|
||||
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"percentage"}
|
||||
label={t(
|
||||
"promotions.form.value_type.percentage.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.percentage.description"
|
||||
)}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"percentage"}
|
||||
label={t(
|
||||
"promotions.form.value_type.percentage.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.value_type.percentage.description"
|
||||
)}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="value"
|
||||
render={({ field: { onChange, ...field } }) => {
|
||||
const currencyCode =
|
||||
promotion.application_method?.currency_code ?? "USD"
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="value"
|
||||
render={({ field: { onChange, ...field } }) => {
|
||||
const currencyCode =
|
||||
promotion.application_method?.currency_code ?? "USD"
|
||||
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{isFixedValueType
|
||||
? t("fields.amount")
|
||||
: t("fields.percentage")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
{isFixedValueType ? (
|
||||
<CurrencyInput
|
||||
min={0}
|
||||
onValueChange={(val) =>
|
||||
onChange(val ? parseInt(val) : null)
|
||||
}
|
||||
code={currencyCode}
|
||||
symbol={getCurrencySymbol(currencyCode)}
|
||||
{...field}
|
||||
value={field.value}
|
||||
/>
|
||||
) : (
|
||||
<DeprecatedPercentageInput
|
||||
key="amount"
|
||||
min={0}
|
||||
max={100}
|
||||
{...field}
|
||||
value={field.value || ""}
|
||||
onChange={(e) => {
|
||||
onChange(
|
||||
e.target.value === ""
|
||||
? null
|
||||
: parseInt(e.target.value)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="allocation"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>{t("promotions.fields.allocation")}</Form.Label>
|
||||
<Form.Control>
|
||||
<RadioGroup
|
||||
className="flex-col gap-y-3"
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"each"}
|
||||
label={t("promotions.form.allocation.each.title")}
|
||||
description={t(
|
||||
"promotions.form.allocation.each.description"
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{isFixedValueType
|
||||
? t("fields.amount")
|
||||
: t("fields.percentage")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
{isFixedValueType ? (
|
||||
<CurrencyInput
|
||||
min={0}
|
||||
onValueChange={(val) =>
|
||||
onChange(val ? parseInt(val) : null)
|
||||
}
|
||||
code={currencyCode}
|
||||
symbol={getCurrencySymbol(currencyCode)}
|
||||
{...field}
|
||||
value={field.value}
|
||||
/>
|
||||
) : (
|
||||
<DeprecatedPercentageInput
|
||||
key="amount"
|
||||
min={0}
|
||||
max={100}
|
||||
{...field}
|
||||
value={field.value || ""}
|
||||
onChange={(e) => {
|
||||
onChange(
|
||||
e.target.value === ""
|
||||
? null
|
||||
: parseInt(e.target.value)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="allocation"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("promotions.fields.allocation")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<RadioGroup
|
||||
className="flex-col gap-y-3"
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"each"}
|
||||
label={t("promotions.form.allocation.each.title")}
|
||||
description={t(
|
||||
"promotions.form.allocation.each.description"
|
||||
)}
|
||||
/>
|
||||
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"across"}
|
||||
label={t("promotions.form.allocation.across.title")}
|
||||
description={t(
|
||||
"promotions.form.allocation.across.description"
|
||||
)}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<RadioGroup.ChoiceBox
|
||||
value={"across"}
|
||||
label={t(
|
||||
"promotions.form.allocation.across.title"
|
||||
)}
|
||||
description={t(
|
||||
"promotions.form.allocation.across.description"
|
||||
)}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</RouteDrawer.Body>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user