Merged in revert-pr-1925 (pull request #1927)

Revert "Feat/sw 2323 find booking (pull request #1925)"

Approved-by: Anton Gunnarsson
This commit is contained in:
Linus Flood
2025-05-02 13:05:42 +00:00
parent 87efb72ff2
commit 6979ac0c3b
69 changed files with 883 additions and 1508 deletions

View File

@@ -145,7 +145,7 @@ export default function AddAncillaryFlowModal({
) {
addAncillary.mutate(
{
refId,
confirmationNumber: booking.confirmationNumber,
ancillaryComment: data.optionalText,
ancillaryDeliveryTime: selectedAncillary?.requiresDeliveryTime
? data.deliveryTime
@@ -175,8 +175,8 @@ export default function AddAncillaryFlowModal({
)
clearAncillarySessionData()
closeModal()
utils.booking.confirmation.invalidate({
refId: booking.refId,
utils.booking.get.invalidate({
confirmationNumber: booking.confirmationNumber,
})
router.refresh()
} else {
@@ -211,7 +211,7 @@ export default function AddAncillaryFlowModal({
}
: undefined
guaranteeBooking.mutate({
refId,
confirmationNumber: booking.confirmationNumber,
language: lang,
...(card && { card }),
success: `${guaranteeRedirectUrl}?status=success&RefId=${encodeURIComponent(refId)}&ancillary=1`,

View File

@@ -10,12 +10,12 @@ import { toast } from "@/components/TempDesignSystem/Toasts"
import useLang from "@/hooks/useLang"
export default function RemoveButton({
refId,
confirmationNumber,
codes,
title,
onSuccess,
}: {
refId: string
confirmationNumber: string
codes: string[]
title?: string
onSuccess: () => void
@@ -51,7 +51,7 @@ export default function RemoveButton({
removePackage.mutate(
{
language: lang,
refId,
confirmationNumber,
codes,
},
{

View File

@@ -25,7 +25,6 @@ import type {
export function AddedAncillaries({
ancillaries,
booking,
refId,
}: AddedAncillariesProps) {
const intl = useIntl()
const router = useRouter()
@@ -127,7 +126,7 @@ export function AddedAncillaries({
{booking.confirmationNumber && ancillary.code ? (
<div className={styles.actions}>
<RemoveButton
refId={refId}
confirmationNumber={booking.confirmationNumber}
codes={
ancillary.code ===
BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST
@@ -193,7 +192,7 @@ export function AddedAncillaries({
booking.canModifyAncillaries ? (
<div className={styles.actions}>
<RemoveButton
refId={refId}
confirmationNumber={booking.confirmationNumber}
codes={
ancillary.code ===
BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST

View File

@@ -20,12 +20,10 @@ import type { Lang } from "@/constants/languages"
export default function GuaranteeAncillaryHandler({
confirmationNumber,
refId,
returnUrl,
lang,
}: {
confirmationNumber: string
refId: string
returnUrl: string
lang: Lang
}) {
@@ -49,7 +47,7 @@ export default function GuaranteeAncillaryHandler({
addAncillary.mutate(
{
refId,
confirmationNumber,
ancillaryComment: formData.optionalText,
ancillaryDeliveryTime: selectedAncillary.requiresDeliveryTime
? formData.deliveryTime
@@ -88,7 +86,7 @@ export default function GuaranteeAncillaryHandler({
},
}
)
}, [confirmationNumber, refId, returnUrl, addAncillary, lang, router])
}, [confirmationNumber, returnUrl, addAncillary, lang, router])
return <LoadingSpinner />
}

View File

@@ -213,11 +213,7 @@ export function Ancillaries({
</>
)}
<AddedAncillaries
booking={booking}
ancillaries={uniqueAncillaries}
refId={refId}
/>
<AddedAncillaries booking={booking} ancillaries={uniqueAncillaries} />
<AncillaryFlowModalWrapper>
<AddAncillaryFlowModal

View File

@@ -64,10 +64,10 @@ export default function Details({ booking, user }: DetailsProps) {
const updateGuest = trpc.booking.update.useMutation({
onMutate: () => setIsLoading(true),
onSuccess: (refId) => {
if (refId) {
utils.booking.confirmation.invalidate({
refId,
onSuccess: (data) => {
if (data) {
utils.booking.get.invalidate({
confirmationNumber: data.confirmationNumber,
})
toast.success(
@@ -99,7 +99,7 @@ export default function Details({ booking, user }: DetailsProps) {
async function onSubmit(data: ModifyContactSchema) {
updateGuest.mutate({
refId: booking.refId,
confirmationNumber: booking.confirmationNumber,
guest: {
email: data.email,
phoneNumber: data.phoneNumber,

View File

@@ -1,5 +1,4 @@
"use client"
import { useMyStayStore } from "@/stores/my-stay"
import Details from "./Details"

View File

@@ -0,0 +1,168 @@
import { cookies } from "next/headers"
import { notFound } from "next/navigation"
import ScandicLogoIcon from "@scandic-hotels/design-system/Icons/ScandicLogoIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { dt } from "@/lib/dt"
import {
getAncillaryPackages,
getBookingConfirmation,
getProfileSafely,
} from "@/lib/trpc/memoizedRequests"
import { decrypt } from "@/server/routers/utils/encryption"
import { getIntl } from "@/i18n"
import AdditionalInfoForm from "../../FindMyBooking/AdditionalInfoForm"
import accessBooking, {
ACCESS_GRANTED,
ERROR_BAD_REQUEST,
ERROR_UNAUTHORIZED,
} from "../accessBooking"
import Footer from "./Footer"
import Specification from "./Specification"
import Total from "./Total"
import styles from "./receipt.module.css"
import { CurrencyEnum } from "@/types/enums/currency"
export async function Receipt({ refId }: { refId: string }) {
const value = decrypt(refId)
if (!value) {
return notFound()
}
const [confirmationNumber, lastName] = value.split(",")
const bookingConfirmation = await getBookingConfirmation(confirmationNumber)
if (!bookingConfirmation) {
return notFound()
}
const { booking, hotel, room } = bookingConfirmation
const user = await getProfileSafely()
const bv = cookies().get("bv")?.value
const intl = await getIntl()
const access = accessBooking(booking.guest, lastName, user, bv)
if (access === ACCESS_GRANTED) {
const ancillaryPackages = await getAncillaryPackages({
fromDate: dt(booking.checkInDate).format("YYYY-MM-DD"),
hotelId: hotel.operaId,
toDate: dt(booking.checkOutDate).format("YYYY-MM-DD"),
})
const currency =
booking.currencyCode !== CurrencyEnum.POINTS
? booking.currencyCode
: (booking.ancillaries.find((a) => a.currency !== CurrencyEnum.POINTS)
?.currency ??
booking.packages.find((p) => p.currency !== CurrencyEnum.POINTS)
?.currency)
return (
<main className={styles.main}>
<div>
<ScandicLogoIcon width="89px" height="19px" color="Icon/Accent" />
<div className={styles.addresses}>
<div>
<Typography variant="Body/Supporting text (caption)/smRegular">
<div>{hotel.name}</div>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<div>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${hotel.address.streetAddress}, ${hotel.address.zipCode} ${hotel.address.city}`}
</div>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<div className={`${styles.tertiary} ${styles.addressMargin}`}>
{hotel.contactInformation.email}
</div>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<div className={styles.tertiary}>
{hotel.contactInformation.phoneNumber}
</div>
</Typography>
</div>
<div className={styles.rightColumn}>
<Typography variant="Body/Supporting text (caption)/smRegular">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<div>{`${booking.guest.firstName} ${booking.guest.lastName}`}</div>
</Typography>
{booking.guest.membershipNumber && (
<Typography variant="Body/Supporting text (caption)/smRegular">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<div>{`${intl.formatMessage({
defaultMessage: "Member",
})} ${booking.guest.membershipNumber}`}</div>
</Typography>
)}
<Typography variant="Body/Supporting text (caption)/smRegular">
<div className={`${styles.tertiary} ${styles.addressMargin}`}>
{booking.guest.email}
</div>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<div className={styles.tertiary}>
{booking.guest.phoneNumber}
</div>
</Typography>
</div>
</div>
</div>
<Total booking={booking} currency={currency} />
<Specification
ancillaryPackages={ancillaryPackages}
booking={booking}
currency={currency}
/>
<hr className={styles.divider} />
<Footer booking={booking} room={room} />
</main>
)
}
if (access === ERROR_BAD_REQUEST) {
return (
<main className={styles.main}>
<div className={styles.form}>
<AdditionalInfoForm
confirmationNumber={confirmationNumber}
lastName={lastName}
/>
</div>
</main>
)
}
if (access === ERROR_UNAUTHORIZED) {
return (
<main className={styles.main}>
<div className={styles.logIn}>
<Typography variant="Title/md">
<h1>
{intl.formatMessage({
defaultMessage: "You need to be logged in to view your booking",
})}
</h1>
</Typography>
<Typography variant="Body/Lead text">
<p>
{intl.formatMessage({
defaultMessage:
"And you need to be logged in with the same member account that made the booking.",
})}
</p>
</Typography>
</div>
</main>
)
}
return notFound()
}

View File

@@ -0,0 +1,45 @@
.main {
background-color: var(--Base-Surface-Primary-light-Normal);
display: flex;
padding: var(--Spacing-x5) var(--Spacing-x4);
flex-direction: column;
gap: var(--Spacing-x5);
}
.addresses {
display: flex;
justify-content: space-between;
margin-top: var(--Spacing-x2);
}
.rightColumn {
text-align: right;
}
.addressMargin {
margin-top: var(--Spacing-x-half);
}
.tertiary {
color: var(--Text-Tertiary);
}
.divider {
color: var(--Border-Divider-Accent);
}
.form {
max-width: 640px;
margin-left: auto;
margin-right: auto;
padding: var(--Spacing-x5) 0;
}
.logIn {
padding: var(--Spacing-x9) var(--Spacing-x2);
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
align-items: center;
color: var(--Scandic-Grey-100);
}

View File

@@ -57,7 +57,7 @@ export default function FinalConfirmation({
)
} else {
const cancelledRooms = rooms.filter((r) =>
variables.refIds.includes(r.refId)
variables.confirmationNumbers.includes(r.confirmationNumber)
)
for (const cancelledRoom of cancelledRooms) {
toast.success(
@@ -93,16 +93,13 @@ export default function FinalConfirmation({
)
}
utils.booking.confirmation.invalidate({
refId: bookedRoom.refId,
lang,
utils.booking.get.invalidate({
confirmationNumber: bookedRoom.confirmationNumber,
})
utils.booking.linkedReservations.invalidate({
refId: bookedRoom.refId,
lang,
rooms: bookedRoom.linkedReservations,
})
closeModal()
},
onError() {
@@ -116,13 +113,13 @@ export default function FinalConfirmation({
function cancelBooking() {
if (Array.isArray(formRooms)) {
const refIdsToCancel = formRooms
const confirmationNumbersToCancel = formRooms
.filter((r) => r.checked)
.map((r) => r.confirmationNumber)
if (refIdsToCancel.length) {
if (confirmationNumbersToCancel.length) {
cancelBookingsMutation.mutate({
refIds: refIdsToCancel,
lang,
confirmationNumbers: confirmationNumbersToCancel,
language: lang,
})
}
} else {

View File

@@ -54,10 +54,10 @@ export default function Confirmation({
)
const updateBooking = trpc.booking.update.useMutation({
onSuccess: (refId) => {
if (refId) {
utils.booking.confirmation.invalidate({
refId,
onSuccess: (updatedBooking) => {
if (updatedBooking) {
utils.booking.get.invalidate({
confirmationNumber: updatedBooking.confirmationNumber,
})
toast.success(
@@ -86,7 +86,7 @@ export default function Confirmation({
function handleModifyStay() {
updateBooking.mutate({
refId: bookedRoom.refId,
confirmationNumber: bookedRoom.confirmationNumber,
checkInDate,
checkOutDate,
})

View File

@@ -60,7 +60,7 @@ export default function Form() {
const guaranteeRedirectUrl = `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}${guaranteeCallback(lang)}`
const { guaranteeBooking, isLoading, handleGuaranteeError } =
useGuaranteeBooking(refId, false, hotelId)
useGuaranteeBooking(confirmationNumber, false, hotelId)
if (isLoading) {
return (
@@ -85,7 +85,7 @@ export default function Form() {
: undefined
writeGlaToSessionStorage("yes", hotelId)
guaranteeBooking.mutate({
refId,
confirmationNumber,
language: lang,
...(card && { card }),
success: `${guaranteeRedirectUrl}?status=success&RefId=${encodeURIComponent(refId)}`,

View File

@@ -143,7 +143,6 @@ export function mapRoomDetails({
priceType,
rate,
rateDefinition: booking.rateDefinition,
refId: booking.refId,
reservationStatus: booking.reservationStatus,
room,
roomName: room?.name ?? "",