Skip to content

Commit 294c375

Browse files
authored
fix(dashboard): edit promotion campaign w/wo currrency (medusajs#13404)
**What** - a promotion couldn't be added to a campaign without a currency budget (on promotion details screen) - fix fetching campaigns pagination issue - move select to Combobox - fix currency restriction and move warning description to the label hint
1 parent c4c2231 commit 294c375

File tree

5 files changed

+56
-74
lines changed

5 files changed

+56
-74
lines changed

.changeset/blue-hounds-unite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@medusajs/dashboard": patch
3+
---
4+
5+
fix(dashboard): add campaign without currency to promotion

packages/admin/dashboard/src/hooks/api/campaigns.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export const useAddOrRemoveCampaignPromotions = (
130130
onSuccess: (data, variables, context) => {
131131
queryClient.invalidateQueries({ queryKey: campaignsQueryKeys.details() })
132132
queryClient.invalidateQueries({ queryKey: promotionsQueryKeys.lists() })
133+
queryClient.invalidateQueries({ queryKey: promotionsQueryKeys.details() })
133134
options?.onSuccess?.(data, variables, context)
134135
},
135136
...options,

packages/admin/dashboard/src/i18n/translations/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2234,7 +2234,7 @@
22342234
"total_used": "Budget used",
22352235
"budget_limit": "Budget limit",
22362236
"campaign_id": {
2237-
"hint": "Only campaigns with the same currency code as the promotion are shown in this list."
2237+
"hint": "Disabled campaigns have budget in a different currency than the promotion."
22382238
}
22392239
},
22402240
"budget": {

packages/admin/dashboard/src/routes/promotions/promotion-add-campaign/components/add-campaign-promotion-form/add-campaign-promotion-form.tsx

Lines changed: 45 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
import { zodResolver } from "@hookform/resolvers/zod"
22
import { AdminCampaign, AdminPromotion } from "@medusajs/types"
3-
import { Button, RadioGroup, Select, Text, toast } from "@medusajs/ui"
3+
import { Button, RadioGroup, toast } from "@medusajs/ui"
44
import { useEffect } from "react"
55
import { useForm, useWatch } from "react-hook-form"
6-
import { Trans, useTranslation } from "react-i18next"
6+
import { useTranslation } from "react-i18next"
77
import * as zod from "zod"
88
import { Form } from "../../../../../components/common/form"
99
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
1010
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
1111
import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
1212
import { CreateCampaignFormFields } from "../../../../campaigns/common/components/create-campaign-form-fields"
1313
import { CampaignDetails } from "./campaign-details"
14+
import { sdk } from "../../../../../lib/client"
15+
import { useComboboxData } from "../../../../../hooks/use-combobox-data"
16+
import { Combobox } from "../../../../../components/inputs/combobox"
17+
import { useCampaign } from "../../../../../hooks/api/campaigns"
1418
import { useDocumentDirection } from "../../../../../hooks/use-document-direction"
1519

1620
type EditPromotionFormProps = {
1721
promotion: AdminPromotion
18-
campaigns: AdminCampaign[]
1922
}
2023

2124
const EditPromotionSchema = zod.object({
@@ -25,14 +28,16 @@ const EditPromotionSchema = zod.object({
2528

2629
export const AddCampaignPromotionFields = ({
2730
form,
28-
campaigns,
2931
withNewCampaign = true,
32+
promotionCurrencyCode,
3033
}: {
3134
form: any
32-
campaigns: AdminCampaign[]
3335
withNewCampaign?: boolean
36+
promotionCurrencyCode?: string
3437
}) => {
3538
const { t } = useTranslation()
39+
const direction = useDocumentDirection()
40+
3641
const watchCampaignId = useWatch({
3742
control: form.control,
3843
name: "campaign_id",
@@ -43,8 +48,31 @@ export const AddCampaignPromotionFields = ({
4348
name: "campaign_choice",
4449
})
4550

46-
const selectedCampaign = campaigns.find((c) => c.id === watchCampaignId)
47-
const direction = useDocumentDirection()
51+
const campaignsCombobox = useComboboxData({
52+
queryFn: (params) =>
53+
sdk.admin.campaign.list({
54+
...params,
55+
}),
56+
queryKey: ["campaigns"],
57+
getOptions: (data) =>
58+
data.campaigns.map((campaign) => ({
59+
label: campaign.name.toUpperCase(),
60+
value: campaign.id,
61+
disabled:
62+
campaign.budget?.currency_code &&
63+
campaign.budget?.currency_code?.toLowerCase() !==
64+
promotionCurrencyCode?.toLowerCase(), // also cannot add promotion which doesn't have currency defined to a campaign with a currency amount budget
65+
})),
66+
})
67+
68+
const { campaign: selectedCampaign } = useCampaign(
69+
watchCampaignId as string,
70+
undefined,
71+
{
72+
enabled: !!watchCampaignId,
73+
}
74+
)
75+
4876
return (
4977
<div className="flex flex-col gap-y-8">
5078
<Form.Field
@@ -99,58 +127,24 @@ export const AddCampaignPromotionFields = ({
99127
<Form.Field
100128
control={form.control}
101129
name="campaign_id"
102-
render={({ field: { onChange, ref, ...field } }) => {
130+
render={({ field: { onChange, ...field } }) => {
103131
return (
104132
<Form.Item>
105-
<Form.Label>
133+
<Form.Label tooltip={t("campaigns.fields.campaign_id.hint")}>
106134
{t("promotions.form.campaign.existing.title")}
107135
</Form.Label>
108136

109137
<Form.Control>
110-
<Select
138+
<Combobox
111139
dir={direction}
112-
onValueChange={onChange}
140+
options={campaignsCombobox.options}
141+
searchValue={campaignsCombobox.searchValue}
142+
onSearchValueChange={campaignsCombobox.onSearchValueChange}
143+
onChange={onChange}
113144
{...field}
114-
>
115-
<Select.Trigger ref={ref}>
116-
<Select.Value />
117-
</Select.Trigger>
118-
119-
<Select.Content>
120-
{!campaigns.length && (
121-
<div className="flex h-[120px] flex-col items-center justify-center gap-2 p-2">
122-
<span className="txt-small text-ui-fg-subtle font-medium">
123-
{t(
124-
"promotions.form.campaign.existing.placeholder.title"
125-
)}
126-
</span>
127-
<span className="txt-small text-ui-fg-muted">
128-
{t(
129-
"promotions.form.campaign.existing.placeholder.desc"
130-
)}
131-
</span>
132-
</div>
133-
)}
134-
{campaigns.map((c) => (
135-
<Select.Item key={c.id} value={c.id}>
136-
{c.name?.toUpperCase()}
137-
</Select.Item>
138-
))}
139-
</Select.Content>
140-
</Select>
145+
></Combobox>
141146
</Form.Control>
142147

143-
<Text
144-
size="small"
145-
leading="compact"
146-
className="text-ui-fg-subtle"
147-
>
148-
<Trans
149-
t={t}
150-
i18nKey="campaigns.fields.campaign_id.hint"
151-
components={[<br key="break" />]}
152-
/>
153-
</Text>
154148
<Form.ErrorMessage />
155149
</Form.Item>
156150
)
@@ -162,14 +156,13 @@ export const AddCampaignPromotionFields = ({
162156
<CreateCampaignFormFields form={form} fieldScope="campaign." />
163157
)}
164158

165-
<CampaignDetails campaign={selectedCampaign} />
159+
<CampaignDetails campaign={selectedCampaign as AdminCampaign} />
166160
</div>
167161
)
168162
}
169163

170164
export const AddCampaignPromotionForm = ({
171165
promotion,
172-
campaigns,
173166
}: EditPromotionFormProps) => {
174167
const { t } = useTranslation()
175168
const { handleSuccess } = useRouteModal()
@@ -227,8 +220,8 @@ export const AddCampaignPromotionForm = ({
227220
<RouteDrawer.Body className="size-full overflow-auto">
228221
<AddCampaignPromotionFields
229222
form={form}
230-
campaigns={campaigns}
231223
withNewCampaign={false}
224+
promotionCurrencyCode={promotion.application_method?.currency_code}
232225
/>
233226
</RouteDrawer.Body>
234227

packages/admin/dashboard/src/routes/promotions/promotion-add-campaign/promotion-add-campaign.tsx

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useTranslation } from "react-i18next"
33
import { useParams } from "react-router-dom"
44

55
import { RouteDrawer } from "../../../components/modals"
6-
import { useCampaigns } from "../../../hooks/api/campaigns"
76
import { usePromotion } from "../../../hooks/api/promotions"
87
import { AddCampaignPromotionForm } from "./components/add-campaign-promotion-form"
98

@@ -12,24 +11,8 @@ export const PromotionAddCampaign = () => {
1211
const { t } = useTranslation()
1312
const { promotion, isPending, isError, error } = usePromotion(id!)
1413

15-
let campaignQuery = {}
16-
17-
if (promotion?.application_method?.currency_code) {
18-
campaignQuery = {
19-
budget: {
20-
currency_code: promotion?.application_method?.currency_code,
21-
},
22-
}
23-
}
24-
25-
const {
26-
campaigns,
27-
isPending: areCampaignsLoading,
28-
isError: isCampaignError,
29-
error: campaignError,
30-
} = useCampaigns(campaignQuery)
31-
if (isError || isCampaignError) {
32-
throw error || campaignError
14+
if (isError) {
15+
throw error
3316
}
3417

3518
return (
@@ -38,8 +21,8 @@ export const PromotionAddCampaign = () => {
3821
<Heading>{t("promotions.campaign.edit.header")}</Heading>
3922
</RouteDrawer.Header>
4023

41-
{!isPending && !areCampaignsLoading && promotion && campaigns && (
42-
<AddCampaignPromotionForm promotion={promotion} campaigns={campaigns} />
24+
{!isPending && promotion && (
25+
<AddCampaignPromotionForm promotion={promotion} />
4326
)}
4427
</RouteDrawer>
4528
)

0 commit comments

Comments
 (0)