Merged in chore/cleanup-my-pages-overview (pull request #3049)

chore(LOY-447): remove flag and unused code on my pages overview

* chore: remove flag and unused code


Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
Matilda Landström
2025-11-04 09:15:43 +00:00
parent 4970dfa2ed
commit 0131b5f731
24 changed files with 18 additions and 568 deletions

View File

@@ -53,7 +53,6 @@ GOOGLE_DYNAMIC_MAP_ID=""
ENABLE_SURPRISES="true"
ENABLE_DTMC="true"
ENABLE_NEW_OVERVIEW_SECTION="true"
SHOW_SITE_WIDE_ALERT="false"

View File

@@ -1,47 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
import { toast } from "@scandic-hotels/design-system/Toast"
import styles from "./copybutton.module.css"
import type { CopyButtonProps } from "@/types/components/myPages/membership"
export default function CopyButton({ membershipNumber }: CopyButtonProps) {
const intl = useIntl()
function handleCopy() {
try {
navigator.clipboard.writeText(membershipNumber)
toast.success(
intl.formatMessage({
id: "myPages.membershipIdCopied",
defaultMessage: "Membership ID copied to clipboard",
})
)
} catch {
toast.error(
intl.formatMessage({
id: "errorMessage.copyFailed",
defaultMessage: "Failed to copy",
})
)
}
}
return (
<Button
onClick={handleCopy}
className={styles.button}
type="button"
variant="icon"
size="small"
intent="tertiary"
>
<MaterialIcon icon="content_copy" color="CurrentColor" />
</Button>
)
}

View File

@@ -1,6 +0,0 @@
.button {
display: flex;
justify-content: center;
align-items: center;
color: var(--Scandic-Brand-Pale-Peach);
}

View File

@@ -1,21 +0,0 @@
.hero {
border-radius: var(--Corner-radius-xl);
display: grid;
gap: var(--Spacing-x2);
grid-template-columns: 1fr;
padding: var(--Spacing-x7) var(--Spacing-x6);
}
.burgundy {
background-color: var(--Scandic-Brand-Burgundy);
}
.red {
background-color: var(--Scandic-Brand-Scandic-Red);
}
@media screen and (min-width: 768px) {
.hero {
grid-template-columns: 1fr 1fr;
}
}

View File

@@ -1,7 +0,0 @@
import type { VariantProps } from "class-variance-authority"
import type { heroVariants } from "./heroVariants"
export interface HeroProps
extends Omit<React.HTMLAttributes<HTMLDivElement>, "color">,
VariantProps<typeof heroVariants> {}

View File

@@ -1,15 +0,0 @@
import { cva } from "class-variance-authority"
import styles from "./hero.module.css"
export const heroVariants = cva(styles.hero, {
variants: {
color: {
burgundy: styles.burgundy,
red: styles.red,
},
},
defaultVariants: {
color: "red",
},
})

View File

@@ -1,8 +0,0 @@
import { heroVariants } from "./heroVariants"
import type { HeroProps } from "./hero"
export default function Hero({ className, color, children }: HeroProps) {
const classNames = heroVariants({ className, color })
return <section className={classNames}>{children}</section>
}

View File

@@ -1,44 +0,0 @@
import Caption from "@scandic-hotels/design-system/Caption"
import { getIntl } from "@/i18n"
import CopyButton from "../../Buttons/CopyButton"
import { membershipNumberVariants } from "./membershipNumberVariants"
import styles from "./membershipNumber.module.css"
import type { MembershipNumberProps } from "@/types/components/myPages/membershipNumber"
export default async function MembershipNumber({
className,
color,
membership,
}: MembershipNumberProps) {
const intl = await getIntl()
const classNames = membershipNumberVariants({ className, color })
return (
<div className={classNames}>
<Caption color="pale">
{intl.formatMessage({
id: "overview.membershipNumber.label",
defaultMessage: "Membership ID:",
})}
</Caption>
<span className={styles.icon}>
<Caption className={styles.icon} color="pale" asChild>
<code data-hj-suppress>
{membership?.membershipNumber ??
intl.formatMessage({
id: "common.NA",
defaultMessage: "N/A",
})}
</code>
</Caption>
{membership?.membershipNumber && (
<CopyButton membershipNumber={membership.membershipNumber} />
)}
</span>
</div>
)
}

View File

@@ -1,37 +0,0 @@
.membershipContainer {
align-items: center;
background: var(--Scandic-Brand-Burgundy);
border-radius: var(--Corner-radius-sm);
display: grid;
grid-template-columns: 1fr;
justify-items: center;
padding: var(--Spacing-x1) var(--Spacing-x2) 0;
}
.icon {
display: flex;
align-items: center;
flex-direction: row;
justify-content: center;
padding-left: var(--Spacing-x2);
}
.burgundy {
background-color: var(--Main-Brand-Burgundy);
}
.red {
background-color: var(--Scandic-Brand-Scandic-Red);
}
@media screen and (min-width: 768px) {
.membershipContainer {
grid-template-columns: auto auto;
padding: 0 0 0 var(--Spacing-x2);
gap: var(--Spacing-x-half);
}
.icon {
padding-left: 0;
}
}

View File

@@ -1,15 +0,0 @@
import { cva } from "class-variance-authority"
import styles from "./membershipNumber.module.css"
export const membershipNumberVariants = cva(styles.membershipContainer, {
variants: {
color: {
burgundy: styles.burgundy,
red: styles.red,
},
},
defaultVariants: {
color: "burgundy",
},
})

View File

@@ -1,41 +0,0 @@
.friend {
align-items: center;
display: flex;
flex-direction: column;
gap: var(--Spacing-x4);
justify-content: center;
}
.header {
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
}
.levelLabel {
position: relative;
transform: rotate(-13deg) translate(0px, -15px);
margin-left: -35px;
}
.friend .name {
text-align: center;
}
.membership {
align-items: center;
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
justify-content: center;
}
.membershipContainer {
align-items: center;
background: var(--Scandic-Brand-Burgundy);
border-radius: var(--Corner-radius-sm);
display: grid;
grid-template-columns: 1fr;
justify-items: center;
padding: var(--Spacing-x1) var(--Spacing-x7) 0 var(--Spacing-x7);
}

View File

@@ -1,56 +0,0 @@
import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels"
import Body from "@scandic-hotels/design-system/Body"
import Title from "@scandic-hotels/design-system/Title"
import { membershipLevels } from "@/constants/membershipLevels"
import MembershipLevelIcon from "@/components/Levels/Icon"
import { getIntl } from "@/i18n"
import { isHighestMembership } from "@/utils/user"
import styles from "./friend.module.css"
import type { FriendProps } from "@/types/components/myPages/friend"
export default async function Friend({
children,
membership,
name,
}: FriendProps) {
const intl = await getIntl()
if (!membership?.membershipLevel) {
return null
}
const isHighestLevel = isHighestMembership(membership.membershipLevel)
const lvlMessageHighest = intl.formatMessage({
id: "overview.friend.highestLevel",
defaultMessage: "Highest level",
})
const lvlMessageLevel = intl.formatMessage(
{ id: "common.membershipLevelWithValue", defaultMessage: "Level {level}" },
{ level: membershipLevels[membership.membershipLevel] }
)
return (
<section className={styles.friend}>
<header className={styles.header}>
<Body color="white" textTransform="bold" textAlign="center">
{isHighestLevel ? lvlMessageHighest : lvlMessageLevel}
</Body>
<MembershipLevelIcon
level={MembershipLevelEnum[membership.membershipLevel]}
height="110"
width="220"
/>
</header>
<div className={styles.membership}>
<Title data-hj-suppress className={styles.name} color="pale" level="h3">
{name}
</Title>
{children}
</div>
</section>
)
}

View File

@@ -1,40 +0,0 @@
import { Lang } from "@scandic-hotels/common/constants/language"
import { dt } from "@scandic-hotels/common/dt"
import Body from "@scandic-hotels/design-system/Body"
import { getFriendsMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import type { UserProps } from "@/types/components/myPages/user"
export default async function ExpiringPoints({ user }: UserProps) {
const intl = await getIntl()
const membership = user.loyalty ? getFriendsMembership(user.loyalty) : null
if (!membership || !membership.pointsToExpire) {
// TODO: handle this case?
return null
}
const d = dt(membership.pointsExpiryDate)
const lang = await getLang()
const dateFormat = lang == Lang.fi ? "DD.MM.YYYY" : "YYYY-MM-DD"
return (
<section>
<Body color="white" textTransform="bold" textAlign="center">
{intl.formatMessage(
{
id: "overview.stats.expiringPoints",
defaultMessage: "{points} spendable points expiring by {date}",
},
{
points: intl.formatNumber(membership.pointsToExpire),
date: d.format(dateFormat),
}
)}
</Body>
</section>
)
}

View File

@@ -1,13 +0,0 @@
.points {
display: grid;
gap: var(--Spacing-x5);
text-wrap: balance;
}
@media screen and (min-width: 768px) {
.points {
grid-auto-flow: column;
row-gap: 0;
column-gap: var(--Spacing-x2);
}
}

View File

@@ -1,5 +0,0 @@
import styles from "./container.module.css"
export default function PointsContainer({ children }: React.PropsWithChildren) {
return <section className={styles.points}>{children}</section>
}

View File

@@ -1,42 +0,0 @@
import Body from "@scandic-hotels/design-system/Body"
import Title from "@scandic-hotels/design-system/Title"
import { getIntl } from "@/i18n"
import styles from "./pointsColumn.module.css"
import type { PointsColumnProps } from "@/types/components/myPages/points"
export async function PointsColumn({
title,
subtitle,
value,
}: PointsColumnProps) {
const intl = await getIntl()
let number = "N/A"
if (typeof value === "number") {
number = intl.formatNumber(value)
}
return (
<article className={styles.article}>
<Body
color="white"
textTransform="bold"
textAlign="center"
className={styles.firstRow}
>
{title}
</Body>
<Title color="white" level="h2" textAlign="center">
{number}
</Title>
{subtitle ? (
<Body color="white" textAlign="center">
{subtitle}
</Body>
) : null}
</article>
)
}

View File

@@ -1,9 +0,0 @@
@media screen and (min-width: 768px) {
.firstRow {
align-content: flex-end;
}
.article {
display: grid;
}
}

View File

@@ -1,67 +0,0 @@
import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels"
import { getFriendsMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import { serverClient } from "@/lib/trpc/server"
import { getIntl } from "@/i18n"
import PointsContainer from "./Container"
import { PointsColumn } from "./PointsColumn"
import type { UserProps } from "@/types/components/myPages/user"
export default async function Points({ user }: UserProps) {
const intl = await getIntl()
const membership = user.loyalty ? getFriendsMembership(user.loyalty) : null
const caller = await serverClient()
const nextLevel =
membership?.nextLevel && MembershipLevelEnum[membership.nextLevel]
? await caller.contentstack.loyaltyLevels.byLevel({
level: MembershipLevelEnum[membership.nextLevel],
})
: null
return (
<PointsContainer>
<PointsColumn
value={membership?.currentPoints}
title={intl.formatMessage({
id: "stats.points.yourPointsToSpend",
defaultMessage: "Your points to spend",
})}
subtitle={intl.formatMessage({
id: "stats.points.asOfToday",
defaultMessage: "as of today",
})}
/>
{nextLevel && (
<PointsColumn
value={membership?.pointsRequiredToNextlevel}
title={intl.formatMessage({
id: "stats.points.pointsNeededToLevelUp",
defaultMessage: "Points needed to level up",
})}
subtitle={intl.formatMessage(
{
id: "stats.points.nextLevel",
defaultMessage: "next level: {nextLevel}",
},
{ nextLevel: nextLevel.name }
)}
/>
)}
{/* TODO: Show NextLevelNightsColumn when nightsToTopTier data is correct from Antavo */}
{/* {membership?.nightsToTopTier && (
<NextLevelNightsColumn
nights={membership.nightsToTopTier}
subtitle={
membership.tierExpirationDate &&
`by ${membership.tierExpirationDate}`
}
/>
)} */}
</PointsContainer>
)
}

View File

@@ -1,18 +0,0 @@
import { Divider } from "@scandic-hotels/design-system/Divider"
import ExpiringPoints from "./ExpiringPoints"
import Points from "./Points"
import styles from "./stats.module.css"
import type { UserProps } from "@/types/components/myPages/user"
export default function Stats({ user }: UserProps) {
return (
<section className={styles.stats}>
<Points user={user} />
<Divider color="pale" />
<ExpiringPoints user={user} />
</section>
)
}

View File

@@ -1,11 +0,0 @@
.stats {
align-content: center;
display: grid;
gap: var(--Spacing-x2);
}
@media screen and (min-width: 1367px) {
.stats {
gap: var(--Spacing-x4);
}
}

View File

@@ -1,4 +1,3 @@
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { env } from "@/env/server"
@@ -9,15 +8,11 @@ import DigitalTeamMemberCard from "@/components/MyPages/DigitalTeamMemberCard"
import DigitalTeamMemberCardAlert from "@/components/MyPages/DigitalTeamMemberCard/Alert"
import LevelProgressCard from "@/components/MyPages/LevelProgressCard"
import { Section } from "@/components/Section"
import SectionHeader from "@/components/Section/Header/Deprecated"
import { SectionHeader } from "@/components/Section/Header"
import SectionLink from "@/components/Section/Link"
import { getIntl } from "@/i18n"
import Hero from "./Friend/Hero"
import MembershipNumber from "./Friend/MembershipNumber"
import Friend from "./Friend"
import MembershipOverviewCard from "./MembershipOverviewCard"
import Stats from "./Stats"
import UserBaseInfo from "./UserBaseInfo"
import styles from "./overview.module.css"
@@ -40,9 +35,8 @@ export default async function Overview({
<DigitalTeamMemberCardAlert />
<SectionHeader
link={link}
preamble={subtitle}
title={title}
headingAs="h3"
preamble={subtitle ?? undefined}
heading={title ?? undefined}
headingLevel="h1"
/>
<DigitalTeamMemberCard user={user}>
@@ -61,23 +55,14 @@ export default async function Overview({
</>
</TeamMemberCardTrigger>
</DigitalTeamMemberCard>
{env.ENABLE_NEW_OVERVIEW_SECTION ? (
<>
<UserBaseInfo user={user} />
<div className={styles.membershipCardsContainer}>
<MembershipOverviewCard user={user} />
<LevelProgressCard user={user} />
</div>
</>
) : (
<Hero color="red">
<Friend membership={user.membership} name={user.name}>
<MembershipNumber color="burgundy" membership={user.membership} />
</Friend>
<Divider className={styles.divider} color="peach" />
<Stats user={user} />
</Hero>
)}
<>
<UserBaseInfo user={user} />
<div className={styles.membershipCardsContainer}>
<MembershipOverviewCard user={user} />
<LevelProgressCard user={user} />
</div>
</>
<SectionLink link={link} variant="mobile" />
</Section>

View File

@@ -1,6 +1,3 @@
import { Divider } from "@scandic-hotels/design-system/Divider"
import { env } from "@/env/server"
import { getProfile } from "@/lib/trpc/memoizedRequests"
import LevelProgressCard from "@/components/MyPages/LevelProgressCard"
@@ -8,10 +5,6 @@ import { Section } from "@/components/Section"
import SectionHeader from "@/components/Section/Header/Deprecated"
import SectionLink from "@/components/Section/Link"
import Friend from "../../Overview/Friend"
import Hero from "../../Overview/Friend/Hero"
import MembershipNumber from "../../Overview/Friend/MembershipNumber"
import Stats from "../../Overview/Stats"
import PointsToSpendCard from "../PointsToSpendCard"
import styles from "./overview.module.css"
@@ -37,23 +30,13 @@ export default async function PointsOverview({
headingAs={"h3"}
headingLevel={"h1"}
/>
{env.ENABLE_NEW_OVERVIEW_SECTION ? (
<div className={styles.membershipCardsContainer}>
<PointsToSpendCard user={user} />
<LevelProgressCard
color="Surface/Brand/Primary 1/Default"
user={user}
/>
</div>
) : (
<Hero color="burgundy">
<Friend membership={user.membership} name={user.name}>
<MembershipNumber color="red" membership={user.membership} />
</Friend>
<Divider className={styles.divider} color="peach" />
<Stats user={user} />
</Hero>
)}
<div className={styles.membershipCardsContainer}>
<PointsToSpendCard user={user} />
<LevelProgressCard
color="Surface/Brand/Primary 1/Default"
user={user}
/>
</div>
<SectionLink link={link} variant="mobile" />
</Section>
)

View File

@@ -152,11 +152,6 @@ export const env = createEnv({
.refine((s) => s === "1" || s === "0")
.transform((s) => s === "1")
.default("1"),
ENABLE_NEW_OVERVIEW_SECTION: z
.string()
.refine((s) => s === "true" || s === "false")
.transform((s) => s === "true")
.default("false"),
CHATBOT_LIVE_LANGS: z
.string()
.optional()
@@ -241,7 +236,6 @@ export const env = createEnv({
DTMC_ENTRA_ID_SECRET: process.env.DTMC_ENTRA_ID_SECRET,
HOTEL_BRANDING: process.env.HOTEL_BRANDING,
WEBVIEW_SHOW_OVERVIEW: process.env.WEBVIEW_SHOW_OVERVIEW,
ENABLE_NEW_OVERVIEW_SECTION: process.env.ENABLE_NEW_OVERVIEW_SECTION,
CHATBOT_LIVE_LANGS: process.env.CHATBOT_LIVE_LANGS,
},
})

View File

@@ -1,9 +0,0 @@
import type { User } from "@scandic-hotels/trpc/types/user"
import type { VariantProps } from "class-variance-authority"
import type { membershipNumberVariants } from "@/components/Blocks/DynamicContent/Overview/Friend/MembershipNumber/membershipNumberVariants"
export interface MembershipNumberProps
extends Omit<React.HTMLAttributes<HTMLDivElement>, "color">,
VariantProps<typeof membershipNumberVariants>,
Pick<User, "membership"> {}