feat(SW-885): ancillary and book next stay
This commit is contained in:
@@ -22,7 +22,10 @@ import SearchList from "./SearchList"
|
||||
import styles from "./search.module.css"
|
||||
|
||||
import type { BookingWidgetSchema } from "@/types/components/bookingWidget"
|
||||
import { ActionType } from "@/types/components/form/bookingwidget"
|
||||
import {
|
||||
ActionType,
|
||||
SetStorageData,
|
||||
} from "@/types/components/form/bookingwidget"
|
||||
import type { SearchProps } from "@/types/components/search"
|
||||
import type { Location } from "@/types/trpc/routers/hotel/locations"
|
||||
|
||||
@@ -40,7 +43,7 @@ export default function Search({ locations, handlePressEnter }: SearchProps) {
|
||||
: null
|
||||
const [state, dispatch] = useReducer(
|
||||
reducer,
|
||||
{ defaultLocations: locations },
|
||||
{ defaultLocations: locations, initialValue: value },
|
||||
init
|
||||
)
|
||||
const handleMatchLocations = useCallback(
|
||||
@@ -122,30 +125,19 @@ export default function Search({ locations, handlePressEnter }: SearchProps) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const searchData =
|
||||
typeof window !== "undefined"
|
||||
? sessionStorage.getItem(sessionStorageKey)
|
||||
: undefined
|
||||
|
||||
const searchHistory =
|
||||
typeof window !== "undefined"
|
||||
? localStorage.getItem(localStorageKey)
|
||||
: null
|
||||
if (searchData || searchHistory) {
|
||||
dispatch({
|
||||
payload: {
|
||||
searchData:
|
||||
isValidJson(searchData) && searchData
|
||||
? JSON.parse(searchData)
|
||||
: undefined,
|
||||
searchHistory:
|
||||
isValidJson(searchHistory) && searchHistory
|
||||
? JSON.parse(searchHistory)
|
||||
: null,
|
||||
},
|
||||
type: ActionType.SET_STORAGE_DATA,
|
||||
})
|
||||
const searchData = sessionStorage.getItem(sessionStorageKey)
|
||||
const searchHistory = localStorage.getItem(localStorageKey)
|
||||
const payload: SetStorageData["payload"] = {}
|
||||
if (searchData) {
|
||||
payload.searchData = JSON.parse(searchData)
|
||||
}
|
||||
if (searchHistory) {
|
||||
payload.searchHistory = JSON.parse(searchHistory)
|
||||
}
|
||||
dispatch({
|
||||
payload,
|
||||
type: ActionType.SET_STORAGE_DATA,
|
||||
})
|
||||
}, [dispatch])
|
||||
|
||||
const stayType = state.searchData?.type === "cities" ? "city" : "hotel"
|
||||
|
||||
@@ -10,11 +10,20 @@ export const localStorageKey = "searchHistory"
|
||||
export const sessionStorageKey = "searchData"
|
||||
|
||||
export function init(initState: InitState): State {
|
||||
const locations = []
|
||||
if (initState.initialValue) {
|
||||
const location = initState.defaultLocations.find(
|
||||
(loc) => loc.name.toLowerCase() === initState.initialValue!.toLowerCase()
|
||||
)
|
||||
if (location) {
|
||||
locations.push(location)
|
||||
}
|
||||
}
|
||||
return {
|
||||
defaultLocations: initState.defaultLocations,
|
||||
locations: [],
|
||||
search: "",
|
||||
searchData: undefined,
|
||||
locations,
|
||||
search: locations.length ? locations[0].name : "",
|
||||
searchData: locations.length ? locations[0] : undefined,
|
||||
searchHistory: null,
|
||||
}
|
||||
}
|
||||
@@ -73,8 +82,12 @@ export function reducer(state: State, action: Action) {
|
||||
case ActionType.SET_STORAGE_DATA: {
|
||||
return {
|
||||
...state,
|
||||
searchData: action.payload.searchData,
|
||||
searchHistory: action.payload.searchHistory,
|
||||
searchData: action.payload.searchData
|
||||
? action.payload.searchData
|
||||
: state.searchData,
|
||||
searchHistory: action.payload.searchHistory
|
||||
? action.payload.searchHistory
|
||||
: state.searchHistory,
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -30,7 +30,11 @@ export default function Confirmation({
|
||||
<PaymentDetails booking={booking} />
|
||||
<Divider color="primaryLightSubtle" />
|
||||
<HotelDetails hotel={hotel} />
|
||||
<Promos />
|
||||
<Promos
|
||||
confirmationNumber={booking.confirmationNumber}
|
||||
hotelId={hotel.operaId}
|
||||
lastName={booking.guest.lastName}
|
||||
/>
|
||||
<div className={styles.mobileReceipt}>
|
||||
<Receipt booking={booking} hotel={hotel} room={room} />
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
|
||||
@@ -6,7 +7,7 @@ import styles from "./promo.module.css"
|
||||
|
||||
import type { PromoProps } from "@/types/components/hotelReservation/bookingConfirmation/promo"
|
||||
|
||||
export default function Promo({ buttonText, text, title }: PromoProps) {
|
||||
export default function Promo({ buttonText, href, text, title }: PromoProps) {
|
||||
return (
|
||||
<article className={styles.promo}>
|
||||
<Title color="white" level="h4">
|
||||
@@ -15,8 +16,10 @@ export default function Promo({ buttonText, text, title }: PromoProps) {
|
||||
<Body className={styles.text} color="white" textAlign="center">
|
||||
{text}
|
||||
</Body>
|
||||
<Button intent="primary" size="small" theme="primaryStrong">
|
||||
{buttonText}
|
||||
<Button asChild intent="primary" size="small" theme="primaryStrong">
|
||||
<Link color="none" href={href}>
|
||||
{buttonText}
|
||||
</Link>
|
||||
</Button>
|
||||
</article>
|
||||
)
|
||||
|
||||
@@ -15,22 +15,22 @@
|
||||
|
||||
.promo:nth-of-type(1) {
|
||||
background-image: linear-gradient(
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 0.36) 37.88%,
|
||||
rgba(0, 0, 0, 0.75) 100%
|
||||
);
|
||||
/* , url(""); uncomment and add image once we have it */
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 0.36) 37.88%,
|
||||
rgba(0, 0, 0, 0.75) 100%
|
||||
),
|
||||
url("/_static/img/Scandic_Park_Party_Lipstick.jpg");
|
||||
}
|
||||
|
||||
.promo:nth-of-type(2) {
|
||||
background-image: linear-gradient(
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 0.36) 37.88%,
|
||||
rgba(0, 0, 0, 0.75) 100%
|
||||
);
|
||||
/* , url(""); uncomment and add image once we have it */
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 0.36) 37.88%,
|
||||
rgba(0, 0, 0, 0.75) 100%
|
||||
),
|
||||
url("/_static/img/Scandic_Family_Breakfast.jpg");
|
||||
}
|
||||
|
||||
.text {
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
"use client"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { homeHrefs } from "@/constants/homeHrefs"
|
||||
import { myBooking } from "@/constants/myBooking"
|
||||
import { env } from "@/env/client"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import Promo from "./Promo"
|
||||
|
||||
import styles from "./promos.module.css"
|
||||
|
||||
export default function Promos() {
|
||||
import type { PromosProps } from "@/types/components/hotelReservation/bookingConfirmation/promos"
|
||||
|
||||
export default function Promos({
|
||||
confirmationNumber,
|
||||
hotelId,
|
||||
lastName,
|
||||
}: PromosProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const homeUrl = homeHrefs[env.NEXT_PUBLIC_NODE_ENV][lang]
|
||||
const myBookingUrl = myBooking[env.NEXT_PUBLIC_NODE_ENV][lang]
|
||||
return (
|
||||
<div className={styles.promos}>
|
||||
<Promo
|
||||
buttonText={intl.formatMessage({ id: "View and buy add-ons" })}
|
||||
href={`${myBookingUrl}?bookingId=${confirmationNumber}&lastName=${lastName}`}
|
||||
text={intl.formatMessage({
|
||||
id: "Discover the little extra touches to make your upcoming stay even more unforgettable.",
|
||||
})}
|
||||
@@ -18,6 +34,7 @@ export default function Promos() {
|
||||
/>
|
||||
<Promo
|
||||
buttonText={intl.formatMessage({ id: "Book another stay" })}
|
||||
href={`${homeUrl}?hotel=${hotelId}`}
|
||||
text={intl.formatMessage({
|
||||
id: "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user