From 0edd615925542af8f859b4b1de25166626dcf657 Mon Sep 17 00:00:00 2001 From: Chuma McPhoy Date: Mon, 9 Dec 2024 17:48:32 +0100 Subject: [PATCH] feat(LOY-62): Add ScriptedRewardText component --- .../Rewards/CurrentLevel/Client.tsx | 98 +++++++++++++++++++ .../Rewards/ScriptedRewardText/index.tsx | 56 +++++++++++ constants/membershipLevels.ts | 6 ++ i18n/dictionaries/da.json | 1 + i18n/dictionaries/de.json | 1 + i18n/dictionaries/en.json | 1 + i18n/dictionaries/fi.json | 1 + i18n/dictionaries/no.json | 1 + i18n/dictionaries/sv.json | 1 + server/routers/contentstack/reward/output.ts | 2 + server/routers/contentstack/reward/query.ts | 4 + .../components/myPages/myPage/accountPage.ts | 5 + 12 files changed, 177 insertions(+) create mode 100644 components/Blocks/DynamicContent/Rewards/CurrentLevel/Client.tsx create mode 100644 components/Blocks/DynamicContent/Rewards/ScriptedRewardText/index.tsx diff --git a/components/Blocks/DynamicContent/Rewards/CurrentLevel/Client.tsx b/components/Blocks/DynamicContent/Rewards/CurrentLevel/Client.tsx new file mode 100644 index 000000000..a9f6d4bd3 --- /dev/null +++ b/components/Blocks/DynamicContent/Rewards/CurrentLevel/Client.tsx @@ -0,0 +1,98 @@ +"use client" + +import { trpc } from "@/lib/trpc/client" +import { Reward } from "@/server/routers/contentstack/reward/output" + +import Image from "@/components/Image" +import LoadingSpinner from "@/components/LoadingSpinner" +import Grids from "@/components/TempDesignSystem/Grids" +import ShowMoreButton from "@/components/TempDesignSystem/ShowMoreButton" +import Title from "@/components/TempDesignSystem/Text/Title" +import useLang from "@/hooks/useLang" + +import ScriptedRewardText from "../ScriptedRewardText" +import Redeem from "./Redeem" + +import styles from "./current.module.css" + +import type { CurrentRewardsClientProps } from "@/types/components/myPages/myPage/accountPage" + +export default function ClientCurrentRewards({ + initialCurrentRewards, + showRedeem, +}: CurrentRewardsClientProps) { + const lang = useLang() + const { data, isFetching, fetchNextPage, hasNextPage, isLoading } = + trpc.contentstack.rewards.current.useInfiniteQuery( + { + limit: 3, + lang, + }, + { + getNextPageParam: (lastPage) => lastPage?.nextCursor, + initialData: { + pageParams: [undefined, 1], + pages: [initialCurrentRewards], + }, + } + ) + function loadMoreData() { + if (hasNextPage) { + fetchNextPage() + } + } + const filteredRewards = data?.pages.filter((page) => page?.rewards) ?? [] + const rewards = filteredRewards + .flatMap((page) => page?.rewards) + .filter((reward): reward is Reward => !!reward) + + if (isLoading) { + return + } + + if (!rewards.length) { + return null + } + + return ( +
+ + {rewards.map((reward, idx) => ( +
+
+ {reward.label + + + {reward.label} + +
+ {showRedeem && ( +
+ +
+ )} +
+ ))} +
+ {hasNextPage && + (isFetching ? ( + + ) : ( + + ))} +
+ ) +} diff --git a/components/Blocks/DynamicContent/Rewards/ScriptedRewardText/index.tsx b/components/Blocks/DynamicContent/Rewards/ScriptedRewardText/index.tsx new file mode 100644 index 000000000..8519d6737 --- /dev/null +++ b/components/Blocks/DynamicContent/Rewards/ScriptedRewardText/index.tsx @@ -0,0 +1,56 @@ +import { useIntl } from "react-intl" + +import { + isMembershipLevel, + MembershipLevelEnum, +} from "@/constants/membershipLevels" + +import BiroScript from "@/components/TempDesignSystem/Text/BiroScript" + +import type { ScriptedRewardTextProps } from "@/types/components/myPages/myPage/accountPage" + +const TIER_TO_FRIEND_MAP: Record = { + [MembershipLevelEnum.L1]: "New Friend", + [MembershipLevelEnum.L2]: "Good Friend", + [MembershipLevelEnum.L3]: "Close Friend", + [MembershipLevelEnum.L4]: "Dear Friend", + [MembershipLevelEnum.L5]: "Loyal Friend", + [MembershipLevelEnum.L6]: "True Friend", + [MembershipLevelEnum.L7]: "Best Friend", +} + +export default function ScriptedRewardText({ + rewardType, + rewardTierLevel, +}: ScriptedRewardTextProps) { + const intl = useIntl() + + let label: string | null = null + + switch (rewardType) { + case "Tier": + if (rewardTierLevel && isMembershipLevel(rewardTierLevel)) { + label = TIER_TO_FRIEND_MAP[rewardTierLevel] + } + break + + case "Campaign": + label = intl.formatMessage({ id: "Campaign" }) + break + + case "Surprise": + label = intl.formatMessage({ id: "Surprise!" }) + break + + // TODO: Add Voucher type + + default: + label = null + } + + return ( + + {label} + + ) +} diff --git a/constants/membershipLevels.ts b/constants/membershipLevels.ts index 3ae0f4650..19e8711db 100644 --- a/constants/membershipLevels.ts +++ b/constants/membershipLevels.ts @@ -18,4 +18,10 @@ export enum MembershipLevelEnum { L7 = "L7", } +export function isMembershipLevel(value: string): value is MembershipLevelEnum { + return Object.values(MembershipLevelEnum).includes( + value as MembershipLevelEnum + ) +} + export type MembershipLevel = keyof typeof MembershipLevelEnum diff --git a/i18n/dictionaries/da.json b/i18n/dictionaries/da.json index ace572018..5d9b23b30 100644 --- a/i18n/dictionaries/da.json +++ b/i18n/dictionaries/da.json @@ -73,6 +73,7 @@ "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.": "Ved at acceptere vilkårene og betingelserne for Scandic Friends, forstår jeg, at mine personlige oplysninger vil blive behandlet i overensstemmelse med Scandics privatlivspolitik.", "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "Ved at betale med en af de tilgængelige betalingsmetoder, accepterer jeg vilkårene for denne booking og de generelle Vilkår og betingelser, og forstår, at Scandic vil behandle min personlige data i forbindelse med denne booking i henhold til Scandics Privatlivspolitik. Jeg accepterer, at Scandic kræver et gyldigt kreditkort under min besøg i tilfælde af, at noget er tilbagebetalt.", "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service": "Ved at tilmelde dig accepterer du Scandic Friends vilkår og betingelser. Dit medlemskab er gyldigt indtil videre, og du kan til enhver tid opsige dit medlemskab ved at sende en e-mail til Scandics kundeservice", + "Campaign": "Kampagne", "Cancel": "Afbestille", "Change room": "Skift værelse", "Check in": "Check ind", diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json index 9f00e1a16..9ca951661 100644 --- a/i18n/dictionaries/de.json +++ b/i18n/dictionaries/de.json @@ -73,6 +73,7 @@ "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.": "Mit der Annahme der Allgemeinen Geschäftsbedingungen für Scandic Friends erkläre ich mich damit einverstanden, dass meine persönlichen Daten in Übereinstimmung mit der Datenschutzrichtlinie von Scandic verarbeitet werden.", "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "Mit der Zahlung über eine der verfügbaren Zahlungsmethoden akzeptiere ich die Buchungsbedingungen und die allgemeinen Geschäftsbedingungen und verstehe, dass Scandic meine personenbezogenen Daten im Zusammenhang mit dieser Buchung gemäß der Scandic Datenschutzrichtlinie verarbeitet. Ich akzeptiere, dass Scandic während meines Aufenthalts eine gültige Kreditkarte für eventuelle Rückerstattungen benötigt.", "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service": "Mit Ihrer Anmeldung akzeptieren Sie die Allgemeinen Geschäftsbedingungen von Scandic Friends. Ihre Mitgliedschaft ist bis auf Weiteres gültig und Sie können sie jederzeit kündigen, indem Sie eine E-Mail an den Kundenservice von Scandic senden.", + "Campaign": "Kampagne", "Cancel": "Stornieren", "Change room": "Zimmer ändern", "Check in": "Einchecken", diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json index 6044fa61c..b426c499c 100644 --- a/i18n/dictionaries/en.json +++ b/i18n/dictionaries/en.json @@ -76,6 +76,7 @@ "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.": "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.", "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.", "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service": "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service", + "Campaign": "Campaign", "Cancel": "Cancel", "Cancellation policy": "Cancellation policy", "Change room": "Change room", diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json index 4f1d96385..97cc5d414 100644 --- a/i18n/dictionaries/fi.json +++ b/i18n/dictionaries/fi.json @@ -73,6 +73,7 @@ "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.": "Kyllä, hyväksyn Scandic Friends -jäsenyyttä koskevat ehdot ja ymmärrän, että Scandic käsittelee henkilötietojani Scandicin Tietosuojaselosteen mukaisesti.", "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "Maksamalla minkä tahansa saatavilla olevan maksutavan avulla hyväksyn tämän varauksen ehdot ja yleiset ehdot ja ehtoja, ja ymmärrän, että Scandic käsittelee minun henkilötietoni tässä varauksessa mukaisesti Scandicin tietosuojavaltuuden mukaisesti. Hyväksyn myös, että Scandic vaatii validin luottokortin majoituksen ajan, jos jokin jää maksamatta.", "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service": "Rekisteröitymällä hyväksyt Scandic Friendsin käyttöehdot. Jäsenyytesi on voimassa toistaiseksi ja voit lopettaa jäsenyytesi milloin tahansa lähettämällä sähköpostia Scandicin asiakaspalveluun", + "Campaign": "Kampanja", "Cancel": "Peruuttaa", "Change room": "Vaihda huonetta", "Check in": "Sisäänkirjautuminen", diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json index d7251993c..df06db6b4 100644 --- a/i18n/dictionaries/no.json +++ b/i18n/dictionaries/no.json @@ -73,6 +73,7 @@ "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.": "Ved å akseptere vilkårene og betingelsene for Scandic Friends, er jeg inneforstått med at mine personopplysninger vil bli behandlet i samsvar med Scandics personvernpolicy.", "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "Ved å betale med en av de tilgjengelige betalingsmetodene godtar jeg vilkårene og betingelsene for denne bestillingen og de generelle vilkårene, og forstår at Scandic vil behandle mine personopplysninger i forbindelse med denne bestillingen i henhold til Scandics personvernpolicy. Jeg aksepterer at Scandic krever et gyldig kredittkort under mitt besøk i tilfelle noe blir refundert.", "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service": "Ved å registrere deg godtar du Scandic Friends vilkår og betingelser. Medlemskapet ditt er gyldig inntil videre, og du kan si opp medlemskapet ditt når som helst ved å sende en e-post til Scandics kundeservice", + "Campaign": "Kampanje", "Cancel": "Avbryt", "Change room": "Endre rom", "Check in": "Sjekk inn", diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json index c540c5167..807bae3d6 100644 --- a/i18n/dictionaries/sv.json +++ b/i18n/dictionaries/sv.json @@ -73,6 +73,7 @@ "By accepting the Terms and Conditions for Scandic Friends I understand that my personal data will be processed in accordance with Scandic's Privacy Policy.": "Genom att acceptera villkoren för Scandic Friends förstår jag att mina personuppgifter kommer att behandlas i enlighet med Scandics Integritetspolicy.", "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "Genom att betala med någon av de tillgängliga betalningsmetoderna accepterar jag villkoren för denna bokning och de generella Villkoren och villkoren, och förstår att Scandic kommer att behandla min personliga data i samband med denna bokning i enlighet med Scandics integritetspolicy. Jag accepterar att Scandic kräver ett giltigt kreditkort under min besök i fall att något är tillbaka betalt.", "By signing up you accept the Scandic Friends Terms and Conditions. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service": "Genom att registrera dig accepterar du Scandic Friends Användarvillkor. Ditt medlemskap gäller tills vidare och du kan när som helst säga upp ditt medlemskap genom att skicka ett mejl till Scandics kundtjänst", + "Campaign": "Kampanj", "Cancel": "Avbryt", "Change room": "Ändra rum", "Check in": "Checka in", diff --git a/server/routers/contentstack/reward/output.ts b/server/routers/contentstack/reward/output.ts index 50f315018..46cc27a47 100644 --- a/server/routers/contentstack/reward/output.ts +++ b/server/routers/contentstack/reward/output.ts @@ -166,6 +166,7 @@ export type Reward = CMSReward & { id: string | undefined rewardType: string | undefined redeemLocation: string | undefined + rewardTierLevel: string | undefined operaRewardId: string } @@ -173,6 +174,7 @@ export type RewardWithRedeem = CMSRewardWithRedeem & { id: string | undefined rewardType: string | undefined redeemLocation: string | undefined + rewardTierLevel: string | undefined operaRewardId: string } diff --git a/server/routers/contentstack/reward/query.ts b/server/routers/contentstack/reward/query.ts index f2e6e1ed9..202b148f1 100644 --- a/server/routers/contentstack/reward/query.ts +++ b/server/routers/contentstack/reward/query.ts @@ -257,6 +257,10 @@ export const rewardQueryRouter = router({ id: apiReward?.id, rewardType: apiReward?.rewardType, redeemLocation: apiReward?.redeemLocation, + rewardTierLevel: + apiReward && "rewardTierLevel" in apiReward + ? apiReward.rewardTierLevel + : undefined, operaRewardId: apiReward && "operaRewardId" in apiReward ? apiReward.operaRewardId diff --git a/types/components/myPages/myPage/accountPage.ts b/types/components/myPages/myPage/accountPage.ts index d545df0ce..c31ff522a 100644 --- a/types/components/myPages/myPage/accountPage.ts +++ b/types/components/myPages/myPage/accountPage.ts @@ -35,6 +35,11 @@ export interface RedeemProps { membershipNumber?: string | null } +export interface ScriptedRewardTextProps { + rewardType?: string + rewardTierLevel?: string +} + export type RedeemModalState = "unmounted" | "hidden" | "visible" export type RedeemStep = "initial" | "confirmation" | "redeemed"