Merged in feat/my-stay-masking (pull request #2116)

Mask values on my-stay and receipt pages SW-2788

* Mask values on my-stay and receipt pages


Approved-by: Joakim Jäderberg
This commit is contained in:
Linus Flood
2025-05-16 09:30:04 +00:00
committed by Joakim Jäderberg
parent f49a13512a
commit 96821c7a6f
3 changed files with 85 additions and 17 deletions

View File

@@ -34,6 +34,7 @@ import Image from "@/components/Image"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext" import { setLang } from "@/i18n/serverContext"
import MyStayProvider from "@/providers/MyStay" import MyStayProvider from "@/providers/MyStay"
import * as maskValue from "@/utils/maskValue"
import { parseRefId } from "@/utils/refId" import { parseRefId } from "@/utils/refId"
import { isValidSession } from "@/utils/session" import { isValidSession } from "@/utils/session"
import { getCurrentWebUrl } from "@/utils/url" import { getCurrentWebUrl } from "@/utils/url"
@@ -42,6 +43,8 @@ import styles from "./page.module.css"
import { BreakfastPackageEnum } from "@/types/enums/breakfast" import { BreakfastPackageEnum } from "@/types/enums/breakfast"
import type { LangParams, PageArgs } from "@/types/params" import type { LangParams, PageArgs } from "@/types/params"
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
import type { SafeUser } from "@/types/user"
export default async function MyStay({ export default async function MyStay({
params, params,
@@ -174,9 +177,31 @@ export default async function MyStay({
promoUrl.searchParams.set("hotel", hotel.operaId) promoUrl.searchParams.set("hotel", hotel.operaId)
const maskedBookingConfirmation = {
...bookingConfirmation,
booking: {
...bookingConfirmation.booking,
guest: {
...bookingConfirmation.booking.guest,
email: maskValue.email(bookingConfirmation.booking.guest.email),
phoneNumber: maskValue.phone(
bookingConfirmation.booking.guest.phoneNumber ?? ""
),
},
},
} satisfies BookingConfirmation
const maskedUser = user
? ({
...user,
email: maskValue.email(user.email),
phoneNumber: maskValue.phone(user.phoneNumber ?? ""),
} satisfies SafeUser)
: null
return ( return (
<MyStayProvider <MyStayProvider
bookingConfirmation={bookingConfirmation} bookingConfirmation={maskedBookingConfirmation}
breakfastPackages={breakfastPackages} breakfastPackages={breakfastPackages}
lang={params.lang} lang={params.lang}
linkedReservationsPromise={linkedReservationsPromise} linkedReservationsPromise={linkedReservationsPromise}
@@ -205,13 +230,13 @@ export default async function MyStay({
<Ancillaries <Ancillaries
ancillariesPromise={ancillaryPackagesPromise} ancillariesPromise={ancillaryPackagesPromise}
packages={breakfastPackages} packages={breakfastPackages}
user={user} user={maskedUser}
savedCreditCards={savedCreditCards} savedCreditCards={savedCreditCards}
/> />
)} )}
<SingleRoom user={user} /> <SingleRoom user={maskedUser} />
<MultiRoom user={user} /> <MultiRoom user={maskedUser} />
<BookingSummary hotel={hotel} /> <BookingSummary hotel={hotel} />
<Promo <Promo

View File

@@ -34,6 +34,7 @@ import Image from "@/components/Image"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext" import { setLang } from "@/i18n/serverContext"
import MyStayProvider from "@/providers/MyStay" import MyStayProvider from "@/providers/MyStay"
import * as maskValue from "@/utils/maskValue"
import { parseRefId } from "@/utils/refId" import { parseRefId } from "@/utils/refId"
import { isValidSession } from "@/utils/session" import { isValidSession } from "@/utils/session"
import { getCurrentWebUrl } from "@/utils/url" import { getCurrentWebUrl } from "@/utils/url"
@@ -42,6 +43,8 @@ import styles from "./page.module.css"
import { BreakfastPackageEnum } from "@/types/enums/breakfast" import { BreakfastPackageEnum } from "@/types/enums/breakfast"
import type { LangParams, PageArgs } from "@/types/params" import type { LangParams, PageArgs } from "@/types/params"
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
import type { SafeUser } from "@/types/user"
export default async function MyStay({ export default async function MyStay({
params, params,
@@ -175,11 +178,33 @@ export default async function MyStay({
? new URL(getCurrentWebUrl({ path: "/", lang })) ? new URL(getCurrentWebUrl({ path: "/", lang }))
: new URL(`${baseUrl}/${lang}/`) : new URL(`${baseUrl}/${lang}/`)
const maskedBookingConfirmation = {
...bookingConfirmation,
booking: {
...bookingConfirmation.booking,
guest: {
...bookingConfirmation.booking.guest,
email: maskValue.email(bookingConfirmation.booking.guest.email),
phoneNumber: maskValue.phone(
bookingConfirmation.booking.guest.phoneNumber ?? ""
),
},
},
} satisfies BookingConfirmation
const maskedUser = user
? ({
...user,
email: maskValue.email(user.email),
phoneNumber: maskValue.phone(user.phoneNumber ?? ""),
} satisfies SafeUser)
: null
promoUrl.searchParams.set("hotel", hotel.operaId) promoUrl.searchParams.set("hotel", hotel.operaId)
return ( return (
<MyStayProvider <MyStayProvider
bookingConfirmation={bookingConfirmation} bookingConfirmation={maskedBookingConfirmation}
breakfastPackages={breakfastPackages} breakfastPackages={breakfastPackages}
lang={params.lang} lang={params.lang}
linkedReservationsPromise={linkedReservationsPromise} linkedReservationsPromise={linkedReservationsPromise}
@@ -208,13 +233,13 @@ export default async function MyStay({
<Ancillaries <Ancillaries
ancillariesPromise={ancillaryPackagesPromise} ancillariesPromise={ancillaryPackagesPromise}
packages={breakfastPackages} packages={breakfastPackages}
user={user} user={maskedUser}
savedCreditCards={savedCreditCards} savedCreditCards={savedCreditCards}
/> />
)} )}
<SingleRoom user={user} /> <SingleRoom user={maskedUser} />
<MultiRoom user={user} /> <MultiRoom user={maskedUser} />
<BookingSummary hotel={hotel} /> <BookingSummary hotel={hotel} />
<Promo <Promo

View File

@@ -14,6 +14,7 @@ import {
import { auth } from "@/auth" import { auth } from "@/auth"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import * as maskValue from "@/utils/maskValue"
import { parseRefId } from "@/utils/refId" import { parseRefId } from "@/utils/refId"
import { isValidSession } from "@/utils/session" import { isValidSession } from "@/utils/session"
@@ -30,6 +31,7 @@ import Total from "./Total"
import styles from "./receipt.module.css" import styles from "./receipt.module.css"
import { CurrencyEnum } from "@/types/enums/currency" import { CurrencyEnum } from "@/types/enums/currency"
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
export async function Receipt({ refId }: { refId: string }) { export async function Receipt({ refId }: { refId: string }) {
const { confirmationNumber, lastName } = parseRefId(refId) const { confirmationNumber, lastName } = parseRefId(refId)
@@ -77,7 +79,7 @@ export async function Receipt({ refId }: { refId: string }) {
return notFound() return notFound()
} }
const { booking, hotel, room } = bookingConfirmation const { hotel, room, booking } = bookingConfirmation
const user = await getProfileSafely() const user = await getProfileSafely()
const intl = await getIntl() const intl = await getIntl()
@@ -98,6 +100,22 @@ export async function Receipt({ refId }: { refId: string }) {
booking.packages.find((p) => p.currency !== CurrencyEnum.POINTS) booking.packages.find((p) => p.currency !== CurrencyEnum.POINTS)
?.currency) ?.currency)
const maskedBookingConfirmation = {
...bookingConfirmation,
booking: {
...bookingConfirmation.booking,
guest: {
...bookingConfirmation.booking.guest,
email: maskValue.email(bookingConfirmation.booking.guest.email),
phoneNumber: maskValue.phone(
bookingConfirmation.booking.guest.phoneNumber ?? ""
),
},
},
} satisfies BookingConfirmation
const { booking: maskedBooking } = maskedBookingConfirmation
return ( return (
<main className={styles.main}> <main className={styles.main}>
<div> <div>
@@ -127,39 +145,39 @@ export async function Receipt({ refId }: { refId: string }) {
<div className={styles.rightColumn}> <div className={styles.rightColumn}>
<Typography variant="Body/Supporting text (caption)/smRegular"> <Typography variant="Body/Supporting text (caption)/smRegular">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<div>{`${booking.guest.firstName} ${booking.guest.lastName}`}</div> <div>{`${maskedBooking.guest.firstName} ${maskedBooking.guest.lastName}`}</div>
</Typography> </Typography>
{booking.guest.membershipNumber && ( {maskedBooking.guest.membershipNumber && (
<Typography variant="Body/Supporting text (caption)/smRegular"> <Typography variant="Body/Supporting text (caption)/smRegular">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<div>{`${intl.formatMessage({ <div>{`${intl.formatMessage({
defaultMessage: "Member", defaultMessage: "Member",
})} ${booking.guest.membershipNumber}`}</div> })} ${maskedBooking.guest.membershipNumber}`}</div>
</Typography> </Typography>
)} )}
<Typography variant="Body/Supporting text (caption)/smRegular"> <Typography variant="Body/Supporting text (caption)/smRegular">
<div className={`${styles.tertiary} ${styles.addressMargin}`}> <div className={`${styles.tertiary} ${styles.addressMargin}`}>
{booking.guest.email} {maskedBooking.guest.email}
</div> </div>
</Typography> </Typography>
<Typography variant="Body/Supporting text (caption)/smRegular"> <Typography variant="Body/Supporting text (caption)/smRegular">
<div className={styles.tertiary}> <div className={styles.tertiary}>
{booking.guest.phoneNumber} {maskedBooking.guest.phoneNumber}
</div> </div>
</Typography> </Typography>
</div> </div>
</div> </div>
</div> </div>
<Total booking={booking} currency={currency} /> <Total booking={maskedBooking} currency={currency} />
<Specification <Specification
ancillaryPackages={ancillaryPackages} ancillaryPackages={ancillaryPackages}
booking={booking} booking={maskedBooking}
currency={currency} currency={currency}
/> />
<hr className={styles.divider} /> <hr className={styles.divider} />
<Footer booking={booking} room={room} /> <Footer booking={maskedBooking} room={room} />
</main> </main>
) )
} }