import { cx } from "class-variance-authority"
import { type ReactNode, Suspense } from "react"
import DiamondAddIcon from "@scandic-hotels/design-system/Icons/DiamondAddIcon"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { getEurobonusMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import {
SAS_EUROBONUS_TIER_TO_NAME_MAP,
TIER_TO_FRIEND_MAP,
} from "@/constants/membershipLevels"
import { getProfileWithExtendedPartnerData } from "@/lib/trpc/memoizedRequests"
import { Section } from "@/components/Section"
import SectionHeader from "@/components/Section/Header/Deprecated"
import SectionLink from "@/components/Section/Link"
import { getIntl } from "@/i18n"
import { getSasTierExpirationDate } from "@/utils/sas"
import { UnlinkSAS } from "./UnlinkSAS"
import styles from "./linkedAccounts.module.css"
import type { UserLoyalty } from "@scandic-hotels/trpc/types/user"
type Props = {
title?: string
link?: { href: string; text: string }
subtitle?: string
}
export default async function SASLinkedAccount({
title,
subtitle,
link,
}: Props) {
const intl = await getIntl()
return (
{intl.formatMessage({
id: "sas.linkedAccounts.changeDelayInfo",
defaultMessage:
"Changes in your level match can take up to 24 hours to be displayed.",
})}
)
}
async function MatchedAccountInfo() {
const user = await getProfileWithExtendedPartnerData()
if (!user || "error" in user || !user.loyalty) {
return null
}
const intl = await getIntl()
const eurobonusMembership = getEurobonusMembership(user.loyalty)
const friendsMembership = user.membership
if (!eurobonusMembership || !friendsMembership) {
return null
}
const sasLevelName =
SAS_EUROBONUS_TIER_TO_NAME_MAP[
eurobonusMembership.boostedTier || eurobonusMembership.tier
]
const sasMembershipNumber = eurobonusMembership.membershipNumber
const sasTierExpirationDate = getSasTierExpirationDate(eurobonusMembership)
const scandicLevelName = TIER_TO_FRIEND_MAP[friendsMembership.membershipLevel]
const scandicExpirationDate = friendsMembership.tierExpirationDate
const matchState = calculateMatchState(user.loyalty)
return (
{intl.formatMessage({
id: "sas.linkedAccounts.linkedAccount",
defaultMessage: "Linked account",
})}
{intl.formatMessage({
id: "partnerSas.sasEuroBonus",
defaultMessage: "SAS EuroBonus",
})}
{intl.formatMessage({
id: "common.level",
defaultMessage: "Level",
})}
{sasLevelName}
{intl.formatMessage({
id: "common.membershipId",
defaultMessage: "Membership ID",
})}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
EB{sasMembershipNumber}
)
}
async function MatchedAccountInfoSkeleton() {
const intl = await getIntl()
return (
{intl.formatMessage({
id: "sas.linkedAccounts.linkedAccount",
defaultMessage: "Linked account",
})}
{intl.formatMessage({
id: "partnerSas.sasEuroBonus",
defaultMessage: "SAS EuroBonus",
})}
{intl.formatMessage({
id: "common.level",
defaultMessage: "Level",
})}
{intl.formatMessage({
id: "common.membershipId",
defaultMessage: "Membership ID",
})}
)
}
type TierMatchMessageProps = {
matchState: MatchState
scandicLevelName: string
sasLevelName: string
}
async function TierMatchMessage({
matchState,
sasLevelName,
scandicLevelName,
}: TierMatchMessageProps) {
const intl = await getIntl()
const messageValues = {
sasLevelName: sasLevelName,
scandicLevelName: scandicLevelName,
sasMark: (text: ReactNode) => (
{text}
),
scandicMark: (text: ReactNode) => (
{text}
),
}
const messageMap: Record = {
boostedBySAS: intl.formatMessage(
{
id: "sas.linkedAccounts.euroBonusSasUpgradedText",
defaultMessage:
"EuroBonus {sasLevelName} has upgraded your Scandic Friends level to {scandicLevelName} .",
},
messageValues
),
boostedByScandic: intl.formatMessage(
{
id: "sas.linkedAccounts.scandicFriendsUpgradedText",
defaultMessage:
"Your Scandic Friends level {scandicLevelName} has upgraded you to EuroBonus {sasLevelName} .",
},
messageValues
),
noBoost: intl.formatMessage(
{
id: "sas.linkedAccounts.euroBonusSasText",
defaultMessage:
"EuroBonus {sasLevelName} and {scandicLevelName} are equally matched. Level up in one of your memberships to qualify for an upgrade!",
},
messageValues
),
}
const iconMap: Record = {
boostedBySAS: ,
boostedByScandic: ,
noBoost: ,
}
return (
{intl.formatMessage({
id: "sas.linkedAccounts.levelMatchStatus",
defaultMessage: "Level match status",
})}
{iconMap[matchState]}
{messageMap[matchState]}
)
}
async function TierMatchMessageSkeleton() {
const intl = await getIntl()
return (
{intl.formatMessage({
id: "sas.linkedAccounts.levelMatchStatus",
defaultMessage: "Level match status",
})}
)
}
type TierMatchExpirationProps = {
matchState: MatchState
sasExpirationDate: string | null
scandicExpirationDate: string | undefined
}
async function TierMatchExpiration({
matchState,
sasExpirationDate,
scandicExpirationDate,
}: TierMatchExpirationProps) {
if (matchState === "noBoost") {
return null
}
const intl = await getIntl()
const displayedExpirationDate =
matchState === "boostedBySAS" ? scandicExpirationDate : sasExpirationDate
if (!displayedExpirationDate) {
return null
}
return (
{intl.formatMessage({
id: "sas.linkedAccounts.upgradeValidUntil",
defaultMessage: "Upgrade valid until",
})}
{displayedExpirationDate}
)
}
function Label({ children }: { children: ReactNode }) {
return (
{children}
)
}
type MatchState = "boostedBySAS" | "boostedByScandic" | "noBoost"
function calculateMatchState(loyalty: UserLoyalty): MatchState {
const eurobonusMembership = getEurobonusMembership(loyalty)
if (eurobonusMembership?.boostedByScandic) return "boostedByScandic"
if (!loyalty.tierBoostedBy) return "noBoost"
if (loyalty.tierBoostedBy === "SAS_EB") return "boostedBySAS"
return "noBoost"
}