Merged in feat/SW-1810-prevent-starting-link-flow-when-linked (pull request #1469)

Prevent SAS link flow when already linked

* Implement check for checking sas_eb membership when starting link flow


Approved-by: Joakim Jäderberg
This commit is contained in:
Anton Gunnarsson
2025-03-05 08:17:02 +00:00
parent 81f1470405
commit 43d3713f59
8 changed files with 33 additions and 23 deletions

View File

@@ -10,7 +10,7 @@ import { protectedServerActionProcedure } from "@/server/trpc"
import { editProfileSchema } from "@/components/Forms/Edit/Profile/schema" import { editProfileSchema } from "@/components/Forms/Edit/Profile/schema"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { getMembership } from "@/utils/user" import { getFriendsMembership } from "@/utils/user"
import { phoneValidator } from "@/utils/zod/phoneValidator" import { phoneValidator } from "@/utils/zod/phoneValidator"
import { Status } from "@/types/components/myPages/myProfile/edit" import { Status } from "@/types/components/myPages/myProfile/edit"
@@ -142,7 +142,7 @@ export const editProfile = protectedServerActionProcedure
status: Status.success, status: Status.success,
} }
} else { } else {
const membership = getMembership(profile.memberships) const membership = getFriendsMembership(profile.memberships)
console.log( console.log(
`[edit profile: ${membership?.membershipNumber}] body keys: ${JSON.stringify(Object.keys(body))}` `[edit profile: ${membership?.membershipNumber}] body keys: ${JSON.stringify(Object.keys(body))}`
) )

View File

@@ -3,6 +3,8 @@ import React from "react"
import { getProfileSafely } from "@/lib/trpc/memoizedRequests" import { getProfileSafely } from "@/lib/trpc/memoizedRequests"
import { getEurobonusMembership } from "@/utils/user"
import { SASModal } from "../components/SASModal" import { SASModal } from "../components/SASModal"
import { LinkAccountForm } from "./LinkAccountForm" import { LinkAccountForm } from "./LinkAccountForm"
@@ -13,10 +15,11 @@ export default async function SASxScandicLinkPage({
}: PageArgs<LangParams>) { }: PageArgs<LangParams>) {
const profile = await getProfileSafely() const profile = await getProfileSafely()
// TODO check if already linked if (!profile) return null
const alreadyLinked = false
if (alreadyLinked) { const eurobonusMembership = getEurobonusMembership(profile.memberships)
if (eurobonusMembership) {
redirect(`/${params.lang}/sas-x-scandic/error?errorCode=alreadyLinked`) redirect(`/${params.lang}/sas-x-scandic/error?errorCode=alreadyLinked`)
} }

View File

@@ -4,13 +4,13 @@ import { dt } from "@/lib/dt"
import Body from "@/components/TempDesignSystem/Text/Body" import Body from "@/components/TempDesignSystem/Text/Body"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext" import { getLang } from "@/i18n/serverContext"
import { getMembership } from "@/utils/user" import { getFriendsMembership } from "@/utils/user"
import type { UserProps } from "@/types/components/myPages/user" import type { UserProps } from "@/types/components/myPages/user"
export default async function ExpiringPoints({ user }: UserProps) { export default async function ExpiringPoints({ user }: UserProps) {
const intl = await getIntl() const intl = await getIntl()
const membership = getMembership(user.memberships) const membership = getFriendsMembership(user.memberships)
if (!membership || !membership.pointsToExpire) { if (!membership || !membership.pointsToExpire) {
// TODO: handle this case? // TODO: handle this case?

View File

@@ -2,7 +2,7 @@ import { MembershipLevelEnum } from "@/constants/membershipLevels"
import { serverClient } from "@/lib/trpc/server" import { serverClient } from "@/lib/trpc/server"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { getMembership } from "@/utils/user" import { getFriendsMembership } from "@/utils/user"
import PointsContainer from "./Container" import PointsContainer from "./Container"
import { PointsColumn } from "./PointsColumn" import { PointsColumn } from "./PointsColumn"
@@ -12,7 +12,7 @@ import type { UserProps } from "@/types/components/myPages/user"
export default async function Points({ user }: UserProps) { export default async function Points({ user }: UserProps) {
const intl = await getIntl() const intl = await getIntl()
const membership = getMembership(user.memberships) const membership = getFriendsMembership(user.memberships)
const nextLevel = const nextLevel =
membership?.nextLevel && MembershipLevelEnum[membership.nextLevel] membership?.nextLevel && MembershipLevelEnum[membership.nextLevel]

View File

@@ -4,7 +4,7 @@ import * as api from "@/lib/api"
import { getVerifiedUser } from "@/server/routers/user/query" import { getVerifiedUser } from "@/server/routers/user/query"
import { router, safeProtectedServiceProcedure } from "@/server/trpc" import { router, safeProtectedServiceProcedure } from "@/server/trpc"
import { getMembership } from "@/utils/user" import { getFriendsMembership } from "@/utils/user"
import { import {
addPackageInput, addPackageInput,
@@ -67,7 +67,7 @@ async function getMembershipNumber(
return undefined return undefined
} }
const membership = getMembership(verifiedUser.data.memberships) const membership = getFriendsMembership(verifiedUser.data.memberships)
return membership?.membershipNumber return membership?.membershipNumber
} }

View File

@@ -2,7 +2,7 @@ import { z } from "zod"
import { countriesMap } from "@/constants/countries" import { countriesMap } from "@/constants/countries"
import { getMembership, scandicMemberships } from "@/utils/user" import { getFriendsMembership, scandicMemberships } from "@/utils/user"
import { imageSchema } from "../hotels/schemas/image" import { imageSchema } from "../hotels/schemas/image"
@@ -18,11 +18,10 @@ const commonMembershipSchema = z.object({
tierExpirationDate: z.string().optional(), tierExpirationDate: z.string().optional(),
}) })
const toLowerCaseString = z.string().transform((s) => s.toLowerCase())
const membershipType = (membershipType: scandicMemberships) => const membershipType = (membershipType: scandicMemberships) =>
z toLowerCaseString
.string()
// The memberships enum is in lower case so this makes sure it will match regardless of casing in the API response. // The memberships enum is in lower case so this makes sure it will match regardless of casing in the API response.
.transform((s) => s.toLowerCase())
.pipe(z.literal(membershipType)) .pipe(z.literal(membershipType))
const friendsMembershipSchema = z const friendsMembershipSchema = z
@@ -35,7 +34,7 @@ const friendsMembershipSchema = z
const otherMembershipSchema = z const otherMembershipSchema = z
.object({ .object({
membershipType: z.string(), membershipType: toLowerCaseString,
membershipNumber: z.string().optional(), membershipNumber: z.string().optional(),
memberSince: z.string().optional(), memberSince: z.string().optional(),
}) })
@@ -75,7 +74,7 @@ export const getUserSchema = z
.transform((apiResponse) => { .transform((apiResponse) => {
return { return {
...apiResponse.data.attributes, ...apiResponse.data.attributes,
membership: getMembership(apiResponse.data.attributes.memberships), membership: getFriendsMembership(apiResponse.data.attributes.memberships),
name: `${apiResponse.data.attributes.firstName} ${apiResponse.data.attributes.lastName}`, name: `${apiResponse.data.attributes.firstName} ${apiResponse.data.attributes.lastName}`,
} }
}) })

View File

@@ -11,7 +11,7 @@ import {
import { cache } from "@/utils/cache" import { cache } from "@/utils/cache"
import * as maskValue from "@/utils/maskValue" import * as maskValue from "@/utils/maskValue"
import { getMembership, getMembershipCards } from "@/utils/user" import { getFriendsMembership, getMembershipCards } from "@/utils/user"
import { import {
friendTransactionsInput, friendTransactionsInput,
@@ -184,7 +184,7 @@ export function parsedUser(data: User, isMFA: boolean) {
firstName: data.firstName, firstName: data.firstName,
language: data.language, language: data.language,
lastName: data.lastName, lastName: data.lastName,
membership: getMembership(data.memberships), membership: getFriendsMembership(data.memberships),
memberships: data.memberships, memberships: data.memberships,
name: `${data.firstName} ${data.lastName}`, name: `${data.firstName} ${data.lastName}`,
phoneNumber: data.phoneNumber, phoneNumber: data.phoneNumber,
@@ -341,7 +341,7 @@ export const userQueryRouter = router({
return null return null
} }
const membershipLevel = getMembership(verifiedData.data.memberships) const membershipLevel = getFriendsMembership(verifiedData.data.memberships)
return membershipLevel return membershipLevel
}), }),
safeMembershipLevel: safeProtectedProcedure.query(async function ({ ctx }) { safeMembershipLevel: safeProtectedProcedure.query(async function ({ ctx }) {
@@ -354,7 +354,7 @@ export const userQueryRouter = router({
return null return null
} }
const membershipLevel = getMembership(verifiedData.data.memberships) const membershipLevel = getFriendsMembership(verifiedData.data.memberships)
return membershipLevel return membershipLevel
}), }),
userTrackingInfo: safeProtectedProcedure.query(async function ({ ctx }) { userTrackingInfo: safeProtectedProcedure.query(async function ({ ctx }) {
@@ -425,7 +425,7 @@ export const userQueryRouter = router({
getPreviousStaysSuccessCounter.add(1) getPreviousStaysSuccessCounter.add(1)
console.info("api.booking.stays.past success", JSON.stringify({})) console.info("api.booking.stays.past success", JSON.stringify({}))
const membership = getMembership(verifiedUserData.data.memberships) const membership = getFriendsMembership(verifiedUserData.data.memberships)
const loggedInUserTrackingData: TrackingSDKUserData = { const loggedInUserTrackingData: TrackingSDKUserData = {
loginStatus: "logged in", loginStatus: "logged in",

View File

@@ -11,9 +11,10 @@ import type { getMembershipCardsSchema } from "@/server/routers/user/output"
export enum scandicMemberships { export enum scandicMemberships {
guestpr = "guestpr", guestpr = "guestpr",
scandicfriends = "scandicfriend's", scandicfriends = "scandicfriend's",
sas_eb = "sas_eb",
} }
export function getMembership(memberships: Memberships) { export function getFriendsMembership(memberships: Memberships) {
return memberships?.find( return memberships?.find(
(membership) => (membership) =>
membership.membershipType.toLowerCase() === scandicMemberships.guestpr membership.membershipType.toLowerCase() === scandicMemberships.guestpr
@@ -28,6 +29,13 @@ export type FriendsMembership = Omit<
nextLevel: MembershipLevel nextLevel: MembershipLevel
} }
export function getEurobonusMembership(memberships: Memberships) {
return memberships?.find(
(membership) =>
membership.membershipType.toLowerCase() === scandicMemberships.sas_eb
)
}
export function getMembershipCards( export function getMembershipCards(
memberships: z.infer<typeof getMembershipCardsSchema> memberships: z.infer<typeof getMembershipCardsSchema>
) { ) {