Merged in feat/SW-2308-family-friends-booking-rest (pull request #1916)
feat: SW-2308 FnF code restriction added * feat: SW-2308 FnF code restriction added * feat: 2308 Optimized code Approved-by: Niclas Edenvin
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { cookies } from "next/headers"
|
||||
import { notFound, redirect } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { BookingErrorCodeEnum } from "@/constants/booking"
|
||||
import { FamilyAndFriendsCodes } from "@/constants/booking"
|
||||
import { selectRate } from "@/constants/routes/hotelReservation"
|
||||
import {
|
||||
getBreakfastPackages,
|
||||
@@ -17,6 +19,7 @@ import RoomOne from "@/components/HotelReservation/EnterDetails/Room/One"
|
||||
import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/Desktop"
|
||||
import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile"
|
||||
import EnterDetailsTrackingWrapper from "@/components/HotelReservation/EnterDetails/Tracking"
|
||||
import FnFNotAllowedAlert from "@/components/HotelReservation/FnFNotAllowedAlert/FnFNotAllowedAlert"
|
||||
import RoomProvider from "@/providers/Details/RoomProvider"
|
||||
import EnterDetailsProvider from "@/providers/EnterDetailsProvider"
|
||||
import { convertSearchParamsToObj } from "@/utils/url"
|
||||
@@ -38,6 +41,18 @@ export default async function DetailsPage({
|
||||
delete booking.modifyRateIndex
|
||||
}
|
||||
|
||||
if (
|
||||
booking.bookingCode &&
|
||||
FamilyAndFriendsCodes.includes(booking.bookingCode)
|
||||
) {
|
||||
const cookieStore = cookies()
|
||||
const isInValidFNF = cookieStore.get("sc")?.value !== "1"
|
||||
|
||||
if (isInValidFNF) {
|
||||
return <FnFNotAllowedAlert />
|
||||
}
|
||||
}
|
||||
|
||||
const breakfastInput = {
|
||||
adults: 1,
|
||||
fromDate: booking.fromDate,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.fnfMain {
|
||||
max-width: var(--max-width-page);
|
||||
margin: auto;
|
||||
min-height: 30dvh;
|
||||
padding: var(--Spacing-x5) 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import Alert from "@/components/TempDesignSystem/Alert"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./FnFNotAllowedAlert.module.css"
|
||||
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
|
||||
export default async function FnFNotAllowedAlert() {
|
||||
const intl = await getIntl()
|
||||
|
||||
return (
|
||||
<div className={styles.fnfMain}>
|
||||
<Alert
|
||||
type={AlertTypeEnum.Warning}
|
||||
text={intl.formatMessage({
|
||||
defaultMessage:
|
||||
"The Friends & Family rate can only be booked via FUSE.",
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import stringify from "json-stable-stringify-without-jsonify"
|
||||
import { cookies } from "next/headers"
|
||||
import { notFound } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import { FamilyAndFriendsCodes } from "@/constants/booking"
|
||||
import {
|
||||
alternativeHotels,
|
||||
alternativeHotelsMap,
|
||||
@@ -21,6 +23,7 @@ import { getIntl } from "@/i18n"
|
||||
import { getHotelSearchDetails } from "@/utils/hotelSearchDetails"
|
||||
import { convertObjToSearchParams } from "@/utils/url"
|
||||
|
||||
import FnFNotAllowedAlert from "../FnFNotAllowedAlert/FnFNotAllowedAlert"
|
||||
import HotelCardListing from "../HotelCardListing"
|
||||
import BookingCodeFilter from "./BookingCodeFilter"
|
||||
import { getFiltersFromHotels, getHotels } from "./helpers"
|
||||
@@ -67,6 +70,15 @@ export default async function SelectHotel({
|
||||
|
||||
if (!city) return notFound()
|
||||
|
||||
if (bookingCode && FamilyAndFriendsCodes.includes(bookingCode)) {
|
||||
const cookieStore = cookies()
|
||||
const isInValidFNF = cookieStore.get("sc")?.value !== "1"
|
||||
|
||||
if (isInValidFNF) {
|
||||
return <FnFNotAllowedAlert />
|
||||
}
|
||||
}
|
||||
|
||||
const hotels = await getHotels(
|
||||
selectHotelParams,
|
||||
isAlternativeFor,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import stringify from "json-stable-stringify-without-jsonify"
|
||||
import { cookies } from "next/headers"
|
||||
import { notFound } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { REDEMPTION } from "@/constants/booking"
|
||||
import { FamilyAndFriendsCodes, REDEMPTION } from "@/constants/booking"
|
||||
import { getHotel } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard"
|
||||
@@ -13,6 +14,7 @@ import { getHotelSearchDetails } from "@/utils/hotelSearchDetails"
|
||||
import { convertSearchParamsToObj } from "@/utils/url"
|
||||
|
||||
import AvailabilityError from "./AvailabilityError"
|
||||
import FnFNotAllowedAlert from "../FnFNotAllowedAlert/FnFNotAllowedAlert"
|
||||
import { getValidDates } from "./getValidDates"
|
||||
import { getTracking } from "./tracking"
|
||||
|
||||
@@ -73,17 +75,26 @@ export default async function SelectRatePage({
|
||||
|
||||
const booking = convertSearchParamsToObj<SelectRateSearchParams>(searchParams)
|
||||
|
||||
let isInValidFNF = false
|
||||
if (bookingCode && FamilyAndFriendsCodes.includes(bookingCode)) {
|
||||
const cookieStore = cookies()
|
||||
isInValidFNF = cookieStore.get("sc")?.value !== "1"
|
||||
}
|
||||
const suspenseKey = stringify(searchParams)
|
||||
return (
|
||||
<>
|
||||
<HotelInfoCard hotel={hotelData.hotel} />
|
||||
|
||||
<RoomsContainer
|
||||
booking={booking}
|
||||
hotelType={hotelData.hotel.hotelType}
|
||||
roomCategories={hotelData.roomCategories}
|
||||
vat={hotelData.hotel.vat}
|
||||
/>
|
||||
{isInValidFNF ? (
|
||||
<FnFNotAllowedAlert />
|
||||
) : (
|
||||
<RoomsContainer
|
||||
booking={booking}
|
||||
hotelType={hotelData.hotel.hotelType}
|
||||
roomCategories={hotelData.roomCategories}
|
||||
vat={hotelData.hotel.vat}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Suspense key={`${suspenseKey}-tracking`} fallback={null}>
|
||||
<TrackingSDK
|
||||
|
||||
@@ -34,6 +34,8 @@ export enum ChildBedTypeEnum {
|
||||
Unknown = "Unknown",
|
||||
}
|
||||
|
||||
export const FamilyAndFriendsCodes = ["D000029555", "D000029271", "D000029195"]
|
||||
|
||||
export const REDEMPTION = "redemption"
|
||||
export const SEARCHTYPE = "searchtype"
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import * as currentWebLogin from "@/middlewares/currentWebLogin"
|
||||
import * as currentWebLoginEmail from "@/middlewares/currentWebLoginEmail"
|
||||
import * as currentWebLogout from "@/middlewares/currentWebLogout"
|
||||
import * as dateFormat from "@/middlewares/dateFormat"
|
||||
import * as familyAndFriends from "@/middlewares/familyAndFriends"
|
||||
import * as handleAuth from "@/middlewares/handleAuth"
|
||||
import * as myPages from "@/middlewares/myPages"
|
||||
import * as redirect from "@/middlewares/redirect"
|
||||
@@ -57,6 +58,7 @@ export const middleware: NextMiddleware = async (request, event) => {
|
||||
webView,
|
||||
dateFormat,
|
||||
bookingFlow,
|
||||
familyAndFriends,
|
||||
sasXScandic,
|
||||
cmsContent,
|
||||
redirect,
|
||||
|
||||
46
apps/scandic-web/middlewares/familyAndFriends.ts
Normal file
46
apps/scandic-web/middlewares/familyAndFriends.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { type NextMiddleware, NextResponse } from "next/server"
|
||||
|
||||
import { getPublicNextURL } from "@/server/utils"
|
||||
|
||||
import { findLang } from "@/utils/languages"
|
||||
|
||||
import { getDefaultRequestHeaders } from "./utils"
|
||||
|
||||
import type { MiddlewareMatcher } from "@/types/middleware"
|
||||
|
||||
export const middleware: NextMiddleware = async (request) => {
|
||||
const lang = findLang(request.nextUrl.pathname)!
|
||||
const nextUrlPublic = getPublicNextURL(request)
|
||||
const redirectUrl = new URL(`/${lang}`, nextUrlPublic)
|
||||
|
||||
const key = request.nextUrl.searchParams.get("key")
|
||||
const code = request.nextUrl.searchParams.get("code")
|
||||
|
||||
const md5 = require("md5")
|
||||
if (
|
||||
key &&
|
||||
code &&
|
||||
key === md5("scandic" + new Date().toISOString().substring(0, 10))
|
||||
) {
|
||||
const headers = new Headers()
|
||||
// Set cookie for this device/user to be valid to use the FnF code for 3 days starting now
|
||||
headers.append(
|
||||
"set-cookie",
|
||||
`sc=1; max-age=259200; Path=/; HttpOnly; SameSite=Lax`
|
||||
)
|
||||
const redirectOpts = {
|
||||
headers,
|
||||
}
|
||||
redirectUrl.searchParams.set("bookingCode", code)
|
||||
return NextResponse.redirect(redirectUrl, redirectOpts)
|
||||
}
|
||||
|
||||
const headers = getDefaultRequestHeaders(request)
|
||||
return NextResponse.redirect(redirectUrl, {
|
||||
headers,
|
||||
})
|
||||
}
|
||||
|
||||
export const matcher: MiddlewareMatcher = (request) => {
|
||||
return request.nextUrl.pathname === "/en/familyandfriends"
|
||||
}
|
||||
@@ -91,6 +91,7 @@
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"libphonenumber-js": "^1.10.60",
|
||||
"lodash-es": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"next": "^14.2.25",
|
||||
"next-auth": "5.0.0-beta.19",
|
||||
|
||||
33
yarn.lock
33
yarn.lock
@@ -6452,6 +6452,7 @@ __metadata:
|
||||
lint-staged: "npm:^15.2.2"
|
||||
lodash-es: "npm:^4.17.21"
|
||||
material-symbols: "npm:^0.29.0"
|
||||
md5: "npm:^2.3.0"
|
||||
nanoid: "npm:^5.0.9"
|
||||
netlify-plugin-cypress: "npm:^2.2.1"
|
||||
next: "npm:^14.2.25"
|
||||
@@ -10282,6 +10283,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"charenc@npm:0.0.2":
|
||||
version: 0.0.2
|
||||
resolution: "charenc@npm:0.0.2"
|
||||
checksum: 10c0/a45ec39363a16799d0f9365c8dd0c78e711415113c6f14787a22462ef451f5013efae8a28f1c058f81fc01f2a6a16955f7a5fd0cd56247ce94a45349c89877d8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"check-error@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "check-error@npm:2.1.1"
|
||||
@@ -10938,6 +10946,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"crypt@npm:0.0.2":
|
||||
version: 0.0.2
|
||||
resolution: "crypt@npm:0.0.2"
|
||||
checksum: 10c0/adbf263441dd801665d5425f044647533f39f4612544071b1471962209d235042fb703c27eea2795c7c53e1dfc242405173003f83cf4f4761a633d11f9653f18
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"css-select@npm:^5.1.0":
|
||||
version: 5.1.0
|
||||
resolution: "css-select@npm:5.1.0"
|
||||
@@ -14151,6 +14166,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-buffer@npm:~1.1.6":
|
||||
version: 1.1.6
|
||||
resolution: "is-buffer@npm:1.1.6"
|
||||
checksum: 10c0/ae18aa0b6e113d6c490ad1db5e8df9bdb57758382b313f5a22c9c61084875c6396d50bbf49315f5b1926d142d74dfb8d31b40d993a383e0a158b15fea7a82234
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-bun-module@npm:^1.0.2":
|
||||
version: 1.3.0
|
||||
resolution: "is-bun-module@npm:1.3.0"
|
||||
@@ -16457,6 +16479,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"md5@npm:^2.3.0":
|
||||
version: 2.3.0
|
||||
resolution: "md5@npm:2.3.0"
|
||||
dependencies:
|
||||
charenc: "npm:0.0.2"
|
||||
crypt: "npm:0.0.2"
|
||||
is-buffer: "npm:~1.1.6"
|
||||
checksum: 10c0/14a21d597d92e5b738255fbe7fe379905b8cb97e0a49d44a20b58526a646ec5518c337b817ce0094ca94d3e81a3313879c4c7b510d250c282d53afbbdede9110
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mdn-data@npm:2.0.28":
|
||||
version: 2.0.28
|
||||
resolution: "mdn-data@npm:2.0.28"
|
||||
|
||||
Reference in New Issue
Block a user