Merged in feat/LOY-364-promo-activation-flow (pull request #2872)

Feat/LOY-364 promo activation flow

* feat(LOY-364): add promo activation flow

* chore(LOY-371): add tracking

Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
Matilda Landström
2025-10-01 06:39:35 +00:00
parent 8ac9e82476
commit 72d62e6868
17 changed files with 373 additions and 35 deletions

View File

@@ -221,6 +221,7 @@ export namespace endpoints {
*/
export namespace Profile {
export const profile = `${base.path.profile}/${version}/${base.enitity.Profile}`
export const promoCampaign = `${profile}/Promotion`
export function teamMemberCard(employeeId: string) {
return `${profile}/${employeeId}/TeamMemberCard`

View File

@@ -62,3 +62,7 @@ export const getSavedPaymentCardsInput = z.object({
export type GetSavedPaymentCardsInput = z.input<
typeof getSavedPaymentCardsInput
>
export const addPromoCampaignInput = z.object({
promotionId: z.string(),
})

View File

@@ -9,6 +9,7 @@ import { serverErrorByStatus } from "../../errors"
import { protectedProcedure, serviceProcedure } from "../../procedures"
import {
addCreditCardInput,
addPromoCampaignInput,
deleteCreditCardInput,
saveCreditCardInput,
signupInput,
@@ -216,4 +217,48 @@ export const userMutationRouter = router({
redirectUrl: signupVerify[input.language],
}
}),
promoCampaign: router({
add: protectedProcedure
.input(addPromoCampaignInput)
.mutation(async function ({ ctx, input }) {
userMutationLogger.info("api.user.promoCampaign.add start")
const apiResponse = await api.post(
api.endpoints.v2.Profile.promoCampaign,
{
headers: {
Authorization: `Bearer ${ctx.session.token.access_token}`,
},
body: {
promotionId: input.promotionId,
},
}
)
if (!apiResponse.ok) {
const text = await apiResponse.text()
userMutationLogger.error(
"api.user.promoCampaign.add error",
JSON.stringify({
query: {
promotionId: input.promotionId,
},
error: {
status: apiResponse.status,
statusText: apiResponse.statusText,
text,
},
})
)
return false
}
userMutationLogger.info(
"api.user.promoCampaign.add success",
JSON.stringify({
query: { promotionId: input.promotionId },
})
)
return true
}),
}),
})

View File

@@ -113,6 +113,7 @@ export const getUserSchema = z
.nullable(),
loyalty: userLoyaltySchema.optional(),
employmentDetails: employmentDetailsSchema,
promotions: z.array(z.string()).nullish(),
}),
type: z.string(),
}),

View File

@@ -93,8 +93,8 @@ export const getVerifiedUser = cache(
)
return null
}
const verifiedData = getUserSchema.safeParse(apiJson)
if (!verifiedData.success) {
metricsGetVerifiedUser.validationError(verifiedData.error)
return null
@@ -224,6 +224,7 @@ export function parsedUser(data: User, isMFA: boolean) {
dateOfBirth: data.dateOfBirth,
email: data.email,
employmentDetails: data.employmentDetails,
promotions: data.promotions || null,
firstName: data.firstName,
language: data.language,
lastName: data.lastName,

View File

@@ -26,6 +26,7 @@ export interface PromoCampaignPage
export type PromoCampaignPageData = PromoCampaignPage["promo_campaign_page"]
export type PromoHero = NonNullable<PromoCampaignPageData["promo_hero"]>
export type PromoCode = NonNullable<PromoCampaignPageData["promo_code"]>
/* REFS */
export interface GetPromoCampaignPageRefsData