203 lines
6.7 KiB
TypeScript
203 lines
6.7 KiB
TypeScript
"use client"
|
||
import { usePathname, useSearchParams } from "next/navigation"
|
||
import { useState } from "react"
|
||
import { useIntl } from "react-intl"
|
||
|
||
import { serializeBookingSearchParams } from "@scandic-hotels/booking-flow/utils/url"
|
||
import { BOOK_NOW_SESSION_KEY } from "@scandic-hotels/common/constants/sessionKeys"
|
||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||
import { LinkList } from "@scandic-hotels/design-system/LinkList"
|
||
import { MessageBanner } from "@scandic-hotels/design-system/MessageBanner"
|
||
import Modal from "@scandic-hotels/design-system/Modal"
|
||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||
import { trackClick, trackEvent } from "@scandic-hotels/tracking/base"
|
||
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
|
||
|
||
import { rewardNightsURL } from "@/constants/rewards"
|
||
|
||
import InfoCard from "@/components/ContentType/StartPage/InfoCard"
|
||
|
||
import { UsePointsButton } from "./UsePointsButton"
|
||
|
||
import styles from "./UsePoints.module.css"
|
||
|
||
import type { ButtonProps } from "@scandic-hotels/design-system/Button"
|
||
import type { UsePointsModalData } from "@scandic-hotels/trpc/routers/contentstack/UsePointsModal/output"
|
||
|
||
function trackButtonClick(label: string) {
|
||
trackClick(label)
|
||
if (label === "book now") {
|
||
sessionStorage.setItem(BOOK_NOW_SESSION_KEY, "true")
|
||
}
|
||
}
|
||
|
||
function trackLinkListClick(linkText: string) {
|
||
if (!linkText) return
|
||
trackEvent({
|
||
event: "linkClick",
|
||
link: { name: linkText },
|
||
})
|
||
}
|
||
|
||
type UsePointsModalProps = {
|
||
buttonVariant: ButtonProps["variant"]
|
||
contentData: UsePointsModalData
|
||
points: number
|
||
className?: string
|
||
}
|
||
|
||
export function UsePointsModal({
|
||
buttonVariant,
|
||
contentData,
|
||
points,
|
||
className,
|
||
}: UsePointsModalProps) {
|
||
const intl = useIntl()
|
||
const [isOpen, setIsOpen] = useState(false)
|
||
const pathname = usePathname()
|
||
const initialSearchParams = useSearchParams()
|
||
|
||
const searchParams = serializeBookingSearchParams(
|
||
{
|
||
searchType: SEARCH_TYPE_REDEMPTION,
|
||
focusWidget: true,
|
||
},
|
||
{ initialSearchParams }
|
||
)
|
||
|
||
const bookLink = `${pathname}?${searchParams}`
|
||
|
||
const [items] = contentData.all_usepointsmodal.items
|
||
|
||
const linkListItems = items.link_group.map((link) => ({
|
||
text: link.text,
|
||
isExternal: link.isExternal,
|
||
href: link.href,
|
||
illustration: link.illustration,
|
||
onClick: () => trackLinkListClick(link.text),
|
||
}))
|
||
|
||
return (
|
||
<>
|
||
<UsePointsButton
|
||
variant={buttonVariant}
|
||
onPress={() => {
|
||
setIsOpen(true)
|
||
trackButtonClick("use points")
|
||
}}
|
||
className={className}
|
||
/>
|
||
<Modal isOpen={isOpen} onToggle={setIsOpen} withActions>
|
||
<div className={styles.modalContent}>
|
||
<div className={styles.header}>
|
||
<Typography variant="Tag/sm">
|
||
<p className={styles.pointsText}>
|
||
{intl.formatMessage({
|
||
id: "myPages.membershipPoints.youHave",
|
||
defaultMessage: "You have",
|
||
})}
|
||
</p>
|
||
</Typography>
|
||
<div className={styles.points}>
|
||
<Typography variant="Title/lg">
|
||
<p className={styles.pointsNumber}>
|
||
{intl.formatNumber(points)}
|
||
</p>
|
||
</Typography>
|
||
<Typography variant="Tag/sm">
|
||
<p className={styles.pointsText}>
|
||
{intl.formatMessage({
|
||
id: "myPages.membershipPoints.pointsToSpend",
|
||
defaultMessage: "points to spend",
|
||
})}
|
||
</p>
|
||
</Typography>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
{points >= 10000 ? (
|
||
<InfoCard
|
||
image={items.image}
|
||
heading={intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.headingAboveThreshold",
|
||
defaultMessage: "You’ve earned a night away",
|
||
})}
|
||
bodyText={intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.bodytext",
|
||
defaultMessage: "Reward nights start at 10,000 points",
|
||
})}
|
||
primaryButton={{
|
||
href: bookLink,
|
||
title: intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.bookNow",
|
||
defaultMessage: "Book now",
|
||
}),
|
||
forceReload: true,
|
||
}}
|
||
secondaryButton={{
|
||
href: rewardNightsURL,
|
||
title: intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.priceList",
|
||
defaultMessage: "Price list",
|
||
}),
|
||
openInNewTab: true,
|
||
materialIcon: (
|
||
<MaterialIcon
|
||
icon="open_in_new"
|
||
color="CurrentColor"
|
||
size={20}
|
||
/>
|
||
),
|
||
}}
|
||
onPrimaryButtonClick={() => trackButtonClick("book now")}
|
||
onSecondaryButtonClick={() => trackButtonClick("price list")}
|
||
theme="primaryDark"
|
||
imagePosition="top"
|
||
height="dynamic"
|
||
></InfoCard>
|
||
) : (
|
||
<InfoCard
|
||
heading={intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.headingBelowThreshold",
|
||
defaultMessage:
|
||
"Earn at least 10 000 points for a reward night",
|
||
})}
|
||
secondaryButton={{
|
||
href: rewardNightsURL,
|
||
title: intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.priceList",
|
||
defaultMessage: "Price list",
|
||
}),
|
||
openInNewTab: true,
|
||
materialIcon: (
|
||
<MaterialIcon
|
||
icon="open_in_new"
|
||
color="CurrentColor"
|
||
size={20}
|
||
/>
|
||
),
|
||
}}
|
||
onSecondaryButtonClick={() => trackButtonClick("price list")}
|
||
theme="primaryDark"
|
||
imagePosition="top"
|
||
height="dynamic"
|
||
></InfoCard>
|
||
)}
|
||
</div>
|
||
<div>
|
||
<LinkList linkListItems={linkListItems}></LinkList>
|
||
</div>
|
||
<MessageBanner
|
||
type="info"
|
||
text={intl.formatMessage({
|
||
id: "myPages.membershipPointsModal.infoBanner",
|
||
defaultMessage:
|
||
"Spending points do not affect your level progress.",
|
||
})}
|
||
/>
|
||
</div>
|
||
</Modal>
|
||
</>
|
||
)
|
||
}
|