Merged in feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow (pull request #2600)
feat(SW-2873): Move HotelReservationSidePeek to booking-flow * Move sidepeek store to booking-flow * Begin move of HotelReservationSidePeek to booking-flow * Copy Link * Update AccessibilityAccordionItem * Split AccessibilityAccordionItem into two components * Fix tracking for Accordion * Duplicate ButtonLink to booking-flow TEMP * AdditionalAmeneties * wip * Move sidepeek accordion items * Remove temp ButtonLink * Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow * Fix accordion tracking * Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow * Update exports * Fix self-referencing import * Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow * Add 'use client' to tracking function * Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow * Fix TEMP folder * Refactor sidepeek tracking * Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow Approved-by: Joakim Jäderberg
This commit is contained in:
@@ -3,13 +3,13 @@
|
||||
import { DialogTrigger } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { RoomSidePeekContent } from "@scandic-hotels/booking-flow/components/RoomSidePeekContent"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { getBookedHotelRoom } from "@scandic-hotels/trpc/routers/booking/helpers"
|
||||
|
||||
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
||||
|
||||
import { RoomSidePeekContent } from "@/components/SidePeeks/RoomSidePeek/RoomSidePeekContent"
|
||||
import SidePeekSelfControlled from "@/components/TempDesignSystem/SidePeekSelfControlled"
|
||||
|
||||
interface RoomDetailsSidePeekProps {
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
.wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: auto;
|
||||
gap: var(--Spacing-x2);
|
||||
font-family: var(--typography-Body-Regular-fontFamily);
|
||||
margin-bottom: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.address,
|
||||
.contactInfo {
|
||||
display: grid;
|
||||
grid-template-columns: subgrid;
|
||||
grid-template-rows: subgrid;
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 1 / 4;
|
||||
}
|
||||
|
||||
.contactInfo > li {
|
||||
font-style: normal;
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.soMeIcons {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.ecoLabel {
|
||||
width: 38px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.ecoLabel img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
flex-shrink: 0;
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 4 / 4;
|
||||
}
|
||||
|
||||
.ecoContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: var(--Spacing-x-one-and-half);
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 4 / 4;
|
||||
font-size: var(--typography-Footnote-Regular-fontSize);
|
||||
line-height: ();
|
||||
margin-bottom: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.ecoLabelText {
|
||||
display: flex;
|
||||
color: var(--UI-Text-Medium-contrast);
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.link {
|
||||
text-decoration: underline;
|
||||
font-family: var(--typography-Body-Regular-fontFamily);
|
||||
color: var(--Text-Interactive-Secondary);
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import FacebookIcon from "@scandic-hotels/design-system/Icons/FacebookIcon"
|
||||
import InstagramIcon from "@scandic-hotels/design-system/Icons/InstagramIcon"
|
||||
import Image from "@scandic-hotels/design-system/Image"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import styles from "./contact.module.css"
|
||||
|
||||
import type { ContactProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
export default function Contact({ hotel }: ContactProps) {
|
||||
const lang = useLang()
|
||||
const intl = useIntl()
|
||||
|
||||
const addressStr = `${hotel.address.streetAddress}, `
|
||||
const cityStr = hotel.address.city
|
||||
|
||||
return (
|
||||
<section className={styles.wrapper}>
|
||||
<address className={styles.address}>
|
||||
<ul className={styles.contactInfo}>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Address",
|
||||
})}
|
||||
</Body>
|
||||
<Body>
|
||||
{addressStr}
|
||||
<br />
|
||||
{cityStr}
|
||||
</Body>
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Driving directions",
|
||||
})}
|
||||
</Body>
|
||||
<Link
|
||||
href={`https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(
|
||||
`${hotel.name}, ${hotel.address.streetAddress}, ${hotel.address.zipCode} ${hotel.address.city}`
|
||||
)}`}
|
||||
>
|
||||
<span className={styles.link}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Google Maps",
|
||||
})}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Contact us",
|
||||
})}
|
||||
</Body>
|
||||
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
|
||||
<span className={styles.link}>
|
||||
{hotel.contactInformation.phoneNumber}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
{(hotel.socialMedia.facebook || hotel.socialMedia.instagram) && (
|
||||
<>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Follow us",
|
||||
})}
|
||||
</Body>
|
||||
<div className={styles.soMeIcons}>
|
||||
{hotel.socialMedia.instagram && (
|
||||
<Link href={hotel.socialMedia.instagram} target="_blank">
|
||||
<InstagramIcon color="Icon/Interactive/Default" />
|
||||
</Link>
|
||||
)}
|
||||
{hotel.socialMedia.facebook && (
|
||||
<Link href={hotel.socialMedia.facebook} target="_blank">
|
||||
<FacebookIcon color="Icon/Interactive/Default" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
</Body>
|
||||
<Link href={`mailto:${hotel.contactInformation.email}`}>
|
||||
<span className={styles.link}>
|
||||
{hotel.contactInformation.email}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</address>
|
||||
{hotel.hotelFacts.ecoLabels?.nordicEcoLabel ? (
|
||||
<div className={styles.ecoContainer}>
|
||||
<div className={styles.ecoLabel}>
|
||||
<Image
|
||||
height={38}
|
||||
width={38}
|
||||
alt={intl.formatMessage({
|
||||
defaultMessage: "Nordic Swan Ecolabel",
|
||||
})}
|
||||
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.ecoLabelText}>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Nordic Swan Ecolabel",
|
||||
})}
|
||||
</span>
|
||||
<span>
|
||||
{hotel.hotelFacts.ecoLabels.svanenEcoLabelCertificateNumber}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -4,9 +4,9 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { FormProvider, useForm } from "react-hook-form"
|
||||
|
||||
import { BED_TYPE_ICONS } from "@scandic-hotels/booking-flow/bedTypeIcons"
|
||||
import RadioCard from "@scandic-hotels/design-system/Form/RadioCard"
|
||||
|
||||
import { BED_TYPE_ICONS } from "@/constants/booking"
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
|
||||
import { useRoomContext } from "@/contexts/Details/Room"
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import useSidePeekStore, {
|
||||
SidePeekEnum,
|
||||
} from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
||||
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type { ToggleSidePeekProps } from "@/types/components/hotelReservation/toggleSidePeekProps"
|
||||
|
||||
export default function ToggleSidePeek({ hotelId }: ToggleSidePeekProps) {
|
||||
@@ -16,7 +18,14 @@ export default function ToggleSidePeek({ hotelId }: ToggleSidePeekProps) {
|
||||
|
||||
return (
|
||||
<Button
|
||||
onPress={() => openSidePeek({ key: SidePeekEnum.hotelDetails, hotelId })}
|
||||
onPress={() => {
|
||||
openSidePeek({ key: SidePeekEnum.hotelDetails, hotelId })
|
||||
trackOpenSidePeekEvent({
|
||||
name: SidePeekEnum.hotelDetails,
|
||||
hotelId,
|
||||
includePathname: true,
|
||||
})
|
||||
}}
|
||||
size="Small"
|
||||
variant="Secondary"
|
||||
color="Inverted"
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import useSidePeekStore, {
|
||||
SidePeekEnum,
|
||||
} from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
||||
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type { ToggleSidePeekProps } from "@/types/components/hotelReservation/toggleSidePeekProps"
|
||||
|
||||
export default function ToggleSidePeek({
|
||||
@@ -20,9 +22,15 @@ export default function ToggleSidePeek({
|
||||
|
||||
return (
|
||||
<Button
|
||||
onPress={() =>
|
||||
onPress={() => {
|
||||
openSidePeek({ key: SidePeekEnum.roomDetails, hotelId, roomTypeCode })
|
||||
}
|
||||
trackOpenSidePeekEvent({
|
||||
name: SidePeekEnum.roomDetails,
|
||||
hotelId,
|
||||
roomTypeCode,
|
||||
includePathname: true,
|
||||
})
|
||||
}}
|
||||
size="Small"
|
||||
variant="Text"
|
||||
wrapping
|
||||
|
||||
@@ -11,6 +11,7 @@ import { memo } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import TripAdvisorChip from "@scandic-hotels/booking-flow/components/TripAdvisorChip"
|
||||
import { SidePeekEnum } from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import {
|
||||
alternativeHotelsMap,
|
||||
selectHotelMap,
|
||||
@@ -44,7 +45,6 @@ import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||
|
||||
import { HotelCardListingTypeEnum } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
function HotelCard({
|
||||
hotelData: { availability, hotel },
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { cookies } from "next/headers"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import SidePeek from "@scandic-hotels/booking-flow/components/HotelReservationSidePeek"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { logger } from "@scandic-hotels/common/logger"
|
||||
import * as maskValue from "@scandic-hotels/common/utils/maskValue"
|
||||
@@ -35,7 +36,6 @@ import Promo from "@/components/HotelReservation/MyStay/Promo"
|
||||
import { ReferenceCard } from "@/components/HotelReservation/MyStay/ReferenceCard"
|
||||
import MultiRoom from "@/components/HotelReservation/MyStay/Rooms/MultiRoom"
|
||||
import SingleRoom from "@/components/HotelReservation/MyStay/Rooms/SingleRoom"
|
||||
import SidePeek from "@/components/HotelReservation/SidePeek"
|
||||
import { getIntl } from "@/i18n"
|
||||
import MyStayProvider from "@/providers/MyStay"
|
||||
import { isLoggedInUser } from "@/utils/isLoggedInUser"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"use client"
|
||||
import { useEffect } from "react"
|
||||
|
||||
import useSidePeekStore from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
||||
|
||||
import type { ReadMoreProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
@@ -29,6 +30,11 @@ export default function ReadMore({
|
||||
<Button
|
||||
onPress={() => {
|
||||
openSidePeek({ key: sidePeekKey, hotelId, showCTA })
|
||||
trackOpenSidePeekEvent({
|
||||
name: sidePeekKey,
|
||||
hotelId,
|
||||
includePathname: true,
|
||||
})
|
||||
}}
|
||||
variant="Text"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState } from "react"
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { SidePeekEnum } from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||
@@ -14,8 +15,6 @@ import styles from "./hotelDescription.module.css"
|
||||
|
||||
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
export default function HotelDescription({
|
||||
description,
|
||||
hotel,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import TripAdvisorChip from "@scandic-hotels/booking-flow/components/TripAdvisorChip"
|
||||
import { SidePeekEnum } from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
@@ -20,7 +21,6 @@ import styles from "./hotelInfoCard.module.css"
|
||||
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
import type { SelectRateBooking } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
export type HotelInfoCardProps = {
|
||||
booking: SelectRateBooking
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import useSidePeekStore, {
|
||||
SidePeekEnum,
|
||||
} from "@scandic-hotels/booking-flow/stores/sidepeek"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
||||
|
||||
import styles from "./details.module.css"
|
||||
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type { ToggleSidePeekProps } from "@/types/components/hotelReservation/toggleSidePeekProps"
|
||||
|
||||
export default function ToggleSidePeek({
|
||||
@@ -21,13 +23,19 @@ export default function ToggleSidePeek({
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={() =>
|
||||
onClick={() => {
|
||||
openSidePeek({
|
||||
key: SidePeekEnum.roomDetails,
|
||||
hotelId,
|
||||
roomTypeCode,
|
||||
})
|
||||
}
|
||||
trackOpenSidePeekEvent({
|
||||
name: SidePeekEnum.roomDetails,
|
||||
hotelId,
|
||||
roomTypeCode,
|
||||
includePathname: true,
|
||||
})
|
||||
}}
|
||||
size="Small"
|
||||
variant="Text"
|
||||
wrapping
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
.spacing {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect } from "react"
|
||||
|
||||
import { trpc } from "@scandic-hotels/trpc/client"
|
||||
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
|
||||
import HotelSidePeek from "@/components/SidePeeks/HotelSidePeek"
|
||||
import RoomSidePeek from "@/components/SidePeeks/RoomSidePeek"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
export default function HotelReservationSidePeek() {
|
||||
const { activeSidePeek, hotelId, roomTypeCode, showCTA } = useSidePeekStore(
|
||||
(state) => ({
|
||||
activeSidePeek: state.activeSidePeek,
|
||||
hotelId: state.hotelId,
|
||||
roomTypeCode: state.roomTypeCode,
|
||||
showCTA: state.showCTA,
|
||||
})
|
||||
)
|
||||
const closeFn = useSidePeekStore((state) => state.closeSidePeek)
|
||||
const lang = useLang()
|
||||
|
||||
const { data: hotelData } = trpc.hotel.get.useQuery(
|
||||
{
|
||||
hotelId: hotelId ?? "",
|
||||
language: lang,
|
||||
isCardOnlyPayment: false,
|
||||
},
|
||||
{
|
||||
enabled: !!hotelId,
|
||||
}
|
||||
)
|
||||
|
||||
const selectedRoom = hotelData?.roomCategories.find((room) =>
|
||||
room.roomTypes.some((type) => type.code === roomTypeCode)
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (activeSidePeek) {
|
||||
window.history.pushState(null, "", window.location.href)
|
||||
}
|
||||
}, [activeSidePeek])
|
||||
|
||||
useEffect(() => {
|
||||
function handlePopState() {
|
||||
if (activeSidePeek) {
|
||||
closeFn()
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("popstate", handlePopState)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("popstate", handlePopState)
|
||||
}
|
||||
}, [activeSidePeek, closeFn])
|
||||
|
||||
if (activeSidePeek) {
|
||||
return (
|
||||
<>
|
||||
{hotelData && (
|
||||
<HotelSidePeek
|
||||
additionalHotelData={hotelData.additionalData}
|
||||
hotel={{ ...hotelData.hotel, url: hotelData.url }}
|
||||
restaurants={hotelData.restaurants}
|
||||
activeSidePeek={activeSidePeek}
|
||||
close={closeFn}
|
||||
showCTA={showCTA}
|
||||
/>
|
||||
)}
|
||||
{selectedRoom && (
|
||||
<RoomSidePeek
|
||||
room={selectedRoom}
|
||||
activeSidePeek={activeSidePeek}
|
||||
close={closeFn}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user