diff --git a/apps/partner-sas/app/[lang]/layout.tsx b/apps/partner-sas/app/[lang]/layout.tsx index 398512076..a4197abd4 100644 --- a/apps/partner-sas/app/[lang]/layout.tsx +++ b/apps/partner-sas/app/[lang]/layout.tsx @@ -1,6 +1,6 @@ import "@scandic-hotels/design-system/fonts.css" import "@scandic-hotels/design-system/style.css" -import "@/public/_static/css/design-system-new-deprecated.css" +import "@scandic-hotels/design-system/design-system-new-deprecated.css" import "../../globals.css" import { BookingFlowTrackingProvider } from "@scandic-hotels/booking-flow/BookingFlowTrackingProvider" diff --git a/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts b/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts index 6eb8ba863..47f6ec36d 100644 --- a/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts +++ b/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts @@ -1,4 +1,4 @@ -import { type NextRequest,NextResponse } from "next/server" +import { type NextRequest, NextResponse } from "next/server" import { AuthError } from "next-auth" import { logger } from "@scandic-hotels/common/logger" diff --git a/apps/scandic-web/app/[lang]/(live)/layout.tsx b/apps/scandic-web/app/[lang]/(live)/layout.tsx index 197b6565d..02b2b5fbc 100644 --- a/apps/scandic-web/app/[lang]/(live)/layout.tsx +++ b/apps/scandic-web/app/[lang]/(live)/layout.tsx @@ -1,6 +1,6 @@ import "@scandic-hotels/design-system/fonts.css" import "@/app/globals.css" -import "@/public/_static/css/design-system-new-deprecated.css" +import "@scandic-hotels/design-system/design-system-new-deprecated.css" import "@scandic-hotels/design-system/style.css" import { ReactQueryDevtools } from "@tanstack/react-query-devtools" diff --git a/apps/scandic-web/app/[lang]/(no-layout)/layout.tsx b/apps/scandic-web/app/[lang]/(no-layout)/layout.tsx index 902dbbb01..fbc138f23 100644 --- a/apps/scandic-web/app/[lang]/(no-layout)/layout.tsx +++ b/apps/scandic-web/app/[lang]/(no-layout)/layout.tsx @@ -1,6 +1,6 @@ import "@scandic-hotels/design-system/fonts.css" import "@/app/globals.css" -import "@/public/_static/css/design-system-new-deprecated.css" +import "@scandic-hotels/design-system/design-system-new-deprecated.css" import "@scandic-hotels/design-system/style.css" import { ReactQueryDevtools } from "@tanstack/react-query-devtools" diff --git a/apps/scandic-web/app/[lang]/(partner)/layout.tsx b/apps/scandic-web/app/[lang]/(partner)/layout.tsx index 78192100e..050dd4eae 100644 --- a/apps/scandic-web/app/[lang]/(partner)/layout.tsx +++ b/apps/scandic-web/app/[lang]/(partner)/layout.tsx @@ -1,6 +1,6 @@ import "@scandic-hotels/design-system/fonts.css" import "@/app/globals.css" -import "@/public/_static/css/design-system-new-deprecated.css" +import "@scandic-hotels/design-system/design-system-new-deprecated.css" import "@scandic-hotels/design-system/style.css" import { ReactQueryDevtools } from "@tanstack/react-query-devtools" diff --git a/apps/scandic-web/app/[lang]/webview/layout.tsx b/apps/scandic-web/app/[lang]/webview/layout.tsx index c050a3251..dc7b8ec7a 100644 --- a/apps/scandic-web/app/[lang]/webview/layout.tsx +++ b/apps/scandic-web/app/[lang]/webview/layout.tsx @@ -1,7 +1,7 @@ import "@scandic-hotels/design-system/fonts.css" import "@/app/globals.css" -import "@/public/_static/css/design-system-new-deprecated.css" import "@scandic-hotels/design-system/style.css" +import "@scandic-hotels/design-system/design-system-new-deprecated.css" import Script from "next/script" import { NuqsAdapter } from "nuqs/adapters/next/app" diff --git a/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx b/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx index 13409e9f0..9b33526fb 100644 --- a/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx +++ b/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx @@ -3,12 +3,12 @@ import { useIntl } from "react-intl" import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" import { Divider } from "@scandic-hotels/design-system/Divider" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon" import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon" import ImageGallery from "@scandic-hotels/design-system/ImageGallery" import { Typography } from "@scandic-hotels/design-system/Typography" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import { mapApiImagesToGalleryImages } from "@/utils/imageGallery" import styles from "./hotelListingItem.module.css" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx index 22d81bbc7..9a6c4ea1d 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx @@ -7,6 +7,7 @@ import { useIntl } from "react-intl" import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" import { Divider } from "@scandic-hotels/design-system/Divider" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon" import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon" import ImageGallery from "@scandic-hotels/design-system/ImageGallery" @@ -14,7 +15,6 @@ import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import { mapApiImagesToGalleryImages } from "@/utils/imageGallery" import styles from "./hotelListItem.module.css" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx index 96814f5a5..2ff686998 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx @@ -8,6 +8,7 @@ import { useIntl } from "react-intl" import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" import { Divider } from "@scandic-hotels/design-system/Divider" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon" @@ -16,7 +17,6 @@ import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import { mapApiImagesToGalleryImages } from "@/utils/imageGallery" import styles from "./hotelListingItem.module.css" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx index 13454d0b2..a3b652147 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx @@ -3,13 +3,13 @@ import { useState } from "react" import { useIntl } from "react-intl" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import { IconButton } from "@scandic-hotels/design-system/IconButton" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" -import { FacilityToIcon } from "../../HotelPage/data" import { usePageType } from "../Map/PageTypeProvider" import DialogImage from "./DialogImage" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx index 46a6916e3..d09eb3c27 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx @@ -8,9 +8,9 @@ import { type PropsWithChildren, useEffect, useRef, useState } from "react" import { useIntl } from "react-intl" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" +import { MAP_RESTRICTIONS } from "@scandic-hotels/design-system/Map/mapConstants" import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton" -import { MAP_RESTRICTIONS } from "@/constants/map" import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" import { ErrorBoundary } from "@/components/ErrorBoundary/ErrorBoundary" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx index 56e71f6d4..5443269ae 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx @@ -8,9 +8,10 @@ import { } from "@vis.gl/react-google-maps" import { useMediaQuery } from "usehooks-ts" +import { HotelMarkerByType } from "@scandic-hotels/design-system/Map/Markers/HotelMarkerByType" + import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" -import HotelMarkerByType from "@/components/Maps/Markers" import { trackMapClick } from "@/utils/tracking/destinationPage" import HotelMapCard from "../../../HotelMapCard" diff --git a/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx b/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx index bb9193ecd..05fe81a3f 100644 --- a/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx +++ b/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx @@ -13,8 +13,12 @@ import { useIntl } from "react-intl" import { debounce } from "@scandic-hotels/common/utils/debounce" import { Button } from "@scandic-hotels/design-system/Button" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" +import { InteractiveMap } from "@scandic-hotels/design-system/Map/InteractiveMap" -import InteractiveMap from "@/components/Maps/InteractiveMap" +import { useHotelsMapStore } from "@/stores/hotels-map" + +import { useIsUserLoggedIn } from "@/hooks/useIsUserLoggedIn" +import useLang from "@/hooks/useLang" import Sidebar from "./Sidebar" @@ -43,11 +47,15 @@ export default function HotelMapPageClient({ mapId, }: HotelMapPageClientProps) { const intl = useIntl() + const lang = useLang() const router = useRouter() const rootDiv = useRef(null) const [mapHeight, setMapHeight] = useState("100dvh") const [activePoi, setActivePoi] = useState(null) + const isUserLoggedIn = useIsUserLoggedIn() + const hotelMapStore = useHotelsMapStore() + // Calculate the height of the map based on the viewport height from the start-point (below the header and booking widget) const handleMapHeight = useCallback(() => { const topPosition = rootDiv.current?.getBoundingClientRect().top ?? 0 @@ -132,6 +140,15 @@ export default function HotelMapPageClient({ onActivePoiChange={(poi) => setActivePoi(poi ?? null)} mapId={mapId} markerInfo={markerInfo} + onHoverHotelPin={(args) => { + if (!args) { + hotelMapStore.disengage() + } + hotelMapStore.engage(hotelName) + }} + hoveredHotelPin={hotelMapStore.hoveredHotel} + lang={lang} + isUserLoggedIn={isUserLoggedIn} /> diff --git a/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx b/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx index 555c67961..a60865ce5 100644 --- a/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx @@ -6,10 +6,9 @@ import { useState } from "react" import { Button as ButtonRAC } from "react-aria-components" import { useIntl } from "react-intl" +import { PoiMarker } from "@scandic-hotels/design-system/Map/Markers/PoiMarker" import { Typography } from "@scandic-hotels/design-system/Typography" -import PoiMarker from "@/components/Maps/Markers/Poi" - import { translatePOIGroup } from "./util" import styles from "./sidebar.module.css" diff --git a/apps/scandic-web/components/ContentType/HotelPage/AmenitiesList/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/AmenitiesList/index.tsx index eb96107a4..7504d7ec9 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/AmenitiesList/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/AmenitiesList/index.tsx @@ -1,8 +1,8 @@ import ButtonLink from "@scandic-hotels/design-system/ButtonLink" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { Typography } from "@scandic-hotels/design-system/Typography" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import { getIntl } from "@/i18n" import styles from "./amenitiesList.module.css" diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx index 6772ef272..1fd2a74f3 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx @@ -5,9 +5,9 @@ import { useEffect, useState } from "react" import { useIntl } from "react-intl" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" +import { PoiMarker } from "@scandic-hotels/design-system/Map/Markers/PoiMarker" import { Typography } from "@scandic-hotels/design-system/Typography" -import PoiMarker from "@/components/Maps/Markers/Poi" import { trackHotelMapClick } from "@/utils/tracking" import styles from "./mapCard.module.css" diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/StaticMap/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Map/StaticMap/index.tsx index 828aad84a..579da319a 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/StaticMap/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/Map/StaticMap/index.tsx @@ -1,6 +1,7 @@ +import { HotelMarkerByType } from "@scandic-hotels/design-system/Map/Markers/HotelMarkerByType" + import { env } from "@/env/server" -import HotelMarkerByType from "@/components/Maps/Markers" import StaticMapComp from "@/components/Maps/StaticMap" import { getIntl } from "@/i18n" import { calculateLatWithOffset } from "@/utils/map" diff --git a/apps/scandic-web/components/HotelReservation/BookingConfirmation/Receipt/TotalPrice/index.tsx b/apps/scandic-web/components/HotelReservation/BookingConfirmation/Receipt/TotalPrice/index.tsx index b961154b9..d041bf241 100644 --- a/apps/scandic-web/components/HotelReservation/BookingConfirmation/Receipt/TotalPrice/index.tsx +++ b/apps/scandic-web/components/HotelReservation/BookingConfirmation/Receipt/TotalPrice/index.tsx @@ -3,14 +3,13 @@ import { cx } from "class-variance-authority" import { useIntl } from "react-intl" +import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip" import { Divider } from "@scandic-hotels/design-system/Divider" import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" import { Typography } from "@scandic-hotels/design-system/Typography" import { useBookingConfirmationStore } from "@/stores/booking-confirmation" -import BookingCodeChip from "@/components/BookingCodeChip" - import PriceDetails from "../../PriceDetails" import styles from "./totalPrice.module.css" diff --git a/apps/scandic-web/components/HotelReservation/EnterDetails/Summary/UI/index.tsx b/apps/scandic-web/components/HotelReservation/EnterDetails/Summary/UI/index.tsx index 2d376b59a..c27133c07 100644 --- a/apps/scandic-web/components/HotelReservation/EnterDetails/Summary/UI/index.tsx +++ b/apps/scandic-web/components/HotelReservation/EnterDetails/Summary/UI/index.tsx @@ -9,12 +9,12 @@ import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats" import { dt } from "@scandic-hotels/common/dt" import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting" import Body from "@scandic-hotels/design-system/Body" +import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip" import { Divider } from "@scandic-hotels/design-system/Divider" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import Subtitle from "@scandic-hotels/design-system/Subtitle" import { Typography } from "@scandic-hotels/design-system/Typography" -import BookingCodeChip from "@/components/BookingCodeChip" import PriceDetailsModal from "@/components/HotelReservation/PriceDetailsModal" import { isBookingCodeRate } from "@/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils" import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop" diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelCardSkeleton.tsx b/apps/scandic-web/components/HotelReservation/HotelCard/HotelCardSkeleton.tsx deleted file mode 100644 index b2dc5d4fe..000000000 --- a/apps/scandic-web/components/HotelReservation/HotelCard/HotelCardSkeleton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" - -import styles from "./HotelCardSkeleton.module.css" - -export function HotelCardSkeleton() { - return ( -
- {/* image container */} -
- -
- -
- -
- - - - -
- - -
- -
- {/* price variants */} - {Array.from({ length: 2 }).map((_, index) => ( - - ))} - -
-
- ) -} diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx b/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx deleted file mode 100644 index 99ef80da8..000000000 --- a/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx +++ /dev/null @@ -1,320 +0,0 @@ -"use client" - -import { cx } from "class-variance-authority" -import { - type ReadonlyURLSearchParams, - useParams, - useRouter, - useSearchParams, -} from "next/navigation" -import { memo } from "react" -import { useIntl } from "react-intl" - -import TripAdvisorChip from "@scandic-hotels/booking-flow/components/TripAdvisorChip" -import { - alternativeHotelsMap, - selectHotelMap, - selectRate, -} from "@scandic-hotels/common/constants/routes/hotelReservation" -import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting" -import Caption from "@scandic-hotels/design-system/Caption" -import { Divider } from "@scandic-hotels/design-system/Divider" -import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon" -import ImageGallery from "@scandic-hotels/design-system/ImageGallery" -import Link from "@scandic-hotels/design-system/Link" -import { Typography } from "@scandic-hotels/design-system/Typography" - -import { useHotelsMapStore } from "@/stores/hotels-map" - -import BookingCodeChip from "@/components/BookingCodeChip" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" -import HotelDetailsSidePeek from "@/components/SidePeeks/HotelDetailsSidePeek" -import { mapApiImagesToGalleryImages } from "@/utils/imageGallery" - -import HotelChequeCard from "./HotelChequeCard" -import HotelPointsRow from "./HotelPointsRow" -import HotelPriceCard from "./HotelPriceCard" -import HotelVoucherCard from "./HotelVoucherCard" -import NoPriceAvailableCard from "./NoPriceAvailableCard" -import { hotelCardVariants } from "./variants" - -import styles from "./hotelCard.module.css" - -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" - -function HotelCard({ - hotelData: { availability, hotel, additionalData, restaurants, url }, - isUserLoggedIn, - state = "default", - type = HotelCardListingTypeEnum.PageListing, - bookingCode = "", - isAlternative, -}: HotelCardProps) { - const params = useParams() - const searchParams = useSearchParams() - - const lang = params.lang as Lang - const intl = useIntl() - const { activate, engage, disengage, disengageAfterDelay } = - useHotelsMapStore() - - const amenities = hotel.detailedFacilities.slice(0, 5) - const router = useRouter() - const classNames = hotelCardVariants({ - type, - state, - }) - - const mapUrl = isAlternative - ? alternativeHotelsMap(lang) - : selectHotelMap(lang) - const handleAddressClick = (event: React.MouseEvent) => { - event.preventDefault() - disengage() // Disengage the current hotel to avoid the hover state from being active when clicking on the address - activate(hotel.name) - router.push(`${mapUrl}?${searchParams.toString()}`) - } - - const addressStr = `${hotel.address.streetAddress}, ${hotel.address.city}` - const galleryImages = mapApiImagesToGalleryImages(hotel.galleryImages || []) - const fullPrice = !availability.bookingCode - const price = availability.productType - - const hasInsufficientPoints = !price?.redemptions?.some( - (r) => r.hasEnoughPoints - ) - const notEnoughPointsLabel = intl.formatMessage({ - defaultMessage: "Not enough points", - }) - - const isDisabled = price?.redemptions?.length && hasInsufficientPoints - - return ( -
engage(hotel.name)} - onMouseLeave={() => disengageAfterDelay()} - > -
-
- - {hotel.ratings?.tripAdvisor && ( - - )} -
-
-
-
-
- - -

{hotel.name}

-
-
-
- {type == HotelCardListingTypeEnum.MapListing ? ( - -

{addressStr}

-
- ) : ( - - -

{addressStr}

-
- - )} -
- -
- -
- - - {intl.formatMessage( - { - defaultMessage: "{number} km to city center", - }, - { - number: getSingleDecimal( - hotel.location.distanceToCentre / 1000 - ), - } - )} - - -
-
- - {hotel.hotelContent.texts.descriptions ? ( - -

- {hotel.hotelContent.texts.descriptions.short} -

-
- ) : null} - -
- {amenities.map((facility) => ( -
- - - {facility.name} - -
- ))} -
- -
- - {!availability.productType ? ( - - ) : ( - <> - {bookingCode && ( - - )} - {(!isUserLoggedIn || - !price?.member || - (bookingCode && !fullPrice)) && - price?.public && ( - - )} - {availability.productType.member && ( - - )} - {price?.voucher && ( - - )} - {price?.bonusCheque && ( - - )} - {price?.redemptions?.length ? ( -
- - {intl.formatMessage({ - defaultMessage: "Available rates", - })} - - {price.redemptions.map((redemption) => ( - - ))} -
- ) : null} - {isDisabled ? ( -
- - {notEnoughPointsLabel} - -
- ) : ( -
- - - {intl.formatMessage({ - defaultMessage: "See rooms", - })} - - -
- )} - - )} -
-
-
- ) -} - -interface PricesWrapperProps { - children: React.ReactNode - isClickable?: boolean - hotelId: string - pathname: string - removeBookingCodeFromSearchParams: boolean - searchParams: ReadonlyURLSearchParams -} -function PricesWrapper({ - children, - hotelId, - isClickable, - pathname, - removeBookingCodeFromSearchParams, - searchParams, -}: PricesWrapperProps) { - const content =
{children}
- - if (!isClickable) { - return content - } - - const params = new URLSearchParams(searchParams) - params.delete("city") - params.set("hotel", hotelId) - - if (removeBookingCodeFromSearchParams) { - params.delete("bookingCode") - } - - const href = `${pathname}?${params.toString()}` - - return ( - - {content} - - ) -} - -export default memo(HotelCard) diff --git a/apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/index.tsx b/apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/index.tsx deleted file mode 100644 index 1292dbf7f..000000000 --- a/apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/index.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import Chip from "@scandic-hotels/design-system/Chip" -import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon" -import Image from "@scandic-hotels/design-system/Image" - -import { hotelCardDialogImageVariants } from "./variants" - -import styles from "./hotelCardDialogImage.module.css" - -import type { HotelCardDialogImageProps } from "@/types/components/hotelReservation/selectHotel/map" - -export default function HotelCardDialogImage({ - firstImage, - altText, - rating, - imageError, - setImageError, - position, -}: HotelCardDialogImageProps) { - const classNames = hotelCardDialogImageVariants({ position }) - - return ( -
- {!firstImage || imageError ? ( -
- ) : ( - {altText setImageError(true)} - /> - )} - {rating ? ( -
- - - {rating} - -
- ) : null} -
- ) -} diff --git a/apps/scandic-web/components/HotelReservation/HotelCardDialog/ListingHotelCardDialog/index.tsx b/apps/scandic-web/components/HotelReservation/HotelCardDialog/ListingHotelCardDialog/index.tsx index f91e4c454..f9dcd6b76 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCardDialog/ListingHotelCardDialog/index.tsx +++ b/apps/scandic-web/components/HotelReservation/HotelCardDialog/ListingHotelCardDialog/index.tsx @@ -1,10 +1,15 @@ "use client" + import { useSession } from "next-auth/react" import { useState } from "react" import { useIntl } from "react-intl" import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation" import Caption from "@scandic-hotels/design-system/Caption" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" +import { HotelCardDialogImage } from "@scandic-hotels/design-system/HotelCard/HotelCardDialogImage" +import { HotelPointsRow } from "@scandic-hotels/design-system/HotelCard/HotelPointsRow" +import { NoPriceAvailableCard } from "@scandic-hotels/design-system/HotelCard/NoPriceAvailableCard" import { IconButton } from "@scandic-hotels/design-system/IconButton" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import Link from "@scandic-hotels/design-system/Link" @@ -12,14 +17,9 @@ import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton import Subtitle from "@scandic-hotels/design-system/Subtitle" import { Typography } from "@scandic-hotels/design-system/Typography" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import useLang from "@/hooks/useLang" import { isValidClientSession } from "@/utils/clientSession" -import HotelPointsRow from "../../HotelCard/HotelPointsRow" -import NoPriceAvailableCard from "../../HotelCard/NoPriceAvailableCard" -import HotelCardDialogImage from "../HotelCardDialogImage" - import styles from "./listingHotelCardDialog.module.css" import type { HotelPin } from "@/types/components/hotelReservation/selectHotel/map" @@ -81,7 +81,7 @@ export default function ListingHotelCardDialog({ state.activeFilters) const setResultCount = useHotelFilterStore((state) => state.setResultCount) - const { activeHotel } = useHotelsMapStore() + const { activeHotel, activate, disengage, engage } = useHotelsMapStore() const { showBackToTop, scrollToTop } = useScrollToTop({ threshold: 490 }) const activeCardRef = useRef(null) @@ -118,32 +130,79 @@ export default function HotelCardListing({ return (
- {hotels?.length - ? hotels.map((hotel) => ( -
- ( +
+ engage(hotel.hotel.name)} + onHoverEnd={() => disengage()} + onAddressClick={() => { + const mapUrl = isAlternative + ? alternativeHotelsMap(lang) + : selectHotelMap(lang) + + disengage() // Disengage the current hotel to avoid the hover state from being active when clicking on the address + activate(hotel.hotel.name) + router.push(`${mapUrl}?${searchParams.toString()}`) + }} + belowInfoSlot={ + -
- )) - : null} + } + distanceToCityCenter={hotel.hotel.location.distanceToCentre} + images={mapApiImagesToGalleryImages(hotel.hotel.galleryImages)} + isUserLoggedIn={isUserLoggedIn} + state={ + isHotelActiveInMapView(hotel.hotel.name) ? "active" : "default" + } + type={type} + bookingCode={bookingCode} + isAlternative={isAlternative} + /> +
+ ))} {showBackToTop && ( ([]) @@ -59,7 +64,7 @@ export default function SelectHotelContent({ const listingContainerRef = useRef(null) const activeFilters = useHotelFilterStore((state) => state.activeFilters) - const { activeHotel } = useHotelsMapStore() + const hotelMapStore = useHotelsMapStore() const { showBackToTop, scrollToTop } = useScrollToTop({ threshold: 490, @@ -71,8 +76,10 @@ export default function SelectHotelContent({ ) const coordinates = useMemo(() => { - if (activeHotel) { - const hotel = hotels.find((hotel) => hotel.hotel.name === activeHotel) + if (hotelMapStore.activeHotel) { + const hotel = hotels.find( + (hotel) => hotel.hotel.name === hotelMapStore.activeHotel + ) if (hotel && hotel.hotel.location) { return isAboveMobile @@ -89,7 +96,7 @@ export default function SelectHotelContent({ return isAboveMobile ? cityCoordinates : { ...cityCoordinates, lat: cityCoordinates.lat - 0.006 } - }, [activeHotel, hotels, isAboveMobile, cityCoordinates]) + }, [hotelMapStore.activeHotel, hotels, isAboveMobile, cityCoordinates]) const showOnlyBookingCodeRates = bookingCode && @@ -231,10 +238,62 @@ export default function SelectHotelContent({ { + const galleryImage = mapApiImagesToGalleryImages(pin.images).at(0) + return { + ...pin, + ratings: { + tripAdvisor: pin.ratings ?? null, + }, + image: { + alt: galleryImage?.alt ?? "", + url: galleryImage?.src ?? "", + }, + } + })} mapId={mapId} onTilesLoaded={debouncedUpdateHotelCards} - fitBounds={isAboveMobile || !activeHotel} + fitBounds={isAboveMobile || !hotelMapStore.activeHotel} + onHoverHotelPin={(args) => { + if (!args) { + hotelMapStore.disengage() + return + } + + hotelMapStore.engage(args.hotelName) + }} + hoveredHotelPin={hotelMapStore.hoveredHotel} + onSetActiveHotelPin={(args) => { + if (!args || args.hotelName === hotelMapStore.activeHotel) { + hotelMapStore.deactivate() + return + } + + trackEvent({ + event: "hotelClickMap", + map: { + action: "hotel click - map", + }, + hotelInfo: { + hotelId: args.hotelId, + }, + }) + + hotelMapStore.activate(args.hotelName) + }} + onClickHotel={(hotelId) => { + trackEvent({ + event: "hotelClickMap", + map: { + action: "hotel click - map", + }, + hotelInfo: { + hotelId, + }, + }) + }} + lang={lang} + isUserLoggedIn={isUserLoggedIn} />
) diff --git a/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx b/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx index 0fb058514..4ca01d3b2 100644 --- a/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx @@ -2,7 +2,7 @@ import { APIProvider } from "@vis.gl/react-google-maps" -import SelectHotelMapContent from "./SelectHotelMapContent" +import { SelectHotelMapContent } from "./SelectHotelMapContent" import type { SelectHotelMapProps } from "@/types/components/hotelReservation/selectHotel/map" diff --git a/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx b/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx index a62c37f90..e246dd213 100644 --- a/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx @@ -1,7 +1,6 @@ +import { HotelCardSkeleton } from "@scandic-hotels/design-system/HotelCard/HotelCardSkeleton" import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" -import { HotelCardSkeleton } from "../HotelCard/HotelCardSkeleton" - import styles from "./selectHotel.module.css" type Props = { diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/HotelDescription/index.tsx b/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/HotelDescription/index.tsx index 6cc681ca0..9edea75dc 100644 --- a/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/HotelDescription/index.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/HotelDescription/index.tsx @@ -4,9 +4,9 @@ import { useState } from "react" import { Button as ButtonRAC } from "react-aria-components" import { useIntl } from "react-intl" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import { Typography } from "@scandic-hotels/design-system/Typography" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import HotelDetailsSidePeek from "@/components/SidePeeks/HotelDetailsSidePeek" import Alert from "@/components/TempDesignSystem/Alert" diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx b/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx index e8794049b..35dac0334 100644 --- a/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx @@ -1,12 +1,12 @@ -import TripAdvisorChip from "@scandic-hotels/booking-flow/components/TripAdvisorChip" import { dt } from "@scandic-hotels/common/dt" import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting" import { Divider } from "@scandic-hotels/design-system/Divider" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import ImageGallery from "@scandic-hotels/design-system/ImageGallery" import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" +import { TripAdvisorChip } from "@scandic-hotels/design-system/TripAdvisorChip" import { Typography } from "@scandic-hotels/design-system/Typography" -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import HotelDetailsSidePeek from "@/components/SidePeeks/HotelDetailsSidePeek" import Alert from "@/components/TempDesignSystem/Alert" import { getIntl } from "@/i18n" diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils.ts b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils.ts index d24d6a7f3..c46c0db33 100644 --- a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils.ts +++ b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils.ts @@ -1,5 +1,5 @@ import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" -import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType" +import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType" import { sumPackages } from "@/components/HotelReservation/utils" diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/BookingCodeFilter/index.tsx b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/BookingCodeFilter/index.tsx index cac568243..914af78cb 100644 --- a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/BookingCodeFilter/index.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/BookingCodeFilter/index.tsx @@ -17,7 +17,7 @@ import { ChipButton } from "@scandic-hotels/design-system/ChipButton" import { IconButton } from "@scandic-hotels/design-system/IconButton" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { Typography } from "@scandic-hotels/design-system/Typography" -import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType" +import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType" import { useSelectRateContext } from "@/contexts/SelectRate/SelectRateContext" import { useBreakpoint } from "@/hooks/useBreakpoint" diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/RemoveBookingCodeButton/RemoveBookingCodeButton.tsx b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/RemoveBookingCodeButton/RemoveBookingCodeButton.tsx index 197f24556..d8663c4b0 100644 --- a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/RemoveBookingCodeButton/RemoveBookingCodeButton.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomsHeader/RemoveBookingCodeButton/RemoveBookingCodeButton.tsx @@ -1,6 +1,7 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation" -import BookingCodeChip from "@/components/BookingCodeChip" +import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip" + import { useSelectRateContext } from "@/contexts/SelectRate/SelectRateContext" export function RemoveBookingCodeButton() { diff --git a/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx b/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx deleted file mode 100644 index e7ef85531..000000000 --- a/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { - AdvancedMarker, - AdvancedMarkerAnchorPoint, - InfoWindow, -} from "@vis.gl/react-google-maps" -import { useCallback } from "react" -import { useMediaQuery } from "usehooks-ts" - -import { useHotelsMapStore } from "@/stores/hotels-map" - -import StandaloneHotelCardDialog from "@/components/HotelReservation/HotelCardDialog/StandaloneHotelCardDialog" -import { trackEvent } from "@/utils/tracking/base" - -import HotelPin from "./HotelPin" - -import styles from "./hotelListingMapContent.module.css" - -import type { HotelListingMapContentProps } from "@/types/components/hotelReservation/selectHotel/map" - -function HotelListingMapContent({ hotelPins }: HotelListingMapContentProps) { - const { activeHotel, hoveredHotel, activate, deactivate, engage, disengage } = - useHotelsMapStore() - const isDesktop = useMediaQuery("(min-width: 768px)") - - const toggleActiveHotelPin = useCallback( - (pinName: string | null, hotelId: string) => { - if (activeHotel === pinName || pinName === null) { - deactivate() - return - } - trackEvent({ - event: "hotelClickMap", - map: { - action: "hotel click - map", - }, - hotelInfo: { - hotelId, - }, - }) - activate(pinName) - }, - [activeHotel, activate, deactivate] - ) - - return ( -
- {hotelPins.map((pin) => { - const isActiveOrHovered = - activeHotel === pin.name || hoveredHotel === pin.name - const hotelPrice = - pin.memberPrice ?? - pin.publicPrice ?? - pin.redemptionPrice ?? - pin.voucherPrice ?? - pin.chequePrice?.numberOfCheques ?? - null - - const hotelAdditionalPrice = pin.chequePrice - ? pin.chequePrice.additionalPricePerStay - : undefined - const hotelAdditionalCurrency = pin.chequePrice - ? pin.chequePrice.currency?.toString() - : undefined - return ( - engage(pin.name)} - onMouseLeave={() => disengage()} - onClick={() => toggleActiveHotelPin(pin.name, pin.operaId)} - > - {isActiveOrHovered && isDesktop && ( - - { - deactivate() - disengage() - }} - /> - - )} - - - ) - })} -
- ) -} - -export default HotelListingMapContent diff --git a/apps/scandic-web/components/Maps/InteractiveMap/index.tsx b/apps/scandic-web/components/Maps/InteractiveMap/index.tsx deleted file mode 100644 index 27648bc86..000000000 --- a/apps/scandic-web/components/Maps/InteractiveMap/index.tsx +++ /dev/null @@ -1,114 +0,0 @@ -"use client" - -import { Map, type MapProps, useMap } from "@vis.gl/react-google-maps" -import { useEffect, useState } from "react" -import { useIntl } from "react-intl" - -import { IconButton } from "@scandic-hotels/design-system/IconButton" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" - -import { - DEFAULT_ZOOM, - MAP_RESTRICTIONS, - MAX_ZOOM, - MIN_ZOOM, -} from "@/constants/map" - -import { useZoomControls } from "@/hooks/maps/useZoomControls" - -import HotelListingMapContent from "./HotelListingMapContent" -import PoiMapMarkers from "./PoiMapMarkers" - -import styles from "./interactiveMap.module.css" - -import type { InteractiveMapProps } from "@/types/components/hotelPage/map/interactiveMap" - -export default function InteractiveMap({ - coordinates, - pointsOfInterest, - activePoi, - hotelPins, - mapId, - closeButton, - markerInfo, - fitBounds = true, - onTilesLoaded, - onActivePoiChange, -}: InteractiveMapProps) { - const intl = useIntl() - const map = useMap() - const [hasInitializedBounds, setHasInitializedBounds] = useState(false) - const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = useZoomControls() - - const mapOptions: MapProps = { - defaultZoom: DEFAULT_ZOOM, - minZoom: MIN_ZOOM, - maxZoom: MAX_ZOOM, - defaultCenter: coordinates, - disableDefaultUI: true, - clickableIcons: false, - mapId, - gestureHandling: "greedy", - restriction: MAP_RESTRICTIONS, - } - - useEffect(() => { - if (map && hotelPins?.length && !hasInitializedBounds) { - if (fitBounds) { - const bounds = new google.maps.LatLngBounds() - hotelPins.forEach((marker) => { - bounds.extend(marker.coordinates) - }) - map.fitBounds(bounds, 100) - } - setHasInitializedBounds(true) - } - }, [map, fitBounds, hotelPins, hasInitializedBounds]) - - return ( -
- - {hotelPins && } - {pointsOfInterest && markerInfo && ( - - )} - -
- {closeButton} -
- - - - - - - -
-
-
- ) -} diff --git a/apps/scandic-web/components/Maps/Markers/Poi/index.tsx b/apps/scandic-web/components/Maps/Markers/Poi/index.tsx deleted file mode 100644 index b73ad7de2..000000000 --- a/apps/scandic-web/components/Maps/Markers/Poi/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { IconByIconName } from "@scandic-hotels/design-system/Icons/IconByIconName" - -import { getIconByPoiGroupAndCategory } from "../utils" -import { poiVariants } from "./variants" - -import type { PoiMarkerProps } from "@/types/components/maps/poiMarker" - -export default function PoiMarker({ - group, - categoryName, - skipBackground, - size = "small", - className = "", -}: PoiMarkerProps) { - const iconName = getIconByPoiGroupAndCategory(group, categoryName) - const classNames = poiVariants({ group, skipBackground, size, className }) - - return iconName ? ( - - - - ) : null -} diff --git a/apps/scandic-web/components/Maps/Markers/Poi/variants.ts b/apps/scandic-web/components/Maps/Markers/Poi/variants.ts deleted file mode 100644 index e6f0d58df..000000000 --- a/apps/scandic-web/components/Maps/Markers/Poi/variants.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { cva } from "class-variance-authority" - -import { PointOfInterestGroupEnum } from "@scandic-hotels/trpc/enums/pointOfInterest" - -import styles from "./poi.module.css" - -export const poiVariants = cva(styles.icon, { - variants: { - group: { - [PointOfInterestGroupEnum.ATTRACTIONS]: styles.attractions, - [PointOfInterestGroupEnum.BUSINESS]: styles.business, - [PointOfInterestGroupEnum.LOCATION]: styles.location, - [PointOfInterestGroupEnum.PARKING]: styles.parking, - [PointOfInterestGroupEnum.PUBLIC_TRANSPORT]: styles.publicTransport, - [PointOfInterestGroupEnum.SHOPPING_DINING]: styles.shoppingDining, - }, - skipBackground: { - true: styles.transparent, - false: "", - }, - size: { - small: styles.small, - medium: styles.small, - large: styles.large, - }, - }, - defaultVariants: { - skipBackground: false, - size: "small", - }, -}) diff --git a/apps/scandic-web/components/Maps/Markers/index.tsx b/apps/scandic-web/components/Maps/Markers/index.tsx deleted file mode 100644 index b8175709c..000000000 --- a/apps/scandic-web/components/Maps/Markers/index.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { HotelTypeEnum } from "@scandic-hotels/trpc/enums/hotelType" - -import DowntownCamperMarker from "./DowntownCamper" -import DowntownCamperSmallMarker from "./DowntownCamperSmall" -import GrandHotelMarker from "./GrandHotel" -import GrandHotelSmallMarker from "./GrandHotelSmall" -import HaymarketMarker from "./Haymarket" -import HaymarketSmallMarker from "./HaymarketSmall" -import HotelNorgeMarker from "./HotelNorge" -import HotelNorgeSmallMarker from "./HotelNorgeSmall" -import MarskiMarker from "./Marski" -import MarskiSmallMarker from "./MarskiSmall" -import ScandicMarker from "./Scandic" -import ScandicGoMarker from "./ScandicGo" -import ScandicGoSmallMarker from "./ScandicGoSmall" -import ScandicSmallMarker from "./ScandicSmall" -import TheDockMarker from "./TheDock" -import TheDockSmallMarker from "./TheDockSmall" - -import type { MarkerInfo } from "@scandic-hotels/trpc/types/marker" - -import { SignatureHotelEnum } from "@/types/enums/signatureHotel" - -interface HotelMarkerByTypeProps - extends MarkerInfo, - React.SVGAttributes { - size?: "large" | "small" -} - -export default function HotelMarkerByType({ - hotelId, - hotelType, - size = "large", - ...props -}: HotelMarkerByTypeProps) { - if (hotelType === HotelTypeEnum.ScandicGo) { - return size === "small" ? ( - - ) : ( - - ) - } - - switch (hotelId) { - case SignatureHotelEnum.Haymarket: - return size === "small" ? ( - - ) : ( - - ) - case SignatureHotelEnum.HotelNorge: - return size === "small" ? ( - - ) : ( - - ) - case SignatureHotelEnum.DowntownCamper: - return size === "small" ? ( - - ) : ( - - ) - case SignatureHotelEnum.GrandHotelOslo: - return size === "small" ? ( - - ) : ( - - ) - case SignatureHotelEnum.Marski: - return size === "small" ? ( - - ) : ( - - ) - case SignatureHotelEnum.TheDock: - return size === "small" ? ( - - ) : ( - - ) - - default: - return size === "small" ? ( - - ) : ( - - ) - } -} diff --git a/apps/scandic-web/components/Maps/Markers/utils.ts b/apps/scandic-web/components/Maps/Markers/utils.ts deleted file mode 100644 index f02746f82..000000000 --- a/apps/scandic-web/components/Maps/Markers/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { IconName } from "@scandic-hotels/design-system/Icons/iconName" -import { PointOfInterestGroupEnum } from "@scandic-hotels/trpc/enums/pointOfInterest" - -export function getIconByPoiGroupAndCategory( - group: PointOfInterestGroupEnum, - category?: string -) { - switch (group) { - case PointOfInterestGroupEnum.PUBLIC_TRANSPORT: - return category === "Airport" ? IconName.Airplane : IconName.Train - case PointOfInterestGroupEnum.ATTRACTIONS: - return category === "Museum" ? IconName.Museum : IconName.Camera - case PointOfInterestGroupEnum.BUSINESS: - return IconName.Business - case PointOfInterestGroupEnum.PARKING: - return IconName.Parking - case PointOfInterestGroupEnum.SHOPPING_DINING: - return category === "Restaurant" ? IconName.Restaurant : IconName.Shopping - case PointOfInterestGroupEnum.LOCATION: - default: - return IconName.Location - } -} diff --git a/apps/scandic-web/components/Webviews/LinkToOverview/index.tsx b/apps/scandic-web/components/Webviews/LinkToOverview/index.tsx index 5d5f8df89..e7958e99c 100644 --- a/apps/scandic-web/components/Webviews/LinkToOverview/index.tsx +++ b/apps/scandic-web/components/Webviews/LinkToOverview/index.tsx @@ -3,13 +3,13 @@ import { ArrowLeft } from "react-feather" import Link from "@scandic-hotels/design-system/Link" import { overview } from "@/constants/routes/webviews" +import { env } from "@/env/server" import { getIntl } from "@/i18n" import { getLang } from "@/i18n/serverContext" import { webviewSearchParams } from "@/utils/webviews" import styles from "./linkToOverview.module.css" -import { env } from "@/env/server" export default async function LinkToOverview() { if (!env.WEBVIEW_SHOW_OVERVIEW) { diff --git a/apps/scandic-web/public/_static/css/design-system-new-deprecated.css b/apps/scandic-web/public/_static/css/design-system-new-deprecated.css deleted file mode 100644 index 0c0505e7a..000000000 --- a/apps/scandic-web/public/_static/css/design-system-new-deprecated.css +++ /dev/null @@ -1 +0,0 @@ -:root{--typography-Body-Bold-Desktop-fontSize: 16px;--typography-Body-Bold-fontFamily: "fira sans";--typography-Body-Bold-fontSize: 16px;--typography-Body-Bold-fontWeight: "medium";--typography-Body-Bold-letterSpacing: 1.2000000476837158%;--typography-Body-Bold-lineHeight: 150%;--typography-Body-Bold-Mobile-fontSize: 16px;--typography-Body-Bold-Tablet-estimate-fontSize: 16px;--typography-Body-Bold-textCase: "original";--typography-Body-Bold-textDecoration: "none";--typography-Body-Inline-Desktop-fontSize: 16px;--typography-Body-Inline-fontFamily: "fira sans";--typography-Body-Inline-fontSize: 16px;--typography-Body-Inline-fontWeight: "regular";--typography-Body-Inline-letterSpacing: 1.2000000476837158%;--typography-Body-Inline-lineHeight: 150%;--typography-Body-Inline-Mobile-fontSize: 16px;--typography-Body-Inline-Tablet-estimate-fontSize: 16px;--typography-Body-Inline-textCase: "original";--typography-Body-Inline-textDecoration: "underline";--typography-Body-Link-Desktop-fontSize: 16px;--typography-Body-Link-Mobile-fontSize: 16px;--typography-Body-Link-Tablet-estimate-fontSize: 16px;--typography-Body-Regular-Desktop-fontSize: 16px;--typography-Body-Regular-fontFamily: "fira sans";--typography-Body-Regular-fontSize: 16px;--typography-Body-Regular-fontWeight: "regular";--typography-Body-Regular-letterSpacing: 1.2000000476837158%;--typography-Body-Regular-lineHeight: 150%;--typography-Body-Regular-Mobile-fontSize: 16px;--typography-Body-Regular-Tablet-estimate-fontSize: 16px;--typography-Body-Regular-textCase: "original";--typography-Body-Regular-textDecoration: "none";--typography-Body-Underline-fontFamily: "fira sans";--typography-Body-Underline-fontSize: 16px;--typography-Body-Underline-fontWeight: "medium";--typography-Body-Underline-letterSpacing: 1.2000000476837158%;--typography-Body-Underline-lineHeight: 150%;--typography-Body-Underline-textCase: "original";--typography-Body-Underline-textDecoration: "underline";--typography-Caption-Bold-Desktop-fontSize: 14px;--typography-Caption-Bold-fontFamily: "fira sans";--typography-Caption-Bold-fontSize: 14px;--typography-Caption-Bold-fontWeight: "medium";--typography-Caption-Bold-letterSpacing: 1.399999976158142%;--typography-Caption-Bold-lineHeight: 139.9999976158142%;--typography-Caption-Bold-Mobile-fontSize: 14px;--typography-Caption-Bold-Tablet-estimate-fontSize: 14px;--typography-Caption-Bold-textCase: "original";--typography-Caption-Bold-textDecoration: "none";--typography-Caption-Inline-Desktop-fontSize: 14px;--typography-Caption-Inline-fontFamily: "fira sans";--typography-Caption-Inline-fontSize: 14px;--typography-Caption-Inline-fontWeight: "regular";--typography-Caption-Inline-letterSpacing: 1.399999976158142%;--typography-Caption-Inline-lineHeight: 139.9999976158142%;--typography-Caption-Inline-Mobile-fontSize: 14px;--typography-Caption-Inline-Tablet-estimate-fontSize: 14px;--typography-Caption-Inline-textCase: "original";--typography-Caption-Inline-textDecoration: "underline";--typography-Caption-Labels-fontFamily: "brandon text";--typography-Caption-Labels-fontSize: 14px;--typography-Caption-Labels-fontWeight: "bold";--typography-Caption-Labels-letterSpacing: 1.399999976158142%;--typography-Caption-Labels-lineHeight: 150%;--typography-Caption-Labels-textCase: "upper";--typography-Caption-Labels-textDecoration: "none";--typography-Caption-Link-Desktop-fontSize: 14px;--typography-Caption-Link-Mobile-fontSize: 14px;--typography-Caption-Link-Tablet-estimate-fontSize: 14px;--typography-Caption-Regular-Desktop-fontSize: 14px;--typography-Caption-Regular-fontFamily: "fira sans";--typography-Caption-Regular-fontSize: 14px;--typography-Caption-Regular-fontWeight: "regular";--typography-Caption-Regular-letterSpacing: 1.399999976158142%;--typography-Caption-Regular-lineHeight: 139.9999976158142%;--typography-Caption-Regular-Mobile-fontSize: 14px;--typography-Caption-Regular-Tablet-estimate-fontSize: 14px;--typography-Caption-Regular-textCase: "original";--typography-Caption-Regular-textDecoration: "none";--typography-Caption-Underline-fontFamily: "fira sans";--typography-Caption-Underline-fontSize: 14px;--typography-Caption-Underline-fontWeight: "medium";--typography-Caption-Underline-letterSpacing: 1.399999976158142%;--typography-Caption-Underline-lineHeight: 139.9999976158142%;--typography-Caption-Underline-textCase: "original";--typography-Caption-Underline-textDecoration: "underline";--typography-Foot-note-Bold-Desktop-fontSize: 12px;--typography-Foot-note-Bold-Mobile-fontSize: 12px;--typography-Foot-note-Bold-Tablet-estimate-fontSize: 12px;--typography-Foot-note-Regular-Desktop-fontSize: 12px;--typography-Foot-note-Regular-Mobile-fontSize: 12px;--typography-Foot-note-Regular-Tablet-estimate-fontSize: 12px;--typography-Footnote-Bold-fontFamily: "fira sans";--typography-Footnote-Bold-fontSize: 12px;--typography-Footnote-Bold-fontWeight: "medium";--typography-Footnote-Bold-letterSpacing: 1.399999976158142%;--typography-Footnote-Bold-lineHeight: 150%;--typography-Footnote-Bold-textCase: "original";--typography-Footnote-Bold-textDecoration: "none";--typography-Footnote-Labels-fontFamily: "brandon text";--typography-Footnote-Labels-fontSize: 12px;--typography-Footnote-Labels-fontWeight: "bold";--typography-Footnote-Labels-letterSpacing: 1.399999976158142%;--typography-Footnote-Labels-lineHeight: 150%;--typography-Footnote-Labels-textCase: "upper";--typography-Footnote-Labels-textDecoration: "none";--typography-Footnote-Regular-fontFamily: "fira sans";--typography-Footnote-Regular-fontSize: 12px;--typography-Footnote-Regular-fontWeight: "regular";--typography-Footnote-Regular-letterSpacing: 1.399999976158142%;--typography-Footnote-Regular-lineHeight: 150%;--typography-Footnote-Regular-textCase: "original";--typography-Footnote-Regular-textDecoration: "none";--typography-Preamble-Desktop-fontSize: 20px;--typography-Preamble-fontFamily: "fira sans";--typography-Preamble-fontSize: 20px;--typography-Preamble-fontWeight: "regular";--typography-Preamble-letterSpacing: 1%;--typography-Preamble-lineHeight: 139.9999976158142%;--typography-Preamble-Mobile-fontSize: 18px;--typography-Preamble-Tablet-estimate-fontSize: 19px;--typography-Preamble-textCase: "original";--typography-Preamble-textDecoration: "none";--typography-Script-1-Desktop-fontSize: 32px;--typography-Script-1-fontFamily: "biro script plus";--typography-Script-1-fontSize: 32px;--typography-Script-1-fontWeight: "regular";--typography-Script-1-letterSpacing: 2%;--typography-Script-1-lineHeight: 110.00000238418579%;--typography-Script-1-Mobile-fontSize: 24px;--typography-Script-1-Tablet-estimate-fontSize: 29px;--typography-Script-1-textCase: "original";--typography-Script-1-textDecoration: "none";--typography-Script-2-Desktop-fontSize: 24px;--typography-Script-2-fontFamily: "biro script plus";--typography-Script-2-fontSize: 24px;--typography-Script-2-fontWeight: "regular";--typography-Script-2-letterSpacing: 2%;--typography-Script-2-lineHeight: 110.00000238418579%;--typography-Script-2-Mobile-fontSize: 20px;--typography-Script-2-Tablet-estimate-fontSize: 22px;--typography-Script-2-textCase: "original";--typography-Script-2-textDecoration: "none";--typography-Subtitle-1-Desktop-fontSize: 24px;--typography-Subtitle-1-fontFamily: "fira sans";--typography-Subtitle-1-fontSize: 24px;--typography-Subtitle-1-fontWeight: "medium";--typography-Subtitle-1-letterSpacing: 1%;--typography-Subtitle-1-lineHeight: 120.00000476837158%;--typography-Subtitle-1-Mobile-fontSize: 20px;--typography-Subtitle-1-Tablet-estimate-fontSize: 22px;--typography-Subtitle-1-textCase: "original";--typography-Subtitle-1-textDecoration: "none";--typography-Subtitle-2-Desktop-fontSize: 20px;--typography-Subtitle-2-fontFamily: "fira sans";--typography-Subtitle-2-fontSize: 20px;--typography-Subtitle-2-fontWeight: "medium";--typography-Subtitle-2-letterSpacing: 1%;--typography-Subtitle-2-lineHeight: 120.00000476837158%;--typography-Subtitle-2-Mobile-fontSize: 18px;--typography-Subtitle-2-Tablet-estimate-fontSize: 19px;--typography-Subtitle-2-textCase: "original";--typography-Subtitle-2-textDecoration: "none";--typography-Title-1-Desktop-fontSize: 64px;--typography-Title-1-fontFamily: "brandon text";--typography-Title-1-fontSize: 64px;--typography-Title-1-fontWeight: "black";--typography-Title-1-letterSpacing: .25%;--typography-Title-1-lineHeight: 110.00000238418579%;--typography-Title-1-Mobile-fontSize: 48px;--typography-Title-1-Tablet-estimate-fontSize: 60px;--typography-Title-1-textCase: "upper";--typography-Title-1-textDecoration: "none";--typography-Title-2-Desktop-fontSize: 48px;--typography-Title-2-fontFamily: "brandon text";--typography-Title-2-fontSize: 48px;--typography-Title-2-fontWeight: "black";--typography-Title-2-letterSpacing: .25%;--typography-Title-2-lineHeight: 110.00000238418579%;--typography-Title-2-Mobile-fontSize: 36px;--typography-Title-2-Tablet-estimate-fontSize: 44px;--typography-Title-2-textCase: "upper";--typography-Title-2-textDecoration: "none";--typography-Title-3-Desktop-fontSize: 36px;--typography-Title-3-fontFamily: "brandon text";--typography-Title-3-fontSize: 36px;--typography-Title-3-fontWeight: "black";--typography-Title-3-letterSpacing: .25%;--typography-Title-3-lineHeight: 110.00000238418579%;--typography-Title-3-Mobile-fontSize: 30px;--typography-Title-3-Tablet-estimate-fontSize: 34px;--typography-Title-3-textCase: "upper";--typography-Title-3-textDecoration: "none";--typography-Title-4-Desktop-fontSize: 28px;--typography-Title-4-fontFamily: "brandon text";--typography-Title-4-fontSize: 28px;--typography-Title-4-fontWeight: "bold";--typography-Title-4-letterSpacing: .25%;--typography-Title-4-lineHeight: 110.00000238418579%;--typography-Title-4-Mobile-fontSize: 24px;--typography-Title-4-Tablet-estimate-fontSize: 26px;--typography-Title-4-textCase: "original";--typography-Title-4-textDecoration: "none";--typography-Title-5-Desktop-fontSize: 24px;--typography-Title-5-fontFamily: "brandon text";--typography-Title-5-fontSize: 24px;--typography-Title-5-fontWeight: "black";--typography-Title-5-letterSpacing: .25%;--typography-Title-5-lineHeight: 110.00000238418579%;--typography-Title-5-Mobile-fontSize: 20px;--typography-Title-5-Tablet-estimate-fontSize: 21px;--typography-Title-5-textCase: "upper";--typography-Title-5-textDecoration: "none"}:root{--Base-Background-Primary-Elevated: var(--Scandic-Beige-00);--Base-Background-Primary-Normal: var(--Scandic-Beige-00);--Base-Border-Hover: var(--Scandic-Peach-80);--Base-Border-Inverted: var(--UI-Opacity-White-100);--Base-Border-Normal: var(--Scandic-Beige-40);--Base-Border-Subtle: var(--Scandic-Beige-20);--Base-Button-Inverted-Border-Disabled: var(--UI-Opacity-White-0);--Base-Button-Inverted-Border-Hover: var(--UI-Opacity-White-0);--Base-Button-Inverted-Border-Normal: var(--UI-Opacity-White-0);--Base-Button-Inverted-Fill-Disabled: var(--UI-Grey-20);--Base-Button-Inverted-Fill-Hover: var(--Scandic-Beige-10);--Base-Button-Inverted-Fill-Hover-alt: var(--Scandic-Peach-10);--Base-Button-Inverted-Fill-Normal: var(--UI-Opacity-White-100);--Base-Button-Inverted-On-Fill-Disabled: var(--UI-Grey-40);--Base-Button-Inverted-On-Fill-Hover: var(--Scandic-Red-90);--Base-Button-Inverted-On-Fill-Normal: var(--Scandic-Red-100);--Base-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Base-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Base-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Base-Button-Primary-Fill-Disabled: var(--UI-Grey-20);--Base-Button-Primary-Fill-Hover: var(--Scandic-Red-70);--Base-Button-Primary-Fill-Normal: var(--Scandic-Red-60);--Base-Button-Primary-On-Fill-Disabled: var(--UI-Grey-40);--Base-Button-Primary-On-Fill-Hover: var(--UI-Opacity-White-100);--Base-Button-Primary-On-Fill-Normal: var(--UI-Opacity-White-100);--Base-Button-Secondary-Border-Disabled: var(--UI-Grey-30);--Base-Button-Secondary-Border-Hover: var(--Scandic-Peach-80);--Base-Button-Secondary-Border-Normal: var(--Scandic-Red-100);--Base-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Base-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Base-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Base-Button-Secondary-On-Fill-Disabled: var(--UI-Grey-40);--Base-Button-Secondary-On-Fill-Hover: var(--Scandic-Peach-80);--Base-Button-Secondary-On-Fill-Normal: var(--Scandic-Red-100);--Base-Button-Tertiary-Border-Disabled: var(--UI-Opacity-White-0);--Base-Button-Tertiary-Border-Hover: var(--UI-Opacity-White-0);--Base-Button-Tertiary-Border-Normal: var(--UI-Opacity-White-0);--Base-Button-Tertiary-Fill-Disabled: var(--UI-Grey-20);--Base-Button-Tertiary-Fill-Hover: var(--Scandic-Red-90);--Base-Button-Tertiary-Fill-Normal: var(--Scandic-Red-100);--Base-Button-Tertiary-On-Fill-Disabled: var(--UI-Grey-40);--Base-Button-Tertiary-On-Fill-Hover: var(--UI-Opacity-White-100);--Base-Button-Tertiary-On-Fill-Normal: var(--UI-Opacity-White-100);--Base-Button-Text-Border-Disabled: var(--UI-Opacity-White-0);--Base-Button-Text-Border-Hover: var(--UI-Opacity-White-0);--Base-Button-Text-Border-Normal: var(--UI-Opacity-White-0);--Base-Button-Text-Fill-Disabled: var(--UI-Opacity-White-0);--Base-Button-Text-Fill-Hover: var(--UI-Opacity-White-0);--Base-Button-Text-Fill-Normal: var(--UI-Opacity-White-0);--Base-Button-Text-On-Fill-Disabled: var(--UI-Grey-40);--Base-Button-Text-On-Fill-Hover: var(--Scandic-Peach-80);--Base-Button-Text-On-Fill-Normal: var(--Scandic-Red-100);--Base-Icon-Low-contrast: var(--Scandic-Peach-70);--Base-Interactive-Surface-Primary-normal: var(--Scandic-Red-80);--Base-Interactive-Surface-Secondary-normal: var(--Scandic-Green-70);--Base-Interactive-Surface-Tertiary-normal: var(--Scandic-Blue-60);--Base-Surface-Primary-dark-Hover: var(--Scandic-Peach-20);--Base-Surface-Primary-dark-Normal: var(--Scandic-Peach-10);--Base-Surface-Primary-light-Hover: var(--UI-Grey-00);--Base-Surface-Primary-light-Hover-alt: var(--Scandic-Beige-10);--Base-Surface-Primary-light-Normal: var(--UI-Opacity-White-100);--Base-Surface-Secondary-light-Hover: var(--Scandic-Peach-10);--Base-Surface-Secondary-light-Hover-alt: var(--Scandic-Peach-20);--Base-Surface-Secondary-light-Normal: var(--Scandic-Beige-00);--Base-Surface-Subtle-Hover: var(--Scandic-Beige-20);--Base-Surface-Subtle-Normal: var(--Scandic-Beige-10);--Base-Text-Accent: var(--Scandic-Red-60);--Base-Text-Disabled: var(--UI-Grey-40);--Base-Text-High-contrast: var(--Scandic-Red-100);--Base-Text-Inverted: var(--UI-Opacity-White-100);--Base-Text-Medium-contrast: var(--Scandic-Peach-80);--Primary-Dark-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Primary-Dark-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Primary-Dark-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Primary-Dark-Button-Primary-Fill-Disabled: var(--UI-Opacity-White-20);--Primary-Dark-Button-Primary-Fill-Hover: var(--Scandic-Peach-20);--Primary-Dark-Button-Primary-Fill-Normal: var(--Scandic-Peach-10);--Primary-Dark-Button-Primary-On-Fill-Disabled: var(--UI-Opacity-White-30);--Primary-Dark-Button-Primary-On-Fill-Hover: var(--Scandic-Red-80);--Primary-Dark-Button-Primary-On-Fill-Normal: var(--Scandic-Red-100);--Primary-Dark-Button-Secondary-Border-Disabled: var(--UI-Opacity-White-20);--Primary-Dark-Button-Secondary-Border-Hover: var(--Scandic-Peach-30);--Primary-Dark-Button-Secondary-Border-Normal: var(--Scandic-Peach-10);--Primary-Dark-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Primary-Dark-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Primary-Dark-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Primary-Dark-Button-Secondary-On-Fill-Disabled: var(--UI-Opacity-White-30);--Primary-Dark-Button-Secondary-On-Fill-Hover: var(--Scandic-Peach-30);--Primary-Dark-Button-Secondary-On-Fill-Normal: var(--Scandic-Peach-10);--Primary-Dark-On-Surface-Accent: var(--Scandic-Peach-50);--Primary-Dark-On-Surface-Divider: var(--Scandic-Peach-80);--Primary-Dark-On-Surface-Text: var(--Scandic-Peach-10);--Primary-Dark-Surface-Hover: var(--Scandic-Red-90);--Primary-Dark-Surface-Normal: var(--Scandic-Red-100);--Primary-Dim-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Primary-Dim-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Primary-Dim-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Primary-Dim-Button-Primary-Fill-Disabled: var(--UI-Opacity-Almost-Black-10);--Primary-Dim-Button-Primary-Fill-Hover: var(--Scandic-Red-80);--Primary-Dim-Button-Primary-Fill-Normal: var(--Scandic-Red-100);--Primary-Dim-Button-Primary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Primary-Dim-Button-Primary-On-Fill-Hover: var(--Scandic-Peach-30);--Primary-Dim-Button-Primary-On-Fill-Normal: var(--Scandic-Peach-10);--Primary-Dim-Button-Secondary-Border-Disabled: var( --UI-Opacity-Almost-Black-20 );--Primary-Dim-Button-Secondary-Border-Hover: var(--Scandic-Red-80);--Primary-Dim-Button-Secondary-Border-Normal: var(--Scandic-Red-100);--Primary-Dim-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Primary-Dim-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Primary-Dim-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Primary-Dim-Button-Secondary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Primary-Dim-Button-Secondary-On-Fill-Hover: var(--Scandic-Red-80);--Primary-Dim-Button-Secondary-On-Fill-Normal: var(--Scandic-Red-100);--Primary-Dim-On-Surface-Accent: var(--Scandic-Peach-80);--Primary-Dim-On-Surface-Divider: var(--Scandic-Peach-40);--Primary-Dim-On-Surface-Text: var(--Scandic-Red-100);--Primary-Dim-Surface-Hover: var(--Scandic-Peach-40);--Primary-Dim-Surface-Normal: var(--Scandic-Peach-30);--Primary-Light-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Primary-Light-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Primary-Light-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Primary-Light-Button-Primary-Fill-Disabled: var( --UI-Opacity-Almost-Black-10 );--Primary-Light-Button-Primary-Fill-Hover: var(--Scandic-Red-80);--Primary-Light-Button-Primary-Fill-Normal: var(--Scandic-Red-100);--Primary-Light-Button-Primary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Primary-Light-Button-Primary-On-Fill-Hover: var(--Scandic-Peach-30);--Primary-Light-Button-Primary-On-Fill-Normal: var(--Scandic-Peach-10);--Primary-Light-Button-Secondary-Border-Disabled: var( --UI-Opacity-Almost-Black-20 );--Primary-Light-Button-Secondary-Border-Hover: var(--Scandic-Red-80);--Primary-Light-Button-Secondary-Border-Normal: var(--Scandic-Red-100);--Primary-Light-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Primary-Light-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Primary-Light-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Primary-Light-Button-Secondary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Primary-Light-Button-Secondary-On-Fill-Hover: var(--Scandic-Red-80);--Primary-Light-Button-Secondary-On-Fill-Normal: var(--Scandic-Red-100);--Primary-Light-On-Surface-Accent: var(--Scandic-Red-60);--Primary-Light-On-Surface-Divider: var(--Scandic-Peach-30);--Primary-Light-On-Surface-Divider-subtle: var(--Scandic-Beige-10);--Primary-Light-On-Surface-Text: var(--Scandic-Red-100);--Primary-Light-Surface-Hover: var(--Scandic-Peach-20);--Primary-Light-Surface-Normal: var(--Scandic-Peach-10);--Primary-Strong-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Primary-Strong-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Primary-Strong-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Primary-Strong-Button-Primary-Fill-Disabled: var(--UI-Opacity-White-20);--Primary-Strong-Button-Primary-Fill-Hover: var(--Scandic-Red-00);--Primary-Strong-Button-Primary-Fill-Normal: var(--UI-Opacity-White-100);--Primary-Strong-Button-Primary-On-Fill-Disabled: var(--UI-Opacity-White-20);--Primary-Strong-Button-Primary-On-Fill-Hover: var(--Scandic-Red-70);--Primary-Strong-Button-Primary-On-Fill-Normal: var(--Scandic-Red-70);--Primary-Strong-Button-Secondary-Border-Disabled: var(--UI-Opacity-White-20);--Primary-Strong-Button-Secondary-Border-Hover: var(--Scandic-Peach-00);--Primary-Strong-Button-Secondary-Border-Normal: var(--UI-Opacity-White-100);--Primary-Strong-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Primary-Strong-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Primary-Strong-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Primary-Strong-Button-Secondary-On-Fill-Disabled: var( --UI-Opacity-White-20 );--Primary-Strong-Button-Secondary-On-Fill-Hover: var(--Scandic-Red-00);--Primary-Strong-Button-Secondary-On-Fill-Normal: var(--UI-Opacity-White-100);--Primary-Strong-On-Surface-Accent: var(--Scandic-Peach-10);--Primary-Strong-On-Surface-Divider: var(--Scandic-Red-70);--Primary-Strong-On-Surface-Text: var(--UI-Opacity-White-100);--Primary-Strong-Surface-Hover: var(--Scandic-Red-70);--Primary-Strong-Surface-Normal: var(--Scandic-Red-60);--Secondary-Dark-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Secondary-Dark-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Secondary-Dark-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Secondary-Dark-Button-Primary-Fill-Disabled: var(--UI-Opacity-White-10);--Secondary-Dark-Button-Primary-Fill-Hover: var(--Scandic-Green-30);--Secondary-Dark-Button-Primary-Fill-Normal: var(--Scandic-Green-20);--Secondary-Dark-Button-Primary-On-Fill-Disabled: var(--UI-Opacity-White-20);--Secondary-Dark-Button-Primary-On-Fill-Hover: var(--Scandic-Green-80);--Secondary-Dark-Button-Primary-On-Fill-Normal: var(--Scandic-Green-90);--Secondary-Dark-Button-Secondary-Border-Disabled: var(--UI-Opacity-White-20);--Secondary-Dark-Button-Secondary-Border-Hover: var(--Scandic-Green-30);--Secondary-Dark-Button-Secondary-Border-Normal: var(--Scandic-Green-20);--Secondary-Dark-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Secondary-Dark-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Secondary-Dark-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Secondary-Dark-Button-Secondary-On-Fill-Disabled: var( --UI-Opacity-White-20 );--Secondary-Dark-Button-Secondary-On-Fill-Hover: var(--Scandic-Green-30);--Secondary-Dark-Button-Secondary-On-Fill-Normal: var(--Scandic-Green-20);--Secondary-Dark-On-Surface-Accent: var(--Scandic-Green-40);--Secondary-Dark-On-Surface-Divider: var(--Scandic-Green-80);--Secondary-Dark-On-Surface-Text: var(--Scandic-Green-20);--Secondary-Dark-Surface-Hover: var(--Scandic-Green-80);--Secondary-Dark-Surface-Normal: var(--Scandic-Green-90);--Secondary-Light-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Secondary-Light-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Secondary-Light-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Secondary-Light-Button-Primary-Fill-Disabled: var( --UI-Opacity-Almost-Black-10 );--Secondary-Light-Button-Primary-Fill-Hover: var(--Scandic-Green-80);--Secondary-Light-Button-Primary-Fill-Normal: var(--Scandic-Green-90);--Secondary-Light-Button-Primary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Secondary-Light-Button-Primary-On-Fill-Hover: var(--Scandic-Green-30);--Secondary-Light-Button-Primary-On-Fill-Normal: var(--Scandic-Green-20);--Secondary-Light-Button-Secondary-Border-Disabled: var( --UI-Opacity-Almost-Black-20 );--Secondary-Light-Button-Secondary-Border-Hover: var(--Scandic-Green-80);--Secondary-Light-Button-Secondary-Border-Normal: var(--Scandic-Green-90);--Secondary-Light-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Secondary-Light-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Secondary-Light-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Secondary-Light-Button-Secondary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Secondary-Light-Button-Secondary-On-Fill-Hover: var(--Scandic-Green-80);--Secondary-Light-Button-Secondary-On-Fill-Normal: var(--Scandic-Green-90);--Secondary-Light-On-Surface-Accent: var(--Scandic-Green-50);--Secondary-Light-On-Surface-Divider: var(--Scandic-Green-30);--Secondary-Light-On-Surface-Text: var(--Scandic-Green-90);--Secondary-Light-Surface-Hover: var(--Scandic-Green-20);--Secondary-Light-Surface-Normal: var(--Scandic-Green-20);--Tertiary-Dark-Button-Primary-Border-Disabled: var(--UI-Opacity-White-0);--Tertiary-Dark-Button-Primary-Border-Hover: var(--UI-Opacity-White-0);--Tertiary-Dark-Button-Primary-Border-Normal: var(--UI-Opacity-White-0);--Tertiary-Dark-Button-Primary-Fill-Disabled: var(--UI-Opacity-White-10);--Tertiary-Dark-Button-Primary-Fill-Hover: var(--Scandic-Yellow-20);--Tertiary-Dark-Button-Primary-Fill-Normal: var(--Scandic-Yellow-10);--Tertiary-Dark-Button-Primary-On-Fill-Disabled: var(--UI-Opacity-White-20);--Tertiary-Dark-Button-Primary-On-Fill-Hover: var(--Scandic-Blue-80);--Tertiary-Dark-Button-Primary-On-Fill-Normal: var(--Scandic-Blue-100);--Tertiary-Dark-Button-Secondary-Border-Disabled: var(--UI-Opacity-White-20);--Tertiary-Dark-Button-Secondary-Border-Hover: var(--Scandic-Yellow-20);--Tertiary-Dark-Button-Secondary-Border-Normal: var(--Scandic-Yellow-10);--Tertiary-Dark-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Tertiary-Dark-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Tertiary-Dark-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Tertiary-Dark-Button-Secondary-On-Fill-Disabled: var(--UI-Opacity-White-20);--Tertiary-Dark-Button-Secondary-On-Fill-Hover: var(--Scandic-Yellow-20);--Tertiary-Dark-Button-Secondary-On-Fill-Normal: var(--Scandic-Yellow-10);--Tertiary-Dark-On-Surface-Accent: var(--Scandic-Blue-40);--Tertiary-Dark-On-Surface-Divider: var(--Scandic-Blue-80);--Tertiary-Dark-On-Surface-Text: var(--Scandic-Yellow-10);--Tertiary-Dark-Surface-Hover: var(--Scandic-Blue-90);--Tertiary-Dark-Surface-Normal: var(--Scandic-Blue-100);--Tertiary-Light-Button-Primary-Border-Disabled: var( --UI-Opacity-Almost-Black-20 );--Tertiary-Light-Button-Primary-Border-Hover: var(--Scandic-Yellow-00);--Tertiary-Light-Button-Primary-Border-Normal: var(--Scandic-Yellow-10);--Tertiary-Light-Button-Primary-Fill-Disabled: var( --UI-Opacity-Almost-Black-10 );--Tertiary-Light-Button-Primary-Fill-Hover: var(--Scandic-Blue-90);--Tertiary-Light-Button-Primary-Fill-Normal: var(--Scandic-Blue-100);--Tertiary-Light-Button-Primary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Tertiary-Light-Button-Primary-On-Fill-Hover: var(--Scandic-Yellow-00);--Tertiary-Light-Button-Primary-On-Fill-Normal: var(--Scandic-Yellow-10);--Tertiary-Light-Button-Secondary-Border-Disabled: var( --UI-Opacity-Almost-Black-20 );--Tertiary-Light-Button-Secondary-Border-Hover: var(--Scandic-Blue-90);--Tertiary-Light-Button-Secondary-Border-Normal: var(--Scandic-Blue-100);--Tertiary-Light-Button-Secondary-Fill-Disabled: var(--UI-Opacity-White-0);--Tertiary-Light-Button-Secondary-Fill-Hover: var(--UI-Opacity-White-0);--Tertiary-Light-Button-Secondary-Fill-Normal: var(--UI-Opacity-White-0);--Tertiary-Light-Button-Secondary-On-Fill-Disabled: var( --UI-Opacity-Almost-Black-20 );--Tertiary-Light-Button-Secondary-On-Fill-Hover: var(--Scandic-Blue-90);--Tertiary-Light-Button-Secondary-On-Fill-Normal: var(--Scandic-Blue-100);--Tertiary-Light-On-Surface-Accent: var(--Scandic-Yellow-50);--Tertiary-Light-On-Surface-Divider: var(--Scandic-Yellow-20);--Tertiary-Light-On-Surface-Text: var(--Scandic-Blue-100);--Tertiary-Light-Surface-Hover: var(--Scandic-Yellow-00);--Tertiary-Light-Surface-Normal: var(--Scandic-Yellow-10);--UI-Input-Controls-Border-Disabled: var(--UI-Grey-40);--UI-Input-Controls-Border-Error: var(--Scandic-Red-70);--UI-Input-Controls-Border-Focus: var(--Scandic-Blue-80);--UI-Input-Controls-Border-Hover: var(--Scandic-Beige-70);--UI-Input-Controls-Border-KeyboardFocus: var(--Scandic-Blue-50);--UI-Input-Controls-Border-Normal: var(--Scandic-Beige-50);--UI-Input-Controls-Fill-Disabled: var(--UI-Grey-60);--UI-Input-Controls-Fill-Normal: var(--UI-Opacity-White-100);--UI-Input-Controls-Fill-Selected: var(--Scandic-Blue-80);--UI-Input-Controls-Fill-Selected-hover: var(--Scandic-Blue-70);--UI-Input-Controls-On-Fill-Normal: var(--UI-Opacity-White-100);--UI-Input-Controls-Surface-Disabled: var(--UI-Grey-10);--UI-Input-Controls-Surface-Hover: var(--Scandic-Beige-10);--UI-Input-Controls-Surface-Normal: var(--UI-Opacity-White-100);--UI-Semantic-Error: var(--Scandic-Red-70);--UI-Semantic-Information: var(--Scandic-Blue-70);--UI-Semantic-Success: var(--Scandic-Green-60);--UI-Semantic-Warning: var(--Scandic-Yellow-60);--UI-Text-Active: var(--Scandic-Blue-90);--UI-Text-Error: var(--Scandic-Red-70);--UI-Text-High-contrast: var(--UI-Grey-100);--UI-Text-Medium-contrast: var(--UI-Grey-80);--UI-Text-Placeholder: var(--UI-Grey-60)}:root{--Corner-radius-Large: 12px;--Corner-radius-Medium: 8px;--Corner-radius-Rounded: 250px;--Corner-radius-Small: 4px;--Corner-radius-xLarge: 16px;--Layout-Desktop-Breakpoints-max-width: 1920px;--Layout-Desktop-Breakpoints-min-width: 1367px;--Layout-Desktop-Columns-Column: 12px;--Layout-Desktop-Gutter-max-width: 24px;--Layout-Desktop-Gutter-min-width: 16px;--Layout-Desktop-Margin-Margin-max: 72px;--Layout-Desktop-Margin-Margin-min: 40px;--Layout-Mobile-Breakpoints-max-width: 767px;--Layout-Mobile-Breakpoints-min-width: 320px;--Layout-Mobile-Columns-Column: 4px;--Layout-Mobile-Gutter-max-width: 16px;--Layout-Mobile-Gutter-min-width: 16px;--Layout-Mobile-Margin-Margin-max: 16px;--Layout-Mobile-Margin-Margin-min: 16px;--Layout-Tablet-Breakpoints-max-width: 1366px;--Layout-Tablet-Breakpoints-min-width: 768px;--Layout-Tablet-Columns-Column: 8px;--Layout-Tablet-Gutter-max-width: 16px;--Layout-Tablet-Gutter-min-width: 16px;--Layout-Tablet-Margin-Margin-max: 32px;--Layout-Tablet-Margin-Margin-min: 24px;--Spacing-x0: 0px;--Spacing-x1: 8px;--Spacing-x2: 16px;--Spacing-x3: 24px;--Spacing-x4: 32px;--Spacing-x5: 40px;--Spacing-x6: 48px;--Spacing-x7: 56px;--Spacing-x9: 72px;--Spacing-x-half: 4px;--Spacing-x-one-and-half: 12px;--Spacing-x-quarter: 2px}:root{--Go-Beige-00: #faf8f2;--Go-Beige-10: #f0ede4;--Go-Beige-20: #e0dcce;--Go-Beige-30: #c8c4b6;--Go-Beige-40: #b0aca0;--Go-Beige-50: #918f83;--Go-Beige-60: #78766d;--Go-Beige-70: #63615a;--Go-Beige-80: #4f4d49;--Go-Beige-90: #373633;--Go-Beige-100: #1f1e1d;--Go-Brand-Aqua: #73fcee;--Go-Brand-Chartreuse: #85ff52;--Go-Brand-Coral: #fa3737;--Go-Brand-Lavender: #dcd7ff;--Go-Brand-Lemon: #f5ff73;--Go-Brand-Linen: #e0dcce;--Go-Brand-Obsidian: #2d163a;--Go-Brand-Pine: #21331f;--Go-Brand-Powder-rose: #ecc8c9;--Go-Green-00: #edffe5;--Go-Green-10: #cdffb8;--Go-Green-20: #a7ff82;--Go-Green-30: #85ff52;--Go-Green-40: #66e03a;--Go-Green-50: #45b222;--Go-Green-60: #2e7f18;--Go-Green-70: #2a601e;--Go-Green-80: #26461f;--Go-Green-90: #21331f;--Go-Green-100: #162115;--Go-Purple-00: #f4f2ff;--Go-Purple-10: #dcd7ff;--Go-Purple-20: #cabffc;--Go-Purple-30: #baa7f7;--Go-Purple-40: #ab8ef0;--Go-Purple-50: #9c75e6;--Go-Purple-60: #8c5bd5;--Go-Purple-70: #733cb2;--Go-Purple-80: #5e2a8c;--Go-Purple-90: #451f61;--Go-Purple-100: #2d163a;--Go-Yellow-00: #fdffe8;--Go-Yellow-10: #faffc4;--Go-Yellow-20: #f8ff9c;--Go-Yellow-30: #f5ff73;--Go-Yellow-40: #edea39;--Go-Yellow-50: #dec614;--Go-Yellow-60: #ba8d07;--Go-Yellow-70: #966400;--Go-Yellow-80: #754403;--Go-Yellow-90: #572701;--Go-Yellow-100: #3b1300;--Scandic-Beige-00: #faf6f2;--Scandic-Beige-10: #f2ece6;--Scandic-Beige-20: #e3d9d1;--Scandic-Beige-30: #d1c4ba;--Scandic-Beige-40: #b8a79a;--Scandic-Beige-50: #9c8a7e;--Scandic-Beige-60: #806e63;--Scandic-Beige-70: #6b584d;--Scandic-Beige-80: #533f35;--Scandic-Beige-90: #3e2b23;--Scandic-Beige-100: #291710;--Scandic-Blue-00: #e8f6ff;--Scandic-Blue-10: #cfebff;--Scandic-Blue-20: #b5e0ff;--Scandic-Blue-30: #93c9f5;--Scandic-Blue-40: #79aee7;--Scandic-Blue-50: #5b8fd4;--Scandic-Blue-60: #3f6dbd;--Scandic-Blue-70: #284ea0;--Scandic-Blue-80: #18347f;--Scandic-Blue-90: #0d1f5f;--Scandic-Blue-100: #0d1440;--Scandic-Brand-Burgundy: #4d001b;--Scandic-Brand-Dark-Blue: #0d1440;--Scandic-Brand-Dark-Green: #093021;--Scandic-Brand-Dark-Grey: #291710;--Scandic-Brand-Light-Blue: #b5e0ff;--Scandic-Brand-Light-Green: #d2edaf;--Scandic-Brand-Pale-Peach: #f7e1d5;--Scandic-Brand-Pale-Yellow: #fff0c2;--Scandic-Brand-Scandic-Red: #cd0921;--Scandic-Brand-Warm-White: #faf6f2;--Scandic-Green-00: #f3fce8;--Scandic-Green-10: #e1f3ca;--Scandic-Green-20: #d2edaf;--Scandic-Green-30: #acdb8a;--Scandic-Green-40: #7cb865;--Scandic-Green-50: #539e49;--Scandic-Green-60: #348337;--Scandic-Green-70: #256931;--Scandic-Green-80: #164e29;--Scandic-Green-90: #093021;--Scandic-Green-100: #091f16;--Scandic-Peach-00: #fff3ed;--Scandic-Peach-10: #f7e1d5;--Scandic-Peach-20: #f4d5c8;--Scandic-Peach-30: #f0c1b6;--Scandic-Peach-40: #e9aba3;--Scandic-Peach-50: #de9490;--Scandic-Peach-60: #cd797c;--Scandic-Peach-70: #b05b65;--Scandic-Peach-80: #8f4350;--Scandic-Peach-90: #642636;--Scandic-Peach-100: #4d0f25;--Scandic-Red-00: #ffebeb;--Scandic-Red-10: #f7c1c2;--Scandic-Red-20: #f79499;--Scandic-Red-30: #f26b74;--Scandic-Red-40: #ed4251;--Scandic-Red-50: #e32034;--Scandic-Red-60: #cd0921;--Scandic-Red-70: #ad0015;--Scandic-Red-80: #8d0011;--Scandic-Red-90: #6d000d;--Scandic-Red-100: #4d001b;--Scandic-Yellow-00: #fff8e3;--Scandic-Yellow-10: #fff0c2;--Scandic-Yellow-20: #fade89;--Scandic-Yellow-30: #f7ce52;--Scandic-Yellow-40: #edb532;--Scandic-Yellow-50: #e59515;--Scandic-Yellow-60: #d17308;--Scandic-Yellow-70: #a85211;--Scandic-Yellow-80: #7d370f;--Scandic-Yellow-90: #4f2313;--Scandic-Yellow-100: #301508;--UI-Grey-00: #f9f6f4;--UI-Grey-10: #ebe8e6;--UI-Grey-20: #d6d2d0;--UI-Grey-30: #c2bdba;--UI-Grey-40: #a8a4a2;--UI-Grey-50: #8c8987;--UI-Grey-60: #787472;--UI-Grey-70: #635f5d;--UI-Grey-80: #57514e;--UI-Grey-90: #403937;--UI-Grey-100: #26201e;--UI-Opacity-Almost-Black-0: #1f1c1b00;--UI-Opacity-Almost-Black-10: #1f1c1b1a;--UI-Opacity-Almost-Black-20: #1f1c1b33;--UI-Opacity-Almost-Black-30: #1f1c1b4d;--UI-Opacity-Almost-Black-40: #1f1c1b66;--UI-Opacity-Almost-Black-50: #1f1c1b80;--UI-Opacity-Almost-Black-60: #1f1c1b99;--UI-Opacity-Almost-Black-70: #1f1c1bb3;--UI-Opacity-Almost-Black-80: #1f1c1bcc;--UI-Opacity-Almost-Black-90: #1f1c1be6;--UI-Opacity-Almost-Black-100: #1f1c1b;--UI-Opacity-White-0: #ffffff00;--UI-Opacity-White-10: #ffffff1a;--UI-Opacity-White-20: #ffffff33;--UI-Opacity-White-30: #ffffff4d;--UI-Opacity-White-40: #ffffff66;--UI-Opacity-White-50: #ffffff80;--UI-Opacity-White-60: #ffffff99;--UI-Opacity-White-70: #ffffffb3;--UI-Opacity-White-80: #ffffffcc;--UI-Opacity-White-90: #ffffffe6;--UI-Opacity-White-100: #ffffff}:root{--Go-Beige-00: #faf8f2;--Go-Beige-10: #f0ede4;--Go-Beige-20: #e0dcce;--Go-Beige-30: #c8c4b6;--Go-Beige-40: #b0aca0;--Go-Beige-50: #918f83;--Go-Beige-60: #78766d;--Go-Beige-70: #63615a;--Go-Beige-80: #4f4d49;--Go-Beige-90: #373633;--Go-Beige-100: #1f1e1d;--Go-Brand-Aqua: #73fcee;--Go-Brand-Chartreuse: #85ff52;--Go-Brand-Coral: #fa3737;--Go-Brand-Lavender: #dcd7ff;--Go-Brand-Lemon: #f5ff73;--Go-Brand-Linen: #e0dcce;--Go-Brand-Obsidian: #2d163a;--Go-Brand-Pine: #21331f;--Go-Brand-Powderrose: #ecc8c9;--Go-Green-00: #edffe5;--Go-Green-10: #cdffb8;--Go-Green-20: #a7ff82;--Go-Green-30: #85ff52;--Go-Green-40: #66e03a;--Go-Green-50: #45b222;--Go-Green-60: #2e7f18;--Go-Green-70: #2a601e;--Go-Green-80: #26461f;--Go-Green-90: #21331f;--Go-Green-100: #162115;--Go-Purple-00: #f4f2ff;--Go-Purple-10: #dcd7ff;--Go-Purple-20: #cabffc;--Go-Purple-30: #baa7f7;--Go-Purple-40: #ab8ef0;--Go-Purple-50: #9c75e6;--Go-Purple-60: #8c5bd5;--Go-Purple-70: #733cb2;--Go-Purple-80: #5e2a8c;--Go-Purple-90: #451f61;--Go-Purple-100: #2d163a;--Go-Yellow-00: #fdffe8;--Go-Yellow-10: #faffc4;--Go-Yellow-20: #f8ff9c;--Go-Yellow-30: #f5ff73;--Go-Yellow-40: #edea39;--Go-Yellow-50: #dec614;--Go-Yellow-60: #ba8d07;--Go-Yellow-70: #966400;--Go-Yellow-80: #754403;--Go-Yellow-90: #572701;--Go-Yellow-100: #3b1300;--Main-Blue-00: #eaf2fc;--Main-Blue-10: #c7d9f5;--Main-Blue-20: #a5c2ee;--Main-Blue-30: #84ace7;--Main-Blue-40: #6697df;--Main-Blue-50: #4983d8;--Main-Blue-60: #2e70d1;--Main-Blue-70: #1555b4;--Main-Blue-80: #023d96;--Main-Blue-90: #002a69;--Main-Blue-100: #001b42;--Main-Brand-Burgundy: #4d001b;--Main-Brand-DarkBlue: #0d1440;--Main-Brand-DarkGreen: #093021;--Main-Brand-DarkGrey: #291710;--Main-Brand-LightBlue: #b5e0ff;--Main-Brand-LightGreen: #d2edaf;--Main-Brand-PalePeach: #f7e1d5;--Main-Brand-PaleYellow: #fff0c2;--Main-Brand-ScandicRed: #cd0921;--Main-Brand-WarmWhite: #faf6f2;--Main-Green-00: #e7f5e1;--Main-Green-10: #badda8;--Main-Green-20: #99ca7e;--Main-Green-30: #7ab859;--Main-Green-40: #5fa53a;--Main-Green-50: #47931f;--Main-Green-60: #33800a;--Main-Green-70: #286806;--Main-Green-80: #1e4f03;--Main-Green-90: #143701;--Main-Green-100: #0e2600;--Main-Grey-00: #f9f6f4;--Main-Grey-10: #ebe8e6;--Main-Grey-20: #d6d2d0;--Main-Grey-30: #c2bdba;--Main-Grey-40: #a8a4a2;--Main-Grey-50: #8c8987;--Main-Grey-60: #787472;--Main-Grey-70: #635f5d;--Main-Grey-80: #57514e;--Main-Grey-90: #403937;--Main-Grey-100: #26201e;--Main-Grey-Almostblack: #1f1c1b;--Main-Grey-White: #ffffff;--Main-Red-00: #ffebeb;--Main-Red-10: #f7c1c2;--Main-Red-20: #f79499;--Main-Red-30: #f26b74;--Main-Red-40: #ed4251;--Main-Red-50: #e32034;--Main-Red-60: #cd0921;--Main-Red-70: #ad0015;--Main-Red-80: #8d0011;--Main-Red-90: #6d000d;--Main-Red-100: #4d001b;--Main-Scandic-00: #ffebeb;--Main-Scandic-10: #f7c1c2;--Main-Scandic-20: #f79499;--Main-Scandic-30: #f26b74;--Main-Scandic-40: #ed4251;--Main-Scandic-50: #e32034;--Main-Scandic-60: #cd0921;--Main-Scandic-70: #ad0015;--Main-Scandic-80: #8d0011;--Main-Scandic-90: #6d000d;--Main-Scandic-100: #4d001b;--Main-Yellow-00: #fff8e3;--Main-Yellow-10: #fff0c2;--Main-Yellow-20: #fade89;--Main-Yellow-30: #f7ce52;--Main-Yellow-40: #edb532;--Main-Yellow-50: #e59515;--Main-Yellow-60: #d17308;--Main-Yellow-70: #a85211;--Main-Yellow-80: #7d370f;--Main-Yellow-90: #4f2313;--Main-Yellow-100: #301508} diff --git a/apps/scandic-web/stores/enter-details/helpers.ts b/apps/scandic-web/stores/enter-details/helpers.ts index 0ee20b735..835fb82f6 100644 --- a/apps/scandic-web/stores/enter-details/helpers.ts +++ b/apps/scandic-web/stores/enter-details/helpers.ts @@ -3,7 +3,7 @@ import { parsePhoneNumberFromString } from "libphonenumber-js" import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" import { logger } from "@scandic-hotels/common/logger" -import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType" +import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType" import { sumPackages, diff --git a/apps/scandic-web/types/components/hotelPage/map/interactiveMap.ts b/apps/scandic-web/types/components/hotelPage/map/interactiveMap.ts deleted file mode 100644 index 1190ce255..000000000 --- a/apps/scandic-web/types/components/hotelPage/map/interactiveMap.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { PointOfInterest } from "@scandic-hotels/trpc/types/hotel" -import type { MarkerInfo } from "@scandic-hotels/trpc/types/marker" -import type { ReactElement } from "react" - -import type { HotelPin } from "@/types/components/hotelReservation/selectHotel/map" -import type { Coordinates } from "@/types/components/maps/coordinates" - -export interface InteractiveMapProps { - coordinates: Coordinates - activePoi?: PointOfInterest["name"] | null - hotelPins?: HotelPin[] - pointsOfInterest?: PointOfInterest[] - markerInfo?: MarkerInfo - mapId: string - closeButton: ReactElement - fitBounds?: boolean - onTilesLoaded?: () => void - onActivePoiChange?: (poi: PointOfInterest["name"] | null) => void -} diff --git a/apps/scandic-web/types/components/hotelReservation/selectHotel/map.ts b/apps/scandic-web/types/components/hotelReservation/selectHotel/map.ts index 0918f6c5e..f3636e518 100644 --- a/apps/scandic-web/types/components/hotelReservation/selectHotel/map.ts +++ b/apps/scandic-web/types/components/hotelReservation/selectHotel/map.ts @@ -50,10 +50,6 @@ export type HotelPin = { hasEnoughPoints: boolean } -export interface HotelListingMapContentProps { - hotelPins: HotelPin[] -} - export interface HotelCardDialogProps { type?: "listing" | "standalone" isOpen: boolean @@ -61,15 +57,6 @@ export interface HotelCardDialogProps { handleClose: (event: { stopPropagation: () => void }) => void } -export interface HotelCardDialogImageProps { - firstImage?: string - altText?: string - rating?: number | null - imageError: boolean - setImageError: (error: boolean) => void - position: "top" | "left" -} - export interface HotelCardDialogListingProps { hotels: HotelResponse[] unfilteredHotelCount: number diff --git a/apps/scandic-web/types/components/hotelReservation/selectHotel/priceCardProps.ts b/apps/scandic-web/types/components/hotelReservation/selectHotel/priceCardProps.ts index 5e7cbeeca..41e4c5ee8 100644 --- a/apps/scandic-web/types/components/hotelReservation/selectHotel/priceCardProps.ts +++ b/apps/scandic-web/types/components/hotelReservation/selectHotel/priceCardProps.ts @@ -10,12 +10,6 @@ export type PriceCardProps = { className?: string } -export type PointsRowProps = { - pointsPerStay: number - additionalPricePerStay?: number - additionalPriceCurrency?: string -} - export type VoucherCardProps = { productTypeVoucher: ProductTypeVoucher } diff --git a/apps/scandic-web/types/components/maps/poiMarker.ts b/apps/scandic-web/types/components/maps/poiMarker.ts deleted file mode 100644 index 8e7abc677..000000000 --- a/apps/scandic-web/types/components/maps/poiMarker.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { PointOfInterestGroupEnum } from "@scandic-hotels/trpc/enums/pointOfInterest" -import type { VariantProps } from "class-variance-authority" - -import type { poiVariants } from "@/components/Maps/Markers/Poi/variants" - -export interface PoiMarkerProps extends VariantProps { - group: PointOfInterestGroupEnum - categoryName?: string - className?: string -} diff --git a/apps/scandic-web/utils/facilityCards.ts b/apps/scandic-web/utils/facilityCards.ts index 9ecb23f89..8a652c26d 100644 --- a/apps/scandic-web/utils/facilityCards.ts +++ b/apps/scandic-web/utils/facilityCards.ts @@ -1,4 +1,4 @@ -import { FacilityEnum } from "@scandic-hotels/trpc/enums/facilities" +import { FacilityEnum } from "@scandic-hotels/common/constants/facilities" import type { Amenities, diff --git a/packages/booking-flow/lib/components/AdditionalAmenities/index.tsx b/packages/booking-flow/lib/components/AdditionalAmenities/index.tsx index c4c7e7669..3780248e6 100644 --- a/packages/booking-flow/lib/components/AdditionalAmenities/index.tsx +++ b/packages/booking-flow/lib/components/AdditionalAmenities/index.tsx @@ -1,7 +1,6 @@ +import { FacilityEnum } from "@scandic-hotels/common/constants/facilities" +import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon" import { Typography } from "@scandic-hotels/design-system/Typography" -import { FacilityEnum } from "@scandic-hotels/trpc/enums/facilities" - -import { FacilityToIcon } from "../TEMP/FacilityToIcon" import styles from "./additionalAmenities.module.css" diff --git a/packages/booking-flow/lib/components/TEMP/FacilityToIcon.tsx b/packages/booking-flow/lib/components/TEMP/FacilityToIcon.tsx deleted file mode 100644 index 6d1a622d6..000000000 --- a/packages/booking-flow/lib/components/TEMP/FacilityToIcon.tsx +++ /dev/null @@ -1,305 +0,0 @@ -import { IconByIconName } from "@scandic-hotels/design-system/Icons/IconByIconName" -import { IconName } from "@scandic-hotels/design-system/Icons/iconName" -import { FacilityEnum } from "@scandic-hotels/trpc/enums/facilities" - -import type { - IconProps, - NucleoIconProps, -} from "@scandic-hotels/design-system/Icons" -import type { MaterialIconSetIconProps } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import type { JSX } from "react" - -const facilityToIconMap: Record = { - [FacilityEnum.AccessibleBathingControls]: IconName.StarFilled, - [FacilityEnum.AccessibleBathtubs]: IconName.StarFilled, - [FacilityEnum.AccessibleElevators]: IconName.StarFilled, - [FacilityEnum.AccessibleLightSwitch]: IconName.StarFilled, - [FacilityEnum.AccessibleRoomsAtHotel1]: IconName.StarFilled, - [FacilityEnum.AccessibleRoomsAtHotel2]: IconName.StarFilled, - [FacilityEnum.AccessibleToilets]: IconName.StarFilled, - [FacilityEnum.AccessibleWashBasins]: IconName.StarFilled, - [FacilityEnum.AdaptedRoomDoors]: IconName.StarFilled, - [FacilityEnum.AdjoiningConventionCentre]: IconName.ConventionCentre, - [FacilityEnum.AirConAirCooling]: IconName.AirConAirCooling, - [FacilityEnum.AirConditioningInRoom]: IconName.AirConditioningInRoom, - [FacilityEnum.AirportMaxDistance8Km]: IconName.Airplane, - [FacilityEnum.AlarmsContinuouslyMonitored]: IconName.StarFilled, - [FacilityEnum.AlarmsHaveStrobeLightsForDeafHardHearingInAllGuestRooms]: - IconName.StarFilled, - [FacilityEnum.AlarmsHaveStrobeLightsForDeafHardHearingInAllHallways]: - IconName.StarFilled, - [FacilityEnum.AlarmsHaveStrobeLightsForDeafHardHearingInAllPublicAreas]: - IconName.StarFilled, - [FacilityEnum.AllAudibleSmokeAlarmsHardwired]: IconName.StarFilled, - [FacilityEnum.AllExteriorDoorsRequireKeyAccessAtNightOrAutomaticallyLock]: - IconName.StarFilled, - [FacilityEnum.AllGuestRoomDoorsHaveViewports]: IconName.StarFilled, - [FacilityEnum.AllGuestRoomDoorsSelfClosing]: IconName.StarFilled, - [FacilityEnum.AllParkingAreasPatrolled]: IconName.StarFilled, - [FacilityEnum.AllParkingAreasWellLit]: IconName.StarFilled, - [FacilityEnum.AllStairsWellsVentilated]: IconName.StarFilled, - [FacilityEnum.ArmchairBed]: IconName.ArmChair, - [FacilityEnum.AudibleAlarms]: IconName.StarFilled, - [FacilityEnum.AudibleSmokeAlarmsInAllHalls]: IconName.StarFilled, - [FacilityEnum.AudibleSmokeAlarmsInAllPublicAreas]: IconName.StarFilled, - [FacilityEnum.AudibleSmokeAlarmsInAllRooms]: IconName.StarFilled, - [FacilityEnum.AudioVisualEquipmentAvailable]: IconName.StarFilled, - [FacilityEnum.AutolinkFireDepartment]: IconName.StarFilled, - [FacilityEnum.AutomatedExternalDefibrillatorOnSiteAED]: IconName.StarFilled, - [FacilityEnum.AutomaticFireDoors]: IconName.StarFilled, - [FacilityEnum.AutoRecallElevators]: IconName.StarFilled, - [FacilityEnum.BalconiesAccessibleToAdjoiningRooms]: IconName.StarFilled, - [FacilityEnum.Ballroom]: IconName.StarFilled, - [FacilityEnum.Banquet]: IconName.StarFilled, - [FacilityEnum.Bar]: IconName.LocalBar, - [FacilityEnum.BasicMedicalEquipmentOnSite]: IconName.StarFilled, - [FacilityEnum.BathroomsAdaptedForDisabledGuests]: IconName.StarFilled, - [FacilityEnum.Beach]: IconName.Beach, - [FacilityEnum.Beach0To1Km]: IconName.Beach, - [FacilityEnum.BeautySalon]: IconName.BeautySalon, - [FacilityEnum.BedroomsWithWheelchairAccess]: IconName.StarFilled, - [FacilityEnum.BikesForLoan]: IconName.Bike, - [FacilityEnum.Bowling]: IconName.Bowling, - [FacilityEnum.BrailleLargePrintHotelLiterature]: IconName.StarFilled, - [FacilityEnum.BrailleLargePrintMenus]: IconName.StarFilled, - [FacilityEnum.Breakfast]: IconName.Breakfast, - [FacilityEnum.Business1]: IconName.BusinessCentre, - [FacilityEnum.Business2]: IconName.BusinessCentre, - [FacilityEnum.BusinessCentre]: IconName.BusinessCentre, - [FacilityEnum.Cafe]: IconName.Restaurant, - [FacilityEnum.CashFree8pmTill6am]: IconName.CashFree, - [FacilityEnum.CashFreeHotel]: IconName.CashFree, - [FacilityEnum.ChildrenWelcome]: IconName.StarFilled, - [FacilityEnum.City]: IconName.City, - [FacilityEnum.CoffeeInReceptionAtCharge]: IconName.CoffeeInReceptionAtCharge, - [FacilityEnum.CoffeeShop]: IconName.CoffeeShop, - [FacilityEnum.CoffeeTeaFacilities]: IconName.CoffeeAlt, - [FacilityEnum.ColourTVInRoomsAllScandicHotels]: IconName.StarFilled, - [FacilityEnum.ComplimentaryColdRefreshments]: - IconName.ComplimentaryColdRefreshments, - [FacilityEnum.CongressHall]: IconName.StarFilled, - [FacilityEnum.ConventionCentre]: IconName.ConventionCentre, - [FacilityEnum.Couples]: IconName.StarFilled, - [FacilityEnum.DeadboltsOnConnectingDoors]: IconName.StarFilled, - [FacilityEnum.DeadboltsSecondaryLocksOnAllGuestRoomDoors]: - IconName.StarFilled, - [FacilityEnum.Defibrillator]: IconName.StarFilled, - [FacilityEnum.Desk]: IconName.Desk, - [FacilityEnum.DirectDialPhoneInRoomsAllScandic]: IconName.DirectDial, - [FacilityEnum.DisabledEmergencyPlan1]: IconName.StarFilled, - [FacilityEnum.DisabledEmergencyPlan2]: IconName.StarFilled, - [FacilityEnum.DisabledParking]: IconName.Wheelchair, - [FacilityEnum.DiscoNightClub]: IconName.Nightlife, - [FacilityEnum.DJLiveMusic]: IconName.Nightlife, - [FacilityEnum.DO_NOT_USE_Restaurant]: IconName.StarFilled, - [FacilityEnum.Downtown]: IconName.StarFilled, - [FacilityEnum.DrinkableTapWater]: IconName.StarFilled, - [FacilityEnum.DVDPlayer]: IconName.StarFilled, - [FacilityEnum.EBikesChargingStation]: IconName.ElectricBike, - [FacilityEnum.ElectronicKeyCards]: IconName.StarFilled, - [FacilityEnum.Elevator]: IconName.Elevator, - [FacilityEnum.EmergencyBackUpGenerators]: IconName.StarFilled, - [FacilityEnum.EmergencyCallButtonOnPhone]: IconName.StarFilled, - [FacilityEnum.EmergencyCodesOrButtonsInRooms]: IconName.StarFilled, - [FacilityEnum.EmergencyEvacuationPlan1]: IconName.StarFilled, - [FacilityEnum.EmergencyEvacuationPlan2]: IconName.StarFilled, - [FacilityEnum.EmergencyEvaluationDrillFrequency]: IconName.StarFilled, - [FacilityEnum.EmergencyInfoInAllRooms]: IconName.StarFilled, - [FacilityEnum.EmergencyLightingAllScandic]: IconName.StarFilled, - [FacilityEnum.EmergencyLightningInAllPublicAreas]: IconName.StarFilled, - [FacilityEnum.EmergencyServiceResponseTimeInMinutes]: IconName.StarFilled, - [FacilityEnum.Entertainment]: IconName.Theatre, - [FacilityEnum.EventVenue]: IconName.StarFilled, - [FacilityEnum.ExchangeFacility]: IconName.StarFilled, - [FacilityEnum.ExitMapsInRooms]: IconName.StarFilled, - [FacilityEnum.ExitSignsLit]: IconName.StarFilled, - [FacilityEnum.ExtraFamilyFriendly]: IconName.ExtraFamilyFriendly, - [FacilityEnum.Families]: IconName.ExtraFamilyFriendly, - [FacilityEnum.FaxFacilityInRoom]: IconName.Fax, - [FacilityEnum.Financial]: IconName.StarFilled, - [FacilityEnum.FireDetectorsAllScandic]: IconName.StarFilled, - [FacilityEnum.FireDetectorsInAllHalls]: IconName.StarFilled, - [FacilityEnum.FireDetectorsInAllPublicAreas]: IconName.StarFilled, - [FacilityEnum.FireDetectorsInAllRooms]: IconName.StarFilled, - [FacilityEnum.FireExtinguishersInAllPublicAreas]: IconName.StarFilled, - [FacilityEnum.FireExtinguishersInPublicAreasAllScandic]: IconName.StarFilled, - [FacilityEnum.FireSafetyAllScandic]: IconName.StarFilled, - [FacilityEnum.FirstAidAvailable]: IconName.StarFilled, - [FacilityEnum.FoodDrinks247]: IconName.FoodDrinks247, - [FacilityEnum.FreeWiFi]: IconName.Wifi, - [FacilityEnum.GiftShop]: IconName.Gift, - [FacilityEnum.Golf]: IconName.Golf, - [FacilityEnum.GolfCourse0To30Km]: IconName.Golf, - [FacilityEnum.GuestRoomDoorsHaveASecondLock]: IconName.StarFilled, - [FacilityEnum.Gym]: IconName.Fitness, - [FacilityEnum.GymTrainingFacilities]: IconName.Fitness, - [FacilityEnum.Hairdresser]: IconName.Hairdresser, - [FacilityEnum.HairdryerInRoomAllScandic]: IconName.HairdryerInRoomAllScandic, - [FacilityEnum.HandicapFacilities]: IconName.StarFilled, - [FacilityEnum.HandrailsInBathrooms]: IconName.StarFilled, - [FacilityEnum.HearingInductionLoops]: IconName.StarFilled, - [FacilityEnum.Highway1]: IconName.StarFilled, - [FacilityEnum.Highway2]: IconName.StarFilled, - [FacilityEnum.Hiking0To3Km]: IconName.Hiking, - [FacilityEnum.HotelCompliesWithAAASecurityStandards]: IconName.StarFilled, - [FacilityEnum.HotelIsFollowingScandicsSafetySecurityPolicy]: - IconName.StarFilled, - [FacilityEnum.HotelWorksAccordingToScandicsAccessibilityConcepts]: - IconName.StarFilled, - [FacilityEnum.IceMachine]: IconName.IceMachine, - [FacilityEnum.IceMachineReception]: IconName.IceMachine, - [FacilityEnum.IDRequiredToReplaceAGuestRoomKey]: IconName.StarFilled, - [FacilityEnum.IfNoWhatAreTheHoursUse24ClockEx0000To0600]: IconName.StarFilled, - [FacilityEnum.InCountry]: IconName.StarFilled, - [FacilityEnum.IndustrialPark]: IconName.StarFilled, - [FacilityEnum.InternetHighSpeedInternetConnectionAllScandic]: - IconName.StarFilled, - [FacilityEnum.InternetHotSpotsAllScandic]: IconName.StarFilled, - [FacilityEnum.IroningRoom]: IconName.Ironing, - [FacilityEnum.IronIroningBoardAllScandic]: IconName.Ironing, - [FacilityEnum.Jacuzzi]: IconName.Jacuzzi, - [FacilityEnum.JacuzziInRoom]: IconName.Jacuzzi, - [FacilityEnum.KayaksForLoan]: IconName.Kayaking, - [FacilityEnum.KeyAccessOnlySecuredFloorsAvailable]: IconName.StarFilled, - [FacilityEnum.KeyAccessOnlyToHealthClubGym]: IconName.Fitness, - [FacilityEnum.KidsPlayRoom]: IconName.StarFilled, - [FacilityEnum.KidsUpToAndIncluding12YearsStayForFree]: IconName.StarFilled, - [FacilityEnum.KitchenInRoom]: IconName.Kitchen, - [FacilityEnum.Lake0To1Km]: IconName.Houseboat, - [FacilityEnum.LakeOrSea0To1Km]: IconName.Houseboat, - [FacilityEnum.LaptopSafe]: IconName.LaptopSafe, - [FacilityEnum.LateCheckOutUntil1400Guaranteed]: IconName.Business, - [FacilityEnum.LaundryRoom]: IconName.LaundryMachine, - [FacilityEnum.LaundryService]: IconName.LaundryMachine, - [FacilityEnum.LaundryServiceExpress]: IconName.TshirtWash, - [FacilityEnum.Leisure]: IconName.StarFilled, - [FacilityEnum.LifestyleConcierge]: IconName.Concierge, - [FacilityEnum.LuggageLockers]: IconName.LuggageLockers, - [FacilityEnum.LuggageStorageAdditionalCost]: IconName.Luggage, - [FacilityEnum.LuggageStorageNoCost]: IconName.Luggage, - [FacilityEnum.Massage]: IconName.Massage, - [FacilityEnum.MeetingArea]: IconName.Business, - [FacilityEnum.MeetingConferenceFacilities]: IconName.Business, - [FacilityEnum.MeetingRooms]: IconName.Business, - [FacilityEnum.MinibarInRoom]: IconName.Minibar, - [FacilityEnum.MobileLift]: IconName.StarFilled, - [FacilityEnum.Mountains0To1Km]: IconName.Landscape, - [FacilityEnum.MovieChannelsInRoomAllScandic]: IconName.TVRemote, - [FacilityEnum.MultipleExitsOnEachFloor]: IconName.StarFilled, - [FacilityEnum.NonSmokingRoomsAllScandic]: IconName.NonSmoking, - [FacilityEnum.OnSiteTrainingFacilities]: IconName.Fitness, - [FacilityEnum.OtherExplainInBriefDescription]: IconName.StarFilled, - [FacilityEnum.OutdoorTerrace]: IconName.Deck, - [FacilityEnum.OvernightSecurity]: IconName.Guard, - [FacilityEnum.ParkingAdditionalCost]: IconName.Parking, - [FacilityEnum.ParkingAttendant]: IconName.StarFilled, - [FacilityEnum.ParkingElectricCharging]: IconName.ElectricCar, - [FacilityEnum.ParkingFreeParking]: IconName.Parking, - [FacilityEnum.ParkingGarage]: IconName.Garage, - [FacilityEnum.ParkingOutdoor]: IconName.ParkingOutdoor, - [FacilityEnum.PCHookUpInRoom]: IconName.StarFilled, - [FacilityEnum.PetFriendlyRooms]: IconName.Pets, - [FacilityEnum.PillowAlarmsAvailable]: IconName.StarFilled, - [FacilityEnum.PlayStationInPlayArea]: IconName.Gaming, - [FacilityEnum.Pool]: IconName.Swim, - [FacilityEnum.PoolSwimmingPoolJacuzziAtHotel]: IconName.Swim, - [FacilityEnum.PrintingService]: IconName.StarFilled, - [FacilityEnum.PropertyMeetsRequirementsFireSafety]: IconName.StarFilled, - [FacilityEnum.PublicAddressSystem]: IconName.StarFilled, - [FacilityEnum.RelaxationSuite]: IconName.StarFilled, - [FacilityEnum.Restaurant]: IconName.Restaurant, - [FacilityEnum.RestrictedRoomAccessAllScandic]: IconName.StarFilled, - [FacilityEnum.RooftopBar]: IconName.Deck, - [FacilityEnum.RoomsAccessibleFromTheInterior]: IconName.StarFilled, - [FacilityEnum.RoomService]: IconName.RoomService, - [FacilityEnum.RoomWindowsOpen]: IconName.StarFilled, - [FacilityEnum.RoomWindowsThatOpenHaveLockingDevice]: IconName.StarFilled, - [FacilityEnum.Rural1]: IconName.StarFilled, - [FacilityEnum.Rural2]: IconName.StarFilled, - [FacilityEnum.SafeDepositBoxInRoomsAllScandic]: IconName.SafetyBox, - [FacilityEnum.SafeDepositBoxInRoomsCanHoldA17InchLaptop]: IconName.SafetyBox, - [FacilityEnum.SafeDepositBoxInRoomsCannotHoldALaptop]: IconName.SafetyBox, - [FacilityEnum.SafetyChainsOnGuestRoomDoor]: IconName.StarFilled, - [FacilityEnum.Sauna]: IconName.Sauna, - [FacilityEnum.ScandicShop24Hrs]: IconName.ConvenienceStore24h, - [FacilityEnum.SecondaryLocksOnSlidingGlassDoors]: IconName.StarFilled, - [FacilityEnum.SecondaryLocksOnWindows]: IconName.StarFilled, - [FacilityEnum.Security24Hours]: IconName.Guard, - [FacilityEnum.SecurityEscortsAvailableOnRequest]: IconName.Guard, - [FacilityEnum.SecurityPersonnelOnSite]: IconName.Guard, - [FacilityEnum.SeparateFloorsForWomen]: IconName.StarFilled, - [FacilityEnum.ServesBreakfastAlwaysIncluded]: IconName.Breakfast, - [FacilityEnum.ServesBreakfastNotAlwaysIncluded]: IconName.Breakfast, - [FacilityEnum.ServesOrganicBreakfastAlwaysIncluded]: IconName.Breakfast, - [FacilityEnum.ServesOrganicBreakfastNotAlwaysIncluded]: IconName.Breakfast, - [FacilityEnum.ServiceGuideDogsAllowed]: IconName.StarFilled, - [FacilityEnum.ServiceSecurity24Hrs]: IconName.Guard, - [FacilityEnum.Shopping]: IconName.Shopping, - [FacilityEnum.SkateboardsForLoan]: IconName.Skateboarding, - [FacilityEnum.Skiing0To1Km]: IconName.Skiing, - [FacilityEnum.Skybar]: IconName.LocalBar, - [FacilityEnum.SmokeDetectorsAllScandic]: IconName.StarFilled, - [FacilityEnum.Solarium]: IconName.StarFilled, - [FacilityEnum.SpecialNeedsMenus]: IconName.StarFilled, - [FacilityEnum.Sports]: IconName.Sports, - [FacilityEnum.SprinklersAllScandic]: IconName.StarFilled, - [FacilityEnum.SprinklersInAllHalls]: IconName.StarFilled, - [FacilityEnum.SprinklersInAllPublicAreas]: IconName.StarFilled, - [FacilityEnum.SprinklersInAllRooms]: IconName.StarFilled, - [FacilityEnum.StaffInDuplicateKeys]: IconName.StarFilled, - [FacilityEnum.StaffRedCrossCertifiedInCPR]: IconName.StarFilled, - [FacilityEnum.StaffTrainedForDisabledGuests]: IconName.StarFilled, - [FacilityEnum.StaffTrainedInAutomatedExternalDefibrillatorUsageAED]: - IconName.StarFilled, - [FacilityEnum.StaffTrainedInCPR]: IconName.StarFilled, - [FacilityEnum.StaffTrainedInFirstAid]: IconName.StarFilled, - [FacilityEnum.StaffTrainedInFirstAidTechniques]: IconName.StarFilled, - [FacilityEnum.StaffTrainedToCaterForDisabledGuestsAllScandic]: - IconName.StarFilled, - [FacilityEnum.Suburbs]: IconName.StarFilled, - [FacilityEnum.SwingboltLock]: IconName.StarFilled, - [FacilityEnum.TeleConferencingFacilitiesAvailable]: IconName.StarFilled, - [FacilityEnum.TelevisionsWithSubtitlesOrClosedCaptions]: IconName.StarFilled, - [FacilityEnum.Tennis1]: IconName.Sports, - [FacilityEnum.Tennis2]: IconName.Sports, - [FacilityEnum.TennisPadel]: IconName.Sports, - [FacilityEnum.Theatre]: IconName.Theatre, - [FacilityEnum.TrouserPress]: IconName.Ironing, - [FacilityEnum.TVWithChromecast1]: IconName.TvCasting, - [FacilityEnum.TVWithChromecast2]: IconName.TvCasting, - [FacilityEnum.UniformSecurityOnPremises]: IconName.StarFilled, - [FacilityEnum.UtilityRoomForIroning]: IconName.Ironing, - [FacilityEnum.VendingMachineWithNecessities]: IconName.Dining, - [FacilityEnum.VideoSurveillanceInHallways]: IconName.StarFilled, - [FacilityEnum.VideoSurveillanceInPublicAreas]: IconName.StarFilled, - [FacilityEnum.VideoSurveillanceMonitored24HrsADay]: IconName.StarFilled, - [FacilityEnum.VideoSurveillanceOfAllParkingAreas]: IconName.StarFilled, - [FacilityEnum.VideoSurveillanceOfExteriorFrontEntrance]: IconName.StarFilled, - [FacilityEnum.VideoSurveillanceRecorded24HrsADayParkingArea]: - IconName.StarFilled, - [FacilityEnum.WallMountedCycleRack]: IconName.Bike, - [FacilityEnum.WellLitWalkways]: IconName.StarFilled, - [FacilityEnum.WellnessAndSaunaEntranceFeeAdmission16PlusYears]: IconName.Spa, - [FacilityEnum.WellnessPoolSaunaEntranceFeeAdmission16PlusYears]: IconName.Spa, - [FacilityEnum.WheelchairAccess]: IconName.Wheelchair, - [FacilityEnum.WideCorridors]: IconName.StarFilled, - [FacilityEnum.WideEntrance]: IconName.StarFilled, - [FacilityEnum.WideRestaurantEntrance]: IconName.StarFilled, - [FacilityEnum.WiFiWirelessInternetAccessAllScandic]: IconName.StarFilled, -} - -interface mapFacilityToIconProps { - id: FacilityEnum -} -export function FacilityToIcon({ - id, - ...props -}: mapFacilityToIconProps & - ( - | MaterialIconSetIconProps - | NucleoIconProps - | IconProps - )): JSX.Element | null { - const iconName = facilityToIconMap[id] - return -} diff --git a/packages/trpc/lib/enums/facilities.ts b/packages/common/constants/facilities.ts similarity index 100% rename from packages/trpc/lib/enums/facilities.ts rename to packages/common/constants/facilities.ts diff --git a/packages/common/constants/hotelType.ts b/packages/common/constants/hotelType.ts new file mode 100644 index 000000000..e68aa08ad --- /dev/null +++ b/packages/common/constants/hotelType.ts @@ -0,0 +1,7 @@ +export const HotelTypes = { + Signature: "signature", + ScandicGo: "scandicgo", + Regular: "regular", +} as const + +export type HotelType = (typeof HotelTypes)[keyof typeof HotelTypes] diff --git a/packages/trpc/lib/enums/rateType.ts b/packages/common/constants/rateType.ts similarity index 100% rename from packages/trpc/lib/enums/rateType.ts rename to packages/common/constants/rateType.ts diff --git a/packages/common/constants/signatureHotels.ts b/packages/common/constants/signatureHotels.ts new file mode 100644 index 000000000..1ea37e868 --- /dev/null +++ b/packages/common/constants/signatureHotels.ts @@ -0,0 +1,8 @@ +export enum SignatureHotelEnum { + DowntownCamper = "879", + GrandHotelOslo = "340", + Haymarket = "890", + HotelNorge = "785", + Marski = "605", + TheDock = "796", +} diff --git a/packages/common/package.json b/packages/common/package.json index 494d64c79..9588f0a60 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -33,12 +33,16 @@ "./utils/isValidJson": "./utils/isValidJson.ts", "./hooks/*": "./hooks/*.ts", "./stores/*": "./stores/*.ts", + "./constants/currency": "./constants/currency.ts", + "./constants/dateFormats": "./constants/dateFormats.ts", + "./constants/facilities": "./constants/facilities.ts", + "./constants/hotelType": "./constants/hotelType.ts", "./constants/language": "./constants/language.ts", "./constants/membershipLevels": "./constants/membershipLevels.ts", "./constants/paymentMethod": "./constants/paymentMethod.ts", - "./constants/currency": "./constants/currency.ts", - "./constants/dateFormats": "./constants/dateFormats.ts", - "./constants/routes/*": "./constants/routes/*.ts" + "./constants/rateType": "./constants/rateType.ts", + "./constants/routes/*": "./constants/routes/*.ts", + "./constants/signatureHotels": "./constants/signatureHotels.ts" }, "dependencies": { "@opentelemetry/api": "^1.9.0", diff --git a/packages/design-system/.storybook/main.ts b/packages/design-system/.storybook/main.ts index 42b3c3b83..d52dbedd3 100644 --- a/packages/design-system/.storybook/main.ts +++ b/packages/design-system/.storybook/main.ts @@ -1,5 +1,6 @@ -import { dirname, join } from 'path' import type { StorybookConfig } from '@storybook/nextjs-vite' +import { dirname, join } from 'path' +import { mergeConfig } from 'vite' const config: StorybookConfig = { stories: ['../lib/**/*.mdx', '../lib/**/*.stories.@(js|jsx|mjs|ts|tsx)'], @@ -9,11 +10,42 @@ const config: StorybookConfig = { getAbsolutePath('@storybook/addon-vitest'), getAbsolutePath('@storybook/addon-docs'), getAbsolutePath('@storybook/addon-a11y'), + getAbsolutePath('storybook-react-intl'), ], framework: { name: getAbsolutePath('@storybook/nextjs-vite'), options: {}, }, + async viteFinal(config) { + return mergeConfig(config, { + plugins: [ + // Add babel plugin for react-intl transformation + { + name: 'formatjs-transform', + async transform(code, id) { + if (id.includes('node_modules')) return + if (!/\.(jsx?|tsx?)$/.test(id)) return + + const babel = await import('@babel/core') + const result = babel.transformSync(code, { + plugins: [ + [ + 'formatjs', + { + idInterpolationPattern: '[sha512:contenthash:base64:6]', + ast: true, + }, + ], + ], + filename: id, + }) + + return result?.code + }, + }, + ], + }) + }, } export default config diff --git a/packages/design-system/.storybook/preview.tsx b/packages/design-system/.storybook/preview.tsx index 67c92795b..ea5ca867d 100644 --- a/packages/design-system/.storybook/preview.tsx +++ b/packages/design-system/.storybook/preview.tsx @@ -1,9 +1,11 @@ import { withThemeByClassName } from '@storybook/addon-themes' - +import { IntlProvider } from 'react-intl' import type { Preview, ReactRenderer } from '@storybook/nextjs-vite' +import { reactIntl } from './reactIntl' import '../lib/fonts.css' import '../lib/style.css' +import '../lib/design-system-new-deprecated.css' export const themes = { themes: { @@ -19,8 +21,33 @@ export const themes = { } const preview: Preview = { - decorators: [withThemeByClassName(themes)], + decorators: [ + // Theme decorator + withThemeByClassName(themes), + (Story) => ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + + + + ), + ], + initialGlobals: { + locale: reactIntl.defaultLocale, + locales: { + en: { icon: '🇬🇧', title: 'English', right: 'EN' }, + sv: { icon: '🇸🇪', title: 'Svenska', right: 'SV' }, + da: { icon: '🇩🇰', title: 'Dansk', right: 'DA' }, + no: { icon: '🇳🇴', title: 'Norsk', right: 'NO' }, + fi: { icon: '🇫🇮', title: 'Suomi', right: 'FI' }, + de: { icon: '🇩🇪', title: 'Deutsch', right: 'DE' }, + }, + backgrounds: { value: 'scandicSubtle' }, + }, parameters: { + reactIntl, + nextjs: { + appDirectory: true, + }, docs: { toc: true, }, @@ -31,18 +58,18 @@ const preview: Preview = { }, }, backgrounds: { - values: [ + options: { // 👇 Scandic - { name: 'Scandic Primary', value: '#FAF6F2' }, - { name: 'Scandic Subtle', value: '#F2ECE6' }, - { name: 'Scandic Primary Dark', value: '#4D001B' }, + scandicPrimary: { name: 'Scandic Primary', value: '#FAF6F2' }, + scandicSubtle: { name: 'Scandic Subtle', value: '#F2ECE6' }, + scandicPrimaryDark: { name: 'Scandic Primary Dark', value: '#4D001B' }, // 👇 Default values - { name: 'Storybook Dark', value: '#333' }, - { name: 'Storybook Light', value: '#F7F9F2' }, - ], - default: 'Scandic Primary', + storybookDark: { name: 'Storybook Dark', value: '#333' }, + storybookLight: { name: 'Storybook Light', value: '#F7F9F2' }, + }, }, }, + tags: ['autodocs'], } diff --git a/packages/design-system/.storybook/reactIntl.ts b/packages/design-system/.storybook/reactIntl.ts new file mode 100644 index 000000000..c978007fd --- /dev/null +++ b/packages/design-system/.storybook/reactIntl.ts @@ -0,0 +1,27 @@ +/* eslint-disable import/no-relative-packages */ +import en from '../../../apps/scandic-web/i18n/dictionaries/en.json' +import sv from '../../../apps/scandic-web/i18n/dictionaries/sv.json' +import da from '../../../apps/scandic-web/i18n/dictionaries/da.json' +import fi from '../../../apps/scandic-web/i18n/dictionaries/fi.json' +import de from '../../../apps/scandic-web/i18n/dictionaries/de.json' +import no from '../../../apps/scandic-web/i18n/dictionaries/no.json' + +const locales = ['en', 'sv', 'da', 'fi', 'no', 'de'] + +const messages: Record<(typeof locales)[number], unknown> = { + en, + sv, + da, + fi, + no, + de, +} + +const formats = {} // optional, if you have any formats + +export const reactIntl = { + defaultLocale: 'en', + locales, + messages, + formats, +} diff --git a/packages/design-system/eslint.config.mjs b/packages/design-system/eslint.config.mjs index 4a620cf30..e4749dda2 100644 --- a/packages/design-system/eslint.config.mjs +++ b/packages/design-system/eslint.config.mjs @@ -5,6 +5,7 @@ import reactRefresh from 'eslint-plugin-react-refresh' import { FlatCompat } from '@eslint/eslintrc' import js from '@eslint/js' import importPlugin from 'eslint-plugin-import' +import formatjs from 'eslint-plugin-formatjs' const compat = new FlatCompat({ recommendedConfig: js.configs.recommended, @@ -28,6 +29,7 @@ export default defineConfig([ plugins: { 'react-refresh': reactRefresh, import: importPlugin, + formatjs, }, rules: { 'import/no-relative-packages': 'error', @@ -37,6 +39,18 @@ export default defineConfig([ allowConstantExport: true, }, ], + + 'formatjs/enforce-default-message': ['error', 'literal'], + 'formatjs/enforce-placeholders': ['error'], + 'formatjs/enforce-plural-rules': ['error'], + 'formatjs/no-literal-string-in-jsx': ['error'], + 'formatjs/no-multiple-whitespaces': ['error'], + 'formatjs/no-multiple-plurals': ['error'], + 'formatjs/no-invalid-icu': ['error'], + 'formatjs/no-id': ['error'], + 'formatjs/no-complex-selectors': ['error'], + 'formatjs/no-useless-message': ['error'], + 'formatjs/prefer-pound-in-plural': ['error'], }, }, globalIgnores(['**/dist', '**/.eslintrc.cjs']), diff --git a/packages/design-system/lib/components/BookingCodeChip/BookingCodeChip.stories.tsx b/packages/design-system/lib/components/BookingCodeChip/BookingCodeChip.stories.tsx new file mode 100644 index 000000000..63c7b624e --- /dev/null +++ b/packages/design-system/lib/components/BookingCodeChip/BookingCodeChip.stories.tsx @@ -0,0 +1,76 @@ +import type { Meta, StoryObj } from '@storybook/react-vite' +import { fn } from 'storybook/test' +import { BookingCodeChip } from './index' + +const meta = { + title: 'Components/BookingCodeChip', + component: BookingCodeChip, + parameters: { + layout: 'centered', + }, +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: {}, + render: () => , +} + +export const WithoutText: Story = { + args: {}, + render: () => , +} + +export const FilledIcon: Story = { + args: {}, + render: () => , +} + +export const Unavailable: Story = { + args: {}, + render: () => , +} + +export const AlignCenter: Story = { + args: {}, + render: () => , +} + +export const WithCloseButton: Story = { + args: {}, + render: () => ( + + ), +} + +export const CampaignBreakfastIncluded: Story = { + args: {}, + render: () => ( + + ), +} + +export const CampaignBreakfastExcluded: Story = { + args: {}, + render: () => ( + + ), +} + +export const CampaignFilledIcon: Story = { + args: {}, + render: () => ( + + ), +} diff --git a/apps/scandic-web/components/BookingCodeChip/bookingCodeChip.module.css b/packages/design-system/lib/components/BookingCodeChip/bookingCodeChip.module.css similarity index 100% rename from apps/scandic-web/components/BookingCodeChip/bookingCodeChip.module.css rename to packages/design-system/lib/components/BookingCodeChip/bookingCodeChip.module.css diff --git a/apps/scandic-web/components/BookingCodeChip/index.tsx b/packages/design-system/lib/components/BookingCodeChip/index.tsx similarity index 73% rename from apps/scandic-web/components/BookingCodeChip/index.tsx rename to packages/design-system/lib/components/BookingCodeChip/index.tsx index 5d9e538b1..5c81519b7 100644 --- a/apps/scandic-web/components/BookingCodeChip/index.tsx +++ b/packages/design-system/lib/components/BookingCodeChip/index.tsx @@ -1,13 +1,13 @@ -import { Button as ButtonRAC } from "react-aria-components" -import { useIntl } from "react-intl" +import { Button as ButtonRAC } from 'react-aria-components' +import { useIntl } from 'react-intl' -import IconChip from "@scandic-hotels/design-system/IconChip" -import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon" -import FilledDiscountIcon from "@scandic-hotels/design-system/Icons/FilledDiscountIcon" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { Typography } from "@scandic-hotels/design-system/Typography" +import IconChip from '@scandic-hotels/design-system/IconChip' +import DiscountIcon from '@scandic-hotels/design-system/Icons/DiscountIcon' +import FilledDiscountIcon from '@scandic-hotels/design-system/Icons/FilledDiscountIcon' +import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon' +import { Typography } from '@scandic-hotels/design-system/Typography' -import styles from "./bookingCodeChip.module.css" +import styles from './bookingCodeChip.module.css' type BaseBookingCodeChipProps = { alignCenter?: boolean @@ -30,7 +30,7 @@ type BookingCodeChipProps = | BookingCodeChipWithoutCloseButtonProps | BookingCodeChipWithCloseButtonProps -export default function BookingCodeChip({ +export function BookingCodeChip({ alignCenter, bookingCode, isBreakfastIncluded, @@ -58,19 +58,19 @@ export default function BookingCodeChip({

- {intl.formatMessage({ defaultMessage: "Campaign" })} + {intl.formatMessage({ defaultMessage: 'Campaign' })} {isBreakfastIncluded ? // eslint-disable-next-line formatjs/no-literal-string-in-jsx - `${bookingCode ?? ""} ${intl.formatMessage({ - defaultMessage: "Breakfast included", + `${bookingCode ?? ''} ${intl.formatMessage({ + defaultMessage: 'Breakfast included', })}` : // eslint-disable-next-line formatjs/no-literal-string-in-jsx - `${bookingCode ?? ""} ${intl.formatMessage({ - defaultMessage: "Breakfast excluded", + `${bookingCode ?? ''} ${intl.formatMessage({ + defaultMessage: 'Breakfast excluded', })}`} @@ -96,12 +96,14 @@ export default function BookingCodeChip({ className={alignCenter ? styles.center : undefined} >

{withText && ( - {intl.formatMessage({ defaultMessage: "Booking code" })} + {intl.formatMessage({ + defaultMessage: 'Booking code', + })} )} diff --git a/packages/design-system/lib/components/Button/Button.stories.tsx b/packages/design-system/lib/components/Button/Button.stories.tsx index 33cfeebd0..9990cd671 100644 --- a/packages/design-system/lib/components/Button/Button.stories.tsx +++ b/packages/design-system/lib/components/Button/Button.stories.tsx @@ -556,6 +556,7 @@ export const TextWithIcon: Story = { args: { onPress: fn(), children: ( + // eslint-disable-next-line formatjs/no-literal-string-in-jsx <> Text with icon @@ -577,6 +578,7 @@ export const TextWithIconInverted: Story = { args: { onPress: fn(), children: ( + // eslint-disable-next-line formatjs/no-literal-string-in-jsx <> Text with icon diff --git a/packages/design-system/lib/components/Chip/index.tsx b/packages/design-system/lib/components/Chip/index.tsx index 560eb5a3f..d5a5740d4 100644 --- a/packages/design-system/lib/components/Chip/index.tsx +++ b/packages/design-system/lib/components/Chip/index.tsx @@ -1,10 +1,9 @@ -import Footnote from '../Footnote' +import Footnote from '@scandic-hotels/design-system/Footnote' import { chipVariants } from './variants' +import { VariantProps } from 'class-variance-authority' -import type { VariantProps } from 'class-variance-authority' - -interface ChipProps +export interface ChipProps extends React.HtmlHTMLAttributes, VariantProps {} diff --git a/packages/design-system/lib/components/FacilityToIcon/FacilityToIcon.stories.tsx b/packages/design-system/lib/components/FacilityToIcon/FacilityToIcon.stories.tsx new file mode 100644 index 000000000..b7524430f --- /dev/null +++ b/packages/design-system/lib/components/FacilityToIcon/FacilityToIcon.stories.tsx @@ -0,0 +1,96 @@ +import type { Meta, StoryObj } from '@storybook/react-vite' + +import { FacilityEnum } from '@scandic-hotels/common/constants/facilities' + +import { FacilityToIcon } from '.' +import { iconVariantConfig } from '../Icons/variants' + +const facilityMapping: Record = Object.fromEntries( + Object.entries(FacilityEnum).filter(([k]) => isNaN(Number(k))) +) as Record + +const colorOptions = Object.keys(iconVariantConfig.variants.color) + +const meta: Meta = { + title: 'Components/Facility To Icon', + component: FacilityToIcon, + argTypes: { + id: { + control: 'select', + options: Object.keys(FacilityEnum) + .map((key) => FacilityEnum[key as keyof typeof FacilityEnum]) + .filter((x) => typeof x === 'string') + .toSorted(), + mapping: facilityMapping, + description: 'Facility identifier (mapped to the corresponding icon)', + }, + color: { + control: 'select', + options: colorOptions, + description: 'Icon color variant', + }, + size: { + control: 'number', + description: 'Icon pixel size', + }, + }, +} + +export default meta + +type Story = StoryObj + +export const Playground: Story = { + args: { + id: FacilityEnum.Bar, + size: 24, + color: 'Icon/Default', + }, +} + +const exampleFacilities = [ + FacilityEnum.AirConAirCooling, + FacilityEnum.AirportMaxDistance8Km, + FacilityEnum.Bar, + FacilityEnum.CashFreeHotel, + FacilityEnum.ChildrenWelcome, + FacilityEnum.Elevator, + FacilityEnum.Gym, + FacilityEnum.ParkingGarage, + FacilityEnum.ParkingOutdoor, + FacilityEnum.Pool, + FacilityEnum.Tennis1, +] + +export const Examples: Story = { + args: { + size: 24, + color: 'Icon/Default', + }, + render: (args) => ( +

+ {exampleFacilities.map((key) => ( +
+ + {FacilityEnum[key]} +
+ ))} +
+ ), +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/data.tsx b/packages/design-system/lib/components/FacilityToIcon/index.tsx similarity index 97% rename from apps/scandic-web/components/ContentType/HotelPage/data.tsx rename to packages/design-system/lib/components/FacilityToIcon/index.tsx index 6d1a622d6..2bc9dde3e 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/data.tsx +++ b/packages/design-system/lib/components/FacilityToIcon/index.tsx @@ -1,13 +1,26 @@ -import { IconByIconName } from "@scandic-hotels/design-system/Icons/IconByIconName" -import { IconName } from "@scandic-hotels/design-system/Icons/iconName" -import { FacilityEnum } from "@scandic-hotels/trpc/enums/facilities" +import { FacilityEnum } from '@scandic-hotels/common/constants/facilities' -import type { - IconProps, - NucleoIconProps, -} from "@scandic-hotels/design-system/Icons" -import type { MaterialIconSetIconProps } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import type { JSX } from "react" +import type { JSX } from 'react' +import { IconName } from '../Icons/iconName' +import { MaterialIconSetIconProps } from '../Icons/MaterialIcon' +import { IconProps, NucleoIconProps } from '../Icons' +import { IconByIconName } from '../Icons/IconByIconName' + +interface mapFacilityToIconProps { + id: FacilityEnum +} +export function FacilityToIcon({ + id, + ...props +}: mapFacilityToIconProps & + ( + | MaterialIconSetIconProps + | NucleoIconProps + | IconProps + )): JSX.Element | null { + const iconName = facilityToIconMap[id] + return +} const facilityToIconMap: Record = { [FacilityEnum.AccessibleBathingControls]: IconName.StarFilled, @@ -287,19 +300,3 @@ const facilityToIconMap: Record = { [FacilityEnum.WideRestaurantEntrance]: IconName.StarFilled, [FacilityEnum.WiFiWirelessInternetAccessAllScandic]: IconName.StarFilled, } - -interface mapFacilityToIconProps { - id: FacilityEnum -} -export function FacilityToIcon({ - id, - ...props -}: mapFacilityToIconProps & - ( - | MaterialIconSetIconProps - | NucleoIconProps - | IconProps - )): JSX.Element | null { - const iconName = facilityToIconMap[id] - return -} diff --git a/packages/design-system/lib/components/HotelCard/HotelCard.stories.tsx b/packages/design-system/lib/components/HotelCard/HotelCard.stories.tsx new file mode 100644 index 000000000..6aff911df --- /dev/null +++ b/packages/design-system/lib/components/HotelCard/HotelCard.stories.tsx @@ -0,0 +1,101 @@ +import type { Meta, StoryObj } from '@storybook/react-vite' +import { HotelCard } from './index' + +import { fn } from 'storybook/test' +import { RateTypeEnum } from '@scandic-hotels/common/constants/rateType' +import { HotelTypeEnum } from '@scandic-hotels/trpc/enums/hotelType' +import { Button } from '@scandic-hotels/design-system/Button' +import { MaterialIcon } from '../Icons/MaterialIcon' + +const meta: Meta = { + title: 'Components/HotelCard', + component: HotelCard, + argTypes: { + state: { + control: { + type: 'select', + options: ['default', 'active'], + }, + }, + type: { + control: { + type: 'select', + options: ['mapListing', 'pageListing'], + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + hotel: { + id: '1', + name: 'Test Hotel', + address: { streetAddress: '123 Test Street', city: 'Test City' }, + description: 'A great place to stay.', + hotelType: HotelTypeEnum.Signature, + detailedFacilities: [], + ratings: { + tripAdvisor: 4, + }, + }, + prices: { + public: { + rateType: RateTypeEnum.Regular, + localPrice: { + currency: 'SEK', + pricePerNight: 1000, + pricePerStay: 1000, + }, + }, + member: { + rateType: RateTypeEnum.Regular, + localPrice: { + currency: 'SEK', + pricePerNight: 800, + pricePerStay: 800, + }, + }, + }, + state: 'default', + isAlternative: false, + type: 'pageListing', + isUserLoggedIn: false, + distanceToCityCenter: 0, + bookingCode: 'ABC123', + images: [ + { + src: 'img/img2.jpg', + alt: 'Alt text', + smallSrc: 'img/img2.jpg', + caption: 'Caption', + }, + ], + + belowInfoSlot: ( + + ), + onAddressClick: fn, + onHover: fn, + onHoverEnd: fn, + }, +} + +export const MapListing: Story = { + args: { + ...Default.args, + type: 'mapListing', + }, +} diff --git a/apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/hotelCardDialogImage.module.css b/packages/design-system/lib/components/HotelCard/HotelCardDialogImage/hotelCardDialogImage.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/hotelCardDialogImage.module.css rename to packages/design-system/lib/components/HotelCard/HotelCardDialogImage/hotelCardDialogImage.module.css diff --git a/packages/design-system/lib/components/HotelCard/HotelCardDialogImage/index.tsx b/packages/design-system/lib/components/HotelCard/HotelCardDialogImage/index.tsx new file mode 100644 index 000000000..0efe5da68 --- /dev/null +++ b/packages/design-system/lib/components/HotelCard/HotelCardDialogImage/index.tsx @@ -0,0 +1,51 @@ +import TripadvisorIcon from '@scandic-hotels/design-system/Icons/TripadvisorIcon' +import Image from '@scandic-hotels/design-system/Image' + +import Chip from '@scandic-hotels/design-system/Chip' + +import { hotelCardDialogImageVariants } from './variants' + +import styles from './hotelCardDialogImage.module.css' + +export type HotelCardDialogImageProps = { + firstImage?: string + altText?: string + rating?: { tripAdvisor?: number | null } + imageError: boolean + setImageError: (error: boolean) => void + position: 'top' | 'left' +} + +export function HotelCardDialogImage({ + firstImage, + altText, + rating, + imageError, + setImageError, + position, +}: HotelCardDialogImageProps) { + const classNames = hotelCardDialogImageVariants({ position }) + + return ( +
+ {!firstImage || imageError ? ( +
+ ) : ( + {altText setImageError(true)} + /> + )} + {rating?.tripAdvisor && ( +
+ + + {rating.tripAdvisor} + +
+ )} +
+ ) +} diff --git a/apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/variants.ts b/packages/design-system/lib/components/HotelCard/HotelCardDialogImage/variants.ts similarity index 61% rename from apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/variants.ts rename to packages/design-system/lib/components/HotelCard/HotelCardDialogImage/variants.ts index 8ca5bb582..26aa1867e 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCardDialog/HotelCardDialogImage/variants.ts +++ b/packages/design-system/lib/components/HotelCard/HotelCardDialogImage/variants.ts @@ -1,6 +1,6 @@ -import { cva } from "class-variance-authority" +import { cva } from 'class-variance-authority' -import styles from "./hotelCardDialogImage.module.css" +import styles from './hotelCardDialogImage.module.css' export const hotelCardDialogImageVariants = cva(styles.imageContainer, { variants: { @@ -10,6 +10,6 @@ export const hotelCardDialogImageVariants = cva(styles.imageContainer, { }, }, defaultVariants: { - position: "top", + position: 'top', }, }) diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelCardSkeleton.module.css b/packages/design-system/lib/components/HotelCard/HotelCardSkeleton.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelCardSkeleton.module.css rename to packages/design-system/lib/components/HotelCard/HotelCardSkeleton.module.css diff --git a/packages/design-system/lib/components/HotelCard/HotelCardSkeleton.tsx b/packages/design-system/lib/components/HotelCard/HotelCardSkeleton.tsx new file mode 100644 index 000000000..66c553f91 --- /dev/null +++ b/packages/design-system/lib/components/HotelCard/HotelCardSkeleton.tsx @@ -0,0 +1,34 @@ +import SkeletonShimmer from '@scandic-hotels/design-system/SkeletonShimmer' + +import styles from './HotelCardSkeleton.module.css' + +export function HotelCardSkeleton() { + return ( +
+ {/* image container */} +
+ +
+ +
+ +
+ + + + +
+ + +
+ +
+ {/* price variants */} + {Array.from({ length: 2 }).map((_, index) => ( + + ))} + +
+
+ ) +} diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelChequeCard/hotelChequeCard.module.css b/packages/design-system/lib/components/HotelCard/HotelChequeCard/hotelChequeCard.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelChequeCard/hotelChequeCard.module.css rename to packages/design-system/lib/components/HotelCard/HotelChequeCard/hotelChequeCard.module.css diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelChequeCard/index.tsx b/packages/design-system/lib/components/HotelCard/HotelChequeCard/index.tsx similarity index 76% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelChequeCard/index.tsx rename to packages/design-system/lib/components/HotelCard/HotelChequeCard/index.tsx index 6626b1b70..be0343c32 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/HotelChequeCard/index.tsx +++ b/packages/design-system/lib/components/HotelCard/HotelChequeCard/index.tsx @@ -1,12 +1,12 @@ -import { useIntl } from "react-intl" +import { useIntl } from 'react-intl' -import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" -import Caption from "@scandic-hotels/design-system/Caption" -import Subtitle from "@scandic-hotels/design-system/Subtitle" +import { CurrencyEnum } from '@scandic-hotels/common/constants/currency' +import Caption from '@scandic-hotels/design-system/Caption' +import Subtitle from '@scandic-hotels/design-system/Subtitle' -import styles from "./hotelChequeCard.module.css" +import styles from './hotelChequeCard.module.css' -import type { ProductTypeCheque } from "@scandic-hotels/trpc/types/availability" +import type { ProductTypeCheque } from '@scandic-hotels/trpc/types/availability' export default function HotelChequeCard({ productTypeCheque, @@ -19,7 +19,7 @@ export default function HotelChequeCard({
{intl.formatMessage({ - defaultMessage: "From", + defaultMessage: 'From', })}
@@ -29,7 +29,7 @@ export default function HotelChequeCard({ {CurrencyEnum.CC} {productTypeCheque.localPrice.additionalPricePerStay > 0 ? ( <> - {"+"} + {'+'} {productTypeCheque.localPrice.additionalPricePerStay} @@ -45,15 +45,15 @@ export default function HotelChequeCard({
{intl.formatMessage({ - defaultMessage: "Approx.", + defaultMessage: 'Approx.', })} - + {productTypeCheque.requestedPrice.numberOfCheques} {CurrencyEnum.CC} {productTypeCheque.requestedPrice.additionalPricePerStay ? // eslint-disable-next-line formatjs/no-literal-string-in-jsx - " + " - : ""} + ' + ' + : ''} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {`${productTypeCheque.requestedPrice.additionalPricePerStay} ${productTypeCheque.requestedPrice.currency}`} diff --git a/packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/StandaloneHotelCardDialog.stories.tsx b/packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/StandaloneHotelCardDialog.stories.tsx new file mode 100644 index 000000000..9c45db049 --- /dev/null +++ b/packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/StandaloneHotelCardDialog.stories.tsx @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from '@storybook/react-vite' +import { StandaloneHotelCardDialog } from './index' + +import { fn } from 'storybook/test' + +const meta: Meta = { + title: 'Components/StandaloneHotelCardDialog', + component: StandaloneHotelCardDialog, + argTypes: {}, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + data: { + name: 'Hotel Name', + image: { + url: 'img/img2.jpg', + alt: 'Alt text', + }, + coordinates: { + lat: 0, + lng: 0, + }, + chequePrice: null, + publicPrice: 100, + memberPrice: 200, + redemptionPrice: null, + voucherPrice: null, + rateType: null, + currency: 'SEK', + amenities: [], + ratings: { tripAdvisor: 5 }, + operaId: '123', + facilityIds: [], + hasEnoughPoints: false, + }, + handleClose: fn(), + }, +} diff --git a/apps/scandic-web/components/HotelReservation/HotelCardDialog/StandaloneHotelCardDialog/index.tsx b/packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/index.tsx similarity index 68% rename from apps/scandic-web/components/HotelReservation/HotelCardDialog/StandaloneHotelCardDialog/index.tsx rename to packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/index.tsx index bdcfa47ba..c468309f5 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCardDialog/StandaloneHotelCardDialog/index.tsx +++ b/packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/index.tsx @@ -1,46 +1,45 @@ -"use client" -import { useSession } from "next-auth/react" -import { useState } from "react" -import { useIntl } from "react-intl" +'use client' -import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation" -import Body from "@scandic-hotels/design-system/Body" -import Caption from "@scandic-hotels/design-system/Caption" -import Footnote from "@scandic-hotels/design-system/Footnote" -import { IconButton } from "@scandic-hotels/design-system/IconButton" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import Link from "@scandic-hotels/design-system/Link" -import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton" -import Subtitle from "@scandic-hotels/design-system/Subtitle" -import { Typography } from "@scandic-hotels/design-system/Typography" +import { useState } from 'react' +import { useIntl } from 'react-intl' -import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" -import useLang from "@/hooks/useLang" -import { isValidClientSession } from "@/utils/clientSession" -import { trackEvent } from "@/utils/tracking/base" +import { selectRate } from '@scandic-hotels/common/constants/routes/hotelReservation' +import Body from '@scandic-hotels/design-system/Body' +import Caption from '@scandic-hotels/design-system/Caption' +import Footnote from '@scandic-hotels/design-system/Footnote' +import { IconButton } from '@scandic-hotels/design-system/IconButton' +import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon' +import Link from '@scandic-hotels/design-system/Link' +import { OldDSButton as Button } from '@scandic-hotels/design-system/OldDSButton' +import Subtitle from '@scandic-hotels/design-system/Subtitle' +import { Typography } from '@scandic-hotels/design-system/Typography' -import HotelPointsRow from "../../HotelCard/HotelPointsRow" -import NoPriceAvailableCard from "../../HotelCard/NoPriceAvailableCard" -import HotelCardDialogImage from "../HotelCardDialogImage" +import { NoPriceAvailableCard } from '../../NoPriceAvailableCard' +import { HotelCardDialogImage } from '../../HotelCardDialogImage' -import styles from "./standaloneHotelCardDialog.module.css" - -import type { HotelPin } from "@/types/components/hotelReservation/selectHotel/map" +import styles from './standaloneHotelCardDialog.module.css' +import { Lang } from '@scandic-hotels/common/constants/language' +import { HotelPin } from '../../../Map/types' +import { FacilityToIcon } from '@scandic-hotels/design-system/FacilityToIcon' +import { HotelPointsRow } from '../../HotelPointsRow' interface StandaloneHotelCardProps { data: HotelPin + lang: Lang + isUserLoggedIn: boolean handleClose: () => void + onClick?: () => void } -export default function StandaloneHotelCardDialog({ +export function StandaloneHotelCardDialog({ data, + lang, handleClose, + isUserLoggedIn, + onClick, }: StandaloneHotelCardProps) { const intl = useIntl() - const lang = useLang() const [imageError, setImageError] = useState(false) - const { data: session } = useSession() - const isUserLoggedIn = isValidClientSession(session) const { name, chequePrice, @@ -50,16 +49,14 @@ export default function StandaloneHotelCardDialog({ voucherPrice, currency, amenities, - images, + image, ratings, operaId, hasEnoughPoints, } = data - const firstImage = images[0]?.imageSizes?.small - const altText = images[0]?.metaData?.altText const notEnoughPointsLabel = intl.formatMessage({ - defaultMessage: "Not enough points", + defaultMessage: 'Not enough points', }) const shouldShowNotEnoughPoints = redemptionPrice && !hasEnoughPoints @@ -72,15 +69,15 @@ export default function StandaloneHotelCardDialog({ className={styles.closeButton} onPress={handleClose} aria-label={intl.formatMessage({ - defaultMessage: "Close", + defaultMessage: 'Close', })} > - {Icon && Icon} + {Icon} {facility.name} @@ -115,13 +112,13 @@ export default function StandaloneHotelCardDialog({ {redemptionPrice ? ( {intl.formatMessage({ - defaultMessage: "Available rates", + defaultMessage: 'Available rates', })} ) : ( {intl.formatMessage({ - defaultMessage: "From", + defaultMessage: 'From', })} )} @@ -129,19 +126,19 @@ export default function StandaloneHotelCardDialog({ {intl.formatMessage( { - defaultMessage: "{price} {currency}", + defaultMessage: '{price} {currency}', }, { price: chequePrice.numberOfCheques, - currency: "CC", + currency: 'CC', } )} {chequePrice.additionalPricePerStay > 0 ? // eslint-disable-next-line formatjs/no-literal-string-in-jsx - " + " + + ' + ' + intl.formatMessage( { - defaultMessage: "{price} {currency}", + defaultMessage: '{price} {currency}', }, { price: chequePrice.additionalPricePerStay, @@ -154,7 +151,7 @@ export default function StandaloneHotelCardDialog({ / {intl.formatMessage({ - defaultMessage: "night", + defaultMessage: 'night', })} @@ -164,7 +161,7 @@ export default function StandaloneHotelCardDialog({ {intl.formatMessage( { - defaultMessage: "{price} {currency}", + defaultMessage: '{price} {currency}', }, { price: voucherPrice, @@ -176,7 +173,7 @@ export default function StandaloneHotelCardDialog({ / {intl.formatMessage({ - defaultMessage: "night", + defaultMessage: 'night', })} @@ -186,7 +183,7 @@ export default function StandaloneHotelCardDialog({ {intl.formatMessage( { - defaultMessage: "{price} {currency}", + defaultMessage: '{price} {currency}', }, { price: publicPrice, @@ -198,7 +195,7 @@ export default function StandaloneHotelCardDialog({ / {intl.formatMessage({ - defaultMessage: "night", + defaultMessage: 'night', })} @@ -208,7 +205,7 @@ export default function StandaloneHotelCardDialog({ {intl.formatMessage( { - defaultMessage: "{price} {currency}", + defaultMessage: '{price} {currency}', }, { price: memberPrice, @@ -220,7 +217,7 @@ export default function StandaloneHotelCardDialog({ / {intl.formatMessage({ - defaultMessage: "night", + defaultMessage: 'night', })} @@ -242,17 +239,7 @@ export default function StandaloneHotelCardDialog({ theme="base" size="small" className={styles.button} - onClick={() => - trackEvent({ - event: "hotelClickMap", - map: { - action: "hotel click - map", - }, - hotelInfo: { - hotelId: operaId, - }, - }) - } + onClick={onClick} > {intl.formatMessage({ - defaultMessage: "See rooms", + defaultMessage: 'See rooms', })} diff --git a/apps/scandic-web/components/HotelReservation/HotelCardDialog/StandaloneHotelCardDialog/standaloneHotelCardDialog.module.css b/packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/standaloneHotelCardDialog.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCardDialog/StandaloneHotelCardDialog/standaloneHotelCardDialog.module.css rename to packages/design-system/lib/components/HotelCard/HotelDialogCard/StandaloneHotelCardDialog/standaloneHotelCardDialog.module.css diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsRow/hotelPointsRow.module.css b/packages/design-system/lib/components/HotelCard/HotelPointsRow/hotelPointsRow.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsRow/hotelPointsRow.module.css rename to packages/design-system/lib/components/HotelCard/HotelPointsRow/hotelPointsRow.module.css diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsRow/index.tsx b/packages/design-system/lib/components/HotelCard/HotelPointsRow/index.tsx similarity index 61% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsRow/index.tsx rename to packages/design-system/lib/components/HotelCard/HotelPointsRow/index.tsx index be51dd37f..555b4695f 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsRow/index.tsx +++ b/packages/design-system/lib/components/HotelCard/HotelPointsRow/index.tsx @@ -1,13 +1,16 @@ -import { useIntl } from "react-intl" +import { useIntl } from 'react-intl' -import Caption from "@scandic-hotels/design-system/Caption" -import Subtitle from "@scandic-hotels/design-system/Subtitle" +import Caption from '@scandic-hotels/design-system/Caption' +import Subtitle from '@scandic-hotels/design-system/Subtitle' -import styles from "./hotelPointsRow.module.css" +import styles from './hotelPointsRow.module.css' -import type { PointsRowProps } from "@/types/components/hotelReservation/selectHotel/priceCardProps" - -export default function HotelPointsRow({ +export type PointsRowProps = { + pointsPerStay: number + additionalPricePerStay?: number + additionalPriceCurrency?: string +} +export function HotelPointsRow({ pointsPerStay, additionalPricePerStay, additionalPriceCurrency, @@ -21,12 +24,12 @@ export default function HotelPointsRow({ {intl.formatMessage({ - defaultMessage: "Points", + defaultMessage: 'Points', })} {additionalPricePerStay ? ( <> - {"+"} + {'+'} {additionalPricePerStay} diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPriceCard/hotelPriceCard.module.css b/packages/design-system/lib/components/HotelCard/HotelPriceCard/hotelPriceCard.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelPriceCard/hotelPriceCard.module.css rename to packages/design-system/lib/components/HotelCard/HotelPriceCard/hotelPriceCard.module.css diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPriceCard/index.tsx b/packages/design-system/lib/components/HotelCard/HotelPriceCard/index.tsx similarity index 69% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelPriceCard/index.tsx rename to packages/design-system/lib/components/HotelCard/HotelPriceCard/index.tsx index c644cda82..138a53f07 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPriceCard/index.tsx +++ b/packages/design-system/lib/components/HotelCard/HotelPriceCard/index.tsx @@ -1,17 +1,31 @@ -import { cx } from "class-variance-authority" -import { useIntl } from "react-intl" +import { cx } from 'class-variance-authority' +import { useIntl } from 'react-intl' -import Body from "@scandic-hotels/design-system/Body" -import Caption from "@scandic-hotels/design-system/Caption" -import { Divider } from "@scandic-hotels/design-system/Divider" -import Subtitle from "@scandic-hotels/design-system/Subtitle" -import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType" +import Body from '@scandic-hotels/design-system/Body' +import Caption from '@scandic-hotels/design-system/Caption' +import { Divider } from '@scandic-hotels/design-system/Divider' +import Subtitle from '@scandic-hotels/design-system/Subtitle' +import { RateTypeEnum } from '@scandic-hotels/common/constants/rateType' -import styles from "./hotelPriceCard.module.css" +import styles from './hotelPriceCard.module.css' -import type { PriceCardProps } from "@/types/components/hotelReservation/selectHotel/priceCardProps" +type Price = { + pricePerStay: number + pricePerNight: number + currency: string +} -export default function HotelPriceCard({ +export type PriceCardProps = { + productTypePrices: { + rateType: RateTypeEnum + localPrice: Price + requestedPrice?: Price + } + isMemberPrice?: boolean + className?: string +} + +export function HotelPriceCard({ productTypePrices, isMemberPrice = false, className, @@ -29,7 +43,7 @@ export default function HotelPriceCard({
{intl.formatMessage({ - defaultMessage: "Member price", + defaultMessage: 'Member price', })}
@@ -39,7 +53,7 @@ export default function HotelPriceCard({
{intl.formatMessage({ - defaultMessage: "Standard price", + defaultMessage: 'Standard price', })}
@@ -49,10 +63,10 @@ export default function HotelPriceCard({
{intl.formatMessage({ - defaultMessage: "From", + defaultMessage: 'From', })}
@@ -60,12 +74,12 @@ export default function HotelPriceCard({
{productTypePrices.localPrice.pricePerNight} {productTypePrices.localPrice.currency} @@ -73,7 +87,7 @@ export default function HotelPriceCard({ / {intl.formatMessage({ - defaultMessage: "night", + defaultMessage: 'night', })} @@ -85,12 +99,12 @@ export default function HotelPriceCard({
{intl.formatMessage({ - defaultMessage: "Approx.", + defaultMessage: 'Approx.', })}
- + {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {`${productTypePrices.requestedPrice.pricePerNight} `} {productTypePrices.requestedPrice.currency} @@ -108,12 +122,12 @@ export default function HotelPriceCard({
{intl.formatMessage({ - defaultMessage: "Total", + defaultMessage: 'Total', })}
- + {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {`${productTypePrices.localPrice.pricePerStay} `} {productTypePrices.localPrice.currency} diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelVoucherCard/hotelVoucherCard.module.css b/packages/design-system/lib/components/HotelCard/HotelVoucherCard/hotelVoucherCard.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelVoucherCard/hotelVoucherCard.module.css rename to packages/design-system/lib/components/HotelCard/HotelVoucherCard/hotelVoucherCard.module.css diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelVoucherCard/index.tsx b/packages/design-system/lib/components/HotelCard/HotelVoucherCard/index.tsx similarity index 62% rename from apps/scandic-web/components/HotelReservation/HotelCard/HotelVoucherCard/index.tsx rename to packages/design-system/lib/components/HotelCard/HotelVoucherCard/index.tsx index fe24bacf9..d2e38c466 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/HotelVoucherCard/index.tsx +++ b/packages/design-system/lib/components/HotelCard/HotelVoucherCard/index.tsx @@ -1,12 +1,12 @@ -import { useIntl } from "react-intl" +import { useIntl } from 'react-intl' -import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" -import Caption from "@scandic-hotels/design-system/Caption" -import Subtitle from "@scandic-hotels/design-system/Subtitle" +import { CurrencyEnum } from '@scandic-hotels/common/constants/currency' +import Caption from '@scandic-hotels/design-system/Caption' +import Subtitle from '@scandic-hotels/design-system/Subtitle' -import styles from "./hotelVoucherCard.module.css" +import styles from './hotelVoucherCard.module.css' -import type { ProductTypeVoucher } from "@scandic-hotels/trpc/types/availability" +import type { ProductTypeVoucher } from '@scandic-hotels/trpc/types/availability' export default function HotelVoucherCard({ productTypeVoucher, @@ -19,7 +19,7 @@ export default function HotelVoucherCard({
{intl.formatMessage({ - defaultMessage: "From", + defaultMessage: 'From', })}
diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/NoPriceAvailableCard/index.tsx b/packages/design-system/lib/components/HotelCard/NoPriceAvailableCard/index.tsx similarity index 53% rename from apps/scandic-web/components/HotelReservation/HotelCard/NoPriceAvailableCard/index.tsx rename to packages/design-system/lib/components/HotelCard/NoPriceAvailableCard/index.tsx index f2ce6cc7e..4f9efa925 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/NoPriceAvailableCard/index.tsx +++ b/packages/design-system/lib/components/HotelCard/NoPriceAvailableCard/index.tsx @@ -1,11 +1,11 @@ -import { useIntl } from "react-intl" +import { useIntl } from 'react-intl' -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { Typography } from "@scandic-hotels/design-system/Typography" +import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon' +import { Typography } from '@scandic-hotels/design-system/Typography' -import styles from "./noPriceAvailable.module.css" +import styles from './noPriceAvailable.module.css' -export default function NoPriceAvailableCard() { +export function NoPriceAvailableCard() { const intl = useIntl() return (
@@ -15,7 +15,7 @@ export default function NoPriceAvailableCard() { {intl.formatMessage({ defaultMessage: - "There are no rooms available that match your request.", + 'There are no rooms available that match your request.', })} diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/NoPriceAvailableCard/noPriceAvailable.module.css b/packages/design-system/lib/components/HotelCard/NoPriceAvailableCard/noPriceAvailable.module.css similarity index 100% rename from apps/scandic-web/components/HotelReservation/HotelCard/NoPriceAvailableCard/noPriceAvailable.module.css rename to packages/design-system/lib/components/HotelCard/NoPriceAvailableCard/noPriceAvailable.module.css diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/hotelCard.module.css b/packages/design-system/lib/components/HotelCard/hotelCard.module.css similarity index 99% rename from apps/scandic-web/components/HotelReservation/HotelCard/hotelCard.module.css rename to packages/design-system/lib/components/HotelCard/hotelCard.module.css index c313f23ac..7f1362fa8 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/hotelCard.module.css +++ b/packages/design-system/lib/components/HotelCard/hotelCard.module.css @@ -35,6 +35,7 @@ display: flex; flex-direction: column; padding: var(--Space-x2); + justify-content: space-between; } .hotelDescription { diff --git a/packages/design-system/lib/components/HotelCard/index.tsx b/packages/design-system/lib/components/HotelCard/index.tsx new file mode 100644 index 000000000..c0558fa22 --- /dev/null +++ b/packages/design-system/lib/components/HotelCard/index.tsx @@ -0,0 +1,377 @@ +'use client' + +import { cx } from 'class-variance-authority' +import { type ReadonlyURLSearchParams, useSearchParams } from 'next/navigation' +import { memo } from 'react' +import { useIntl } from 'react-intl' + +import { + alternativeHotelsMap, + selectHotelMap, + selectRate, +} from '@scandic-hotels/common/constants/routes/hotelReservation' +import { getSingleDecimal } from '@scandic-hotels/common/utils/numberFormatting' +import Caption from '@scandic-hotels/design-system/Caption' +import { Divider } from '@scandic-hotels/design-system/Divider' +import { FacilityToIcon } from '@scandic-hotels/design-system/FacilityToIcon' +import HotelLogoIcon from '@scandic-hotels/design-system/Icons/HotelLogoIcon' +import ImageGallery, { + GalleryImage, +} from '@scandic-hotels/design-system/ImageGallery' +import { HotelPointsRow } from './HotelPointsRow' +import { NoPriceAvailableCard } from './NoPriceAvailableCard' +import Link from '@scandic-hotels/design-system/Link' +import { Typography } from '@scandic-hotels/design-system/Typography' + +import HotelChequeCard from './HotelChequeCard' +import { HotelPriceCard } from './HotelPriceCard' +import HotelVoucherCard from './HotelVoucherCard' +import { hotelCardVariants } from './variants' + +import styles from './hotelCard.module.css' + +import type { Lang } from '@scandic-hotels/common/constants/language' +import { FacilityEnum } from '@scandic-hotels/common/constants/facilities' +import { RateTypeEnum } from '@scandic-hotels/common/constants/rateType' +import { CurrencyEnum } from '@scandic-hotels/common/constants/currency' +import { BookingCodeChip } from '../BookingCodeChip' +import { HotelType } from '@scandic-hotels/common/constants/hotelType' +import { TripAdvisorChip } from '../TripAdvisorChip' + +type Price = { + pricePerStay: number + pricePerNight: number + currency: string +} + +export type HotelCardProps = { + hotel: { + id: string + hotelType: HotelType + name: string + description?: string + detailedFacilities: { name: string; id: FacilityEnum }[] + address: { + city: string + streetAddress: string + } + ratings?: { + tripAdvisor?: number + } + } + prices: { + public?: { + rateType: RateTypeEnum + localPrice: Price + requestedPrice?: Price + } + member?: { + rateType: RateTypeEnum + localPrice: Price + requestedPrice?: Price + } + voucher?: { + numberOfVouchers: number + rateCode: string + rateType: RateTypeEnum + } + bonusCheque?: { + rateCode: string + rateType: RateTypeEnum + localPrice: { + additionalPricePerStay: number + currency: CurrencyEnum | null | undefined + numberOfCheques: number + } + requestedPrice?: { + additionalPricePerStay: number + currency: CurrencyEnum | null | undefined + numberOfCheques: number + } + } + redemptions?: { + rateCode: string + hasEnoughPoints: boolean + localPrice: { + additionalPricePerStay: number + pointsPerStay: number + currency: string + } + }[] + } + + images: GalleryImage[] + distanceToCityCenter: number + isUserLoggedIn: boolean + type?: 'mapListing' | 'pageListing' + state?: 'default' | 'active' + bookingCode?: string | null + isAlternative?: boolean + + lang: Lang + + belowInfoSlot: React.ReactNode + + onHover: () => void + onHoverEnd: () => void + onAddressClick: () => void +} + +export const HotelCard = memo( + ({ + prices, + hotel, + distanceToCityCenter, + isUserLoggedIn, + state = 'default', + type = 'pageListing', + bookingCode = '', + isAlternative, + images, + lang, + belowInfoSlot, + onAddressClick, + onHover, + onHoverEnd, + }: HotelCardProps) => { + const searchParams = useSearchParams() + + const intl = useIntl() + + const amenities = hotel.detailedFacilities.slice(0, 5) + const classNames = hotelCardVariants({ + type, + state, + }) + + const mapUrl = isAlternative + ? alternativeHotelsMap(lang) + : selectHotelMap(lang) + const handleAddressClick = (event: React.MouseEvent) => { + event.preventDefault() + onAddressClick() + } + + const addressStr = `${hotel.address.streetAddress}, ${hotel.address.city}` + const fullPrice = !bookingCode + + const hasInsufficientPoints = !prices.redemptions?.some( + (r) => r.hasEnoughPoints + ) + const notEnoughPointsLabel = intl.formatMessage({ + defaultMessage: 'Not enough points', + }) + + const isDisabled = prices.redemptions?.length && hasInsufficientPoints + + return ( +
onHover()} + onMouseLeave={() => onHoverEnd()} + > +
+
+ + {hotel.ratings?.tripAdvisor && ( + + )} +
+
+
+
+
+ + +

{hotel.name}

+
+
+
+ {type == 'mapListing' && ( + +

{addressStr}

+
+ )} + {type === 'pageListing' && ( + + +

{addressStr}

+
+ + )} +
+ +
+ +
+ + + {intl.formatMessage( + { + defaultMessage: '{number} km to city center', + }, + { + number: getSingleDecimal(distanceToCityCenter / 1000), + } + )} + + +
+
+ + {hotel.description ? ( + +

{hotel.description}

+
+ ) : null} + +
+ {amenities.map((facility) => ( +
+ + + {facility.name} + +
+ ))} +
+ {belowInfoSlot} +
+ + {!prices ? ( + + ) : ( + <> + {bookingCode && ( + + )} + {(!isUserLoggedIn || + !prices?.member || + (bookingCode && !fullPrice)) && + prices?.public && ( + + )} + {prices.member && ( + + )} + {prices?.voucher && ( + + )} + {prices?.bonusCheque && ( + + )} + {prices?.redemptions?.length ? ( +
+ + {intl.formatMessage({ + defaultMessage: 'Available rates', + })} + + {prices.redemptions.map((redemption) => ( + + ))} +
+ ) : null} + {isDisabled ? ( +
+ + {notEnoughPointsLabel} + +
+ ) : ( +
+ + + {intl.formatMessage({ + defaultMessage: 'See rooms', + })} + + +
+ )} + + )} +
+
+
+ ) + } +) + +interface PricesWrapperProps { + children: React.ReactNode + isClickable?: boolean + hotelId: string + pathname: string + removeBookingCodeFromSearchParams: boolean + searchParams: ReadonlyURLSearchParams +} +function PricesWrapper({ + children, + hotelId, + isClickable, + pathname, + removeBookingCodeFromSearchParams, + searchParams, +}: PricesWrapperProps) { + const content =
{children}
+ + if (!isClickable) { + return content + } + + const params = new URLSearchParams(searchParams) + params.delete('city') + params.set('hotel', hotelId) + + if (removeBookingCodeFromSearchParams) { + params.delete('bookingCode') + } + + const href = `${pathname}?${params.toString()}` + + return ( + + {content} + + ) +} diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/variants.ts b/packages/design-system/lib/components/HotelCard/variants.ts similarity index 66% rename from apps/scandic-web/components/HotelReservation/HotelCard/variants.ts rename to packages/design-system/lib/components/HotelCard/variants.ts index 7a136e74b..11c203057 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/variants.ts +++ b/packages/design-system/lib/components/HotelCard/variants.ts @@ -1,6 +1,6 @@ -import { cva } from "class-variance-authority" +import { cva } from 'class-variance-authority' -import styles from "./hotelCard.module.css" +import styles from './hotelCard.module.css' export const hotelCardVariants = cva(styles.card, { variants: { @@ -14,7 +14,7 @@ export const hotelCardVariants = cva(styles.card, { }, }, defaultVariants: { - type: "pageListing", - state: "default", + type: 'pageListing', + state: 'default', }, }) diff --git a/packages/design-system/lib/components/ImageGallery/index.tsx b/packages/design-system/lib/components/ImageGallery/index.tsx index 21b3a037a..86c111ead 100644 --- a/packages/design-system/lib/components/ImageGallery/index.tsx +++ b/packages/design-system/lib/components/ImageGallery/index.tsx @@ -12,7 +12,7 @@ import Lightbox from '../Lightbox' import styles from './imageGallery.module.css' -interface GalleryImage { +export interface GalleryImage { src: string alt: string caption?: string | null diff --git a/packages/design-system/lib/components/JsonToHtml/jsontohtml.module.css b/packages/design-system/lib/components/JsonToHtml/jsontohtml.module.css index 7c6e65778..f9ae18a92 100644 --- a/packages/design-system/lib/components/JsonToHtml/jsontohtml.module.css +++ b/packages/design-system/lib/components/JsonToHtml/jsontohtml.module.css @@ -77,7 +77,7 @@ .heart > .li::before, .li:has(.heart)::before { - content: url("/_static/icons/heart.svg"); + content: url('/_static/icons/heart.svg'); position: relative; height: 8px; top: 3px; @@ -94,7 +94,7 @@ .check > .li::before, .li:has(.check)::before { - content: url("/_static/icons/check-ring.svg"); + content: url('/_static/icons/check-ring.svg'); position: relative; height: 8px; top: 3px; diff --git a/packages/design-system/lib/components/JsonToHtml/types/rte/option.ts b/packages/design-system/lib/components/JsonToHtml/types/rte/option.ts index 126a5aeec..8fd2a4278 100644 --- a/packages/design-system/lib/components/JsonToHtml/types/rte/option.ts +++ b/packages/design-system/lib/components/JsonToHtml/types/rte/option.ts @@ -1,4 +1,4 @@ -import type { RTERenderMark, RTERenderOptionComponent } from "./node" +import type { RTERenderMark, RTERenderOptionComponent } from './node' export type RenderOptions = { [type: string]: RTERenderOptionComponent | RTERenderMark diff --git a/packages/design-system/lib/components/Link/Link.stories.tsx b/packages/design-system/lib/components/Link/Link.stories.tsx new file mode 100644 index 000000000..0386136b7 --- /dev/null +++ b/packages/design-system/lib/components/Link/Link.stories.tsx @@ -0,0 +1,71 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite' + +import { expect } from 'storybook/test' +import Link from '.' + +const meta: Meta = { + title: 'Components/Link', + component: Link, + argTypes: { + size: { + control: 'select', + options: ['small', 'regular', 'tiny', 'none'], + }, + scroll: { + table: { + disable: true, + }, + }, + prefetch: { + table: { + disable: true, + }, + }, + partialMatch: { + table: { + disable: true, + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + active: false, + href: 'https://www.scandichotels.com/en', + }, + render: (args) => {args.href}, + play: async ({ canvasElement }) => { + const link = canvasElement.querySelector('a') + if (!link) throw new Error('Link not found') + expect(link).toBeInTheDocument() + }, +} + +export const Focused: Story = { + args: { + ...Default.args, + }, + render: Default.render, + play: async ({ canvasElement }) => { + const link = canvasElement.querySelector('a') + if (!link) throw new Error('Link not found') + expect(link).toBeInTheDocument() + + expect(link).not.toHaveFocus() + let styles = getComputedStyle(link) + expect(styles.outlineStyle).toBe('none') + expect(parseFloat(styles.outlineWidth)).toBe(0) + + link?.focus() + + expect(link).toHaveFocus() + styles = getComputedStyle(link) + expect(styles.outlineStyle).not.toBe('none') + expect(parseFloat(styles.outlineWidth)).toBeGreaterThan(0) + }, +} diff --git a/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/HotelPin/hotelPin.module.css b/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/HotelPin/hotelPin.module.css similarity index 100% rename from apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/HotelPin/hotelPin.module.css rename to packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/HotelPin/hotelPin.module.css diff --git a/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/HotelPin/index.tsx b/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/HotelPin/index.tsx similarity index 56% rename from apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/HotelPin/index.tsx rename to packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/HotelPin/index.tsx index 205bbd66b..064d28817 100644 --- a/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/HotelPin/index.tsx +++ b/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/HotelPin/index.tsx @@ -1,12 +1,12 @@ -import { useIntl } from "react-intl" +import { useIntl } from 'react-intl' -import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { Typography } from "@scandic-hotels/design-system/Typography" +import { formatPrice } from '@scandic-hotels/common/utils/numberFormatting' +import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon' +import { Typography } from '@scandic-hotels/design-system/Typography' -import HotelMarker from "@/components/Maps/Markers/HotelMarker" +import HotelMarker from '../../../Markers/HotelMarker' -import styles from "./hotelPin.module.css" +import styles from './hotelPin.module.css' interface HotelPinProps { isActive: boolean @@ -16,7 +16,7 @@ interface HotelPinProps { hotelAdditionalCurrency?: string } -export default function HotelPin({ +export function HotelPin({ isActive, hotelPrice, currency, @@ -28,7 +28,7 @@ export default function HotelPin({ return (
@@ -36,17 +36,16 @@ export default function HotelPin({ ) : ( - + )}

{isNotAvailable - ? // eslint-disable-next-line formatjs/no-literal-string-in-jsx - "—" + ? '—' : formatPrice( intl, hotelPrice, diff --git a/apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css b/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css similarity index 100% rename from apps/scandic-web/components/Maps/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css rename to packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css diff --git a/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/index.tsx b/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/index.tsx new file mode 100644 index 000000000..e5389ace2 --- /dev/null +++ b/packages/design-system/lib/components/Map/InteractiveMap/HotelListingMapContent/index.tsx @@ -0,0 +1,122 @@ +import { + AdvancedMarker, + AdvancedMarkerAnchorPoint, + InfoWindow, +} from '@vis.gl/react-google-maps' +import { useMediaQuery } from 'usehooks-ts' + +import { HotelPin } from './HotelPin' +import type { HotelPin as HotelPinType } from '../../types' +import styles from './hotelListingMapContent.module.css' +import { StandaloneHotelCardDialog } from '../../../HotelCard/HotelDialogCard/StandaloneHotelCardDialog' +import { Lang } from '@scandic-hotels/common/constants/language' + +export type HotelListingMapContentProps = { + hotelPins: HotelPinType[] + activeHotel?: string | null + hoveredHotel?: string | null + lang: Lang + isUserLoggedIn: boolean + onClickHotel?: (hotelId: string) => void + setActiveHotel?: (args: { hotelName: string; hotelId: string } | null) => void + setHoveredHotel?: ( + args: { hotelName: string; hotelId: string } | null + ) => void +} +export function HotelListingMapContent({ + hotelPins, + activeHotel, + hoveredHotel, + isUserLoggedIn, + setActiveHotel, + setHoveredHotel, + lang, + onClickHotel, +}: HotelListingMapContentProps) { + const isDesktop = useMediaQuery('(min-width: 768px)') + + const toggleActiveHotelPin = ( + args: { hotelName: string; hotelId: string } | null + ) => { + if (!args) { + setActiveHotel?.(null) + return + } + + setActiveHotel?.({ hotelName: args.hotelName, hotelId: args.hotelId }) + } + + return ( +

+ {hotelPins.map((pin) => { + const isActiveOrHovered = + activeHotel === pin.name || hoveredHotel === pin.name + const hotelPrice = + pin.memberPrice ?? + pin.publicPrice ?? + pin.redemptionPrice ?? + pin.voucherPrice ?? + pin.chequePrice?.numberOfCheques ?? + null + + const hotelAdditionalPrice = pin.chequePrice + ? pin.chequePrice.additionalPricePerStay + : undefined + const hotelAdditionalCurrency = pin.chequePrice + ? pin.chequePrice.currency?.toString() + : undefined + + return ( + { + setHoveredHotel?.({ hotelName: pin.name, hotelId: pin.operaId }) + }} + onMouseLeave={() => { + setHoveredHotel?.(null) + }} + onClick={() => + toggleActiveHotelPin({ + hotelName: pin.name, + hotelId: pin.operaId, + }) + } + > + {isActiveOrHovered && isDesktop && ( + + { + setActiveHotel?.(null) + setHoveredHotel?.(null) + }} + onClick={() => { + onClickHotel?.(pin.operaId) + }} + /> + + )} + + + ) + })} +
+ ) +} diff --git a/packages/design-system/lib/components/Map/InteractiveMap/InteractiveMap.stories.tsx b/packages/design-system/lib/components/Map/InteractiveMap/InteractiveMap.stories.tsx new file mode 100644 index 000000000..ced358078 --- /dev/null +++ b/packages/design-system/lib/components/Map/InteractiveMap/InteractiveMap.stories.tsx @@ -0,0 +1,219 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite' + +// import { expect, fn } from 'storybook/test' +import { InteractiveMap } from '.' +import { Lang } from '@scandic-hotels/common/constants/language' +import { APIProvider } from '@vis.gl/react-google-maps' +import { useState } from 'react' + +const meta: Meta = { + title: 'Components/Map/Interactive Map', + component: InteractiveMap, + argTypes: {}, +} + +export default meta + +type Story = StoryObj + +export const PrimaryDefault: Story = { + args: { + lang: Lang.en, + hotelPins: [ + { + coordinates: { + lat: 59.331303, + lng: 18.065542, + }, + name: 'Downtown Camper by Scandic', + chequePrice: null, + publicPrice: 1100, + memberPrice: 1067, + redemptionPrice: null, + voucherPrice: null, + rateType: 'Regular', + currency: 'SEK', + + amenities: [ + { + filter: 'Hotel facilities', + icon: 'Pool', + id: 1831, + name: 'Pool', + public: true, + sortOrder: 7000, + slug: 'pool', + }, + { + filter: 'Hotel facilities', + icon: 'Restaurant', + id: 1383, + name: 'Restaurant', + public: true, + sortOrder: 6000, + slug: 'restaurant', + }, + { + filter: 'None', + icon: 'KayaksForLoan', + id: 162585, + name: 'Kayaks for loan', + public: true, + sortOrder: 5000, + slug: 'kayaks-for-loan', + }, + { + filter: 'Hotel facilities', + icon: 'None', + id: 239348, + name: 'Rooftop bar', + public: false, + sortOrder: 4000, + slug: 'rooftop-bar', + }, + { + filter: 'None', + icon: 'BikesForLoan', + id: 5550, + name: 'Bikes for loan', + public: true, + sortOrder: 3000, + slug: 'bikes-for-loan', + }, + ], + ratings: { + tripAdvisor: 4.4, + }, + operaId: '879', + facilityIds: [ + 1831, 1383, 162585, 239348, 5550, 162586, 5806, 1014, 1835, 1829, + 1379, 1382, 162587, 1017, 1378, 1408, 1833, 971, 1834, 162584, 1381, + 229144, 267806, + ], + hasEnoughPoints: false, + image: { + alt: 'Bar of Downtown Camper by Scandic in Stockholm', + url: 'https://images-test.scandichotels.com/publishedmedia/z68596isempb61xm2ns9/Scandic_Downtown_Camper_spa_wellness_the_nest_swim.jpg', + }, + }, + { + coordinates: { + lat: 59.33469, + lng: 18.061586, + }, + name: 'Haymarket by Scandic', + chequePrice: null, + publicPrice: null, + memberPrice: 9999, + redemptionPrice: null, + voucherPrice: null, + rateType: 'Regular', + currency: 'SEK', + + amenities: [ + { + filter: 'Hotel facilities', + icon: 'Restaurant', + id: 1383, + name: 'Restaurant', + public: true, + sortOrder: 6000, + slug: 'restaurant', + }, + { + filter: 'None', + icon: 'None', + id: 5806, + name: 'Meeting / conference facilities', + public: true, + sortOrder: 1500, + slug: 'meeting-conference-facilities', + }, + { + filter: 'Hotel facilities', + icon: 'Bar', + id: 1014, + name: 'Bar', + public: true, + sortOrder: 1401, + slug: 'bar', + }, + { + filter: 'Hotel facilities', + icon: 'PetFriendlyRooms', + id: 1835, + name: 'Pet-friendly rooms', + public: true, + sortOrder: 1201, + slug: 'pet-friendly-rooms', + }, + { + filter: 'Hotel facilities', + icon: 'Gym', + id: 1829, + name: 'Gym', + public: true, + sortOrder: 1101, + slug: 'gym', + }, + ], + ratings: { + tripAdvisor: 4.1, + }, + operaId: '890', + facilityIds: [ + 1383, 5806, 1014, 1835, 1829, 1382, 162587, 1017, 1833, 971, 1834, + 1381, 1406, 1913, 345180, 375885, + ], + hasEnoughPoints: false, + image: { + alt: 'Bar', + url: 'https://images-test.scandichotels.com/publishedmedia/6wobp0j1ocvoopy1dmce/haymarket-by-scandic-bar-pauls_-3-.jpg', + }, + }, + ], + isUserLoggedIn: false, + coordinates: { + lat: 59.32644916839965, + lng: 18.067759400301135, + }, + }, + render: (args) => { + const mapKey = import.meta.env.VITE_GOOGLE_STATIC_MAP_KEY + const mapId = import.meta.env.VITE_GOOGLE_DYNAMIC_MAP_ID + if (!mapKey || !mapId) { + throw new Error( + 'VITE_GOOGLE_STATIC_MAP_KEY or VITE_GOOGLE_DYNAMIC_MAP_ID is not defined in your .env file. Please add it to run this story.' + ) + } + + const [hoveredHotelPin, setHoveredHotelPin] = useState() + const [activeHotelPin, setActiveHotelPin] = useState() + + return ( + +
+ { + setHoveredHotelPin(args?.hotelName ?? null) + }} + activeHotelPin={activeHotelPin} + onSetActiveHotelPin={(args) => { + setActiveHotelPin(args?.hotelName ?? null) + }} + /> +
+
+ ) + }, +} diff --git a/apps/scandic-web/components/Maps/InteractiveMap/PoiMapMarkers/index.tsx b/packages/design-system/lib/components/Map/InteractiveMap/PoiMapMarkers/index.tsx similarity index 76% rename from apps/scandic-web/components/Maps/InteractiveMap/PoiMapMarkers/index.tsx rename to packages/design-system/lib/components/Map/InteractiveMap/PoiMapMarkers/index.tsx index 1f9c76035..fdf83c3b3 100644 --- a/apps/scandic-web/components/Maps/InteractiveMap/PoiMapMarkers/index.tsx +++ b/packages/design-system/lib/components/Map/InteractiveMap/PoiMapMarkers/index.tsx @@ -1,18 +1,18 @@ import { AdvancedMarker, AdvancedMarkerAnchorPoint, -} from "@vis.gl/react-google-maps" -import { useIntl } from "react-intl" +} from '@vis.gl/react-google-maps' +import { useIntl } from 'react-intl' -import { Typography } from "@scandic-hotels/design-system/Typography" +import { Typography } from '@scandic-hotels/design-system/Typography' -import HotelMarkerByType from "../../Markers" -import PoiMarker from "../../Markers/Poi" +import { HotelMarkerByType } from '../../Markers/HotelMarkerByType' +import { PoiMarker } from '../../Markers/PoiMarker' -import styles from "./poiMapMarkers.module.css" +import styles from './poiMapMarkers.module.css' -import type { PointOfInterest } from "@scandic-hotels/trpc/types/hotel" -import type { MarkerInfo } from "@scandic-hotels/trpc/types/marker" +import type { PointOfInterest } from '@scandic-hotels/trpc/types/hotel' +import type { MarkerInfo } from '@scandic-hotels/trpc/types/marker' export type PoiMapMarkersProps = { activePoi?: string | null @@ -52,15 +52,15 @@ export default function PoiMapMarkers({ zIndex={activePoi === poi.name ? 2 : 0} onMouseEnter={() => onActivePoiChange?.(poi.name ?? null)} onMouseLeave={() => onActivePoiChange?.(null)} - onClick={() => toggleActivePoi(poi.name ?? "")} + onClick={() => toggleActivePoi(poi.name ?? '')} > @@ -73,7 +73,7 @@ export default function PoiMapMarkers({ {intl.formatMessage( { - defaultMessage: "{distanceInKm} km", + defaultMessage: '{distanceInKm} km', }, { distanceInKm: poi.distance, diff --git a/apps/scandic-web/components/Maps/InteractiveMap/PoiMapMarkers/poiMapMarkers.module.css b/packages/design-system/lib/components/Map/InteractiveMap/PoiMapMarkers/poiMapMarkers.module.css similarity index 100% rename from apps/scandic-web/components/Maps/InteractiveMap/PoiMapMarkers/poiMapMarkers.module.css rename to packages/design-system/lib/components/Map/InteractiveMap/PoiMapMarkers/poiMapMarkers.module.css diff --git a/packages/design-system/lib/components/Map/InteractiveMap/index.tsx b/packages/design-system/lib/components/Map/InteractiveMap/index.tsx new file mode 100644 index 000000000..00d4269ea --- /dev/null +++ b/packages/design-system/lib/components/Map/InteractiveMap/index.tsx @@ -0,0 +1,176 @@ +'use client' + +import { Map, type MapProps, useMap } from '@vis.gl/react-google-maps' +import { useEffect, useState } from 'react' +import { useIntl } from 'react-intl' + +import { IconButton } from '@scandic-hotels/design-system/IconButton' +import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon' + +import { + DEFAULT_ZOOM, + MAP_RESTRICTIONS, + MAX_ZOOM, + MIN_ZOOM, +} from '../mapConstants' + +import { useZoomControls } from './useZoomControls' + +import { HotelListingMapContent } from './HotelListingMapContent' +import PoiMapMarkers from './PoiMapMarkers' + +import styles from './interactiveMap.module.css' + +import type { PointOfInterest } from '@scandic-hotels/trpc/types/hotel' +import type { MarkerInfo } from '@scandic-hotels/trpc/types/marker' +import { HotelPin } from '../types' +import { Lang } from '@scandic-hotels/common/constants/language' + +export type InteractiveMapProps = { + lang: Lang + coordinates: { + lat: number + lng: number + } + activePoi?: PointOfInterest['name'] | null + hotelPins?: HotelPin[] + pointsOfInterest?: PointOfInterest[] + markerInfo?: MarkerInfo + mapId: string + closeButton: React.ReactNode + fitBounds?: boolean + hoveredHotelPin?: string | null + activeHotelPin?: string | null + + isUserLoggedIn: boolean + onTilesLoaded?: () => void + onActivePoiChange?: (poi: PointOfInterest['name'] | null) => void + + onClickHotel?: (hotelId: string) => void + + /** + * Called when a hotel pin is hovered. + * @param args when null, it means the hover has ended + * @returns + */ + onHoverHotelPin?: ( + args: { hotelName: string; hotelId: string } | null + ) => void + + /** + * Called when a hotel pin is activated. + * @param args when null, it means nothing is active + * @returns + */ + onSetActiveHotelPin?: ( + args: { hotelName: string; hotelId: string } | null + ) => void +} + +export function InteractiveMap({ + lang, + coordinates, + pointsOfInterest, + activePoi, + hotelPins, + mapId, + closeButton, + markerInfo, + fitBounds = true, + hoveredHotelPin, + activeHotelPin, + isUserLoggedIn, + onClickHotel, + onHoverHotelPin, + onSetActiveHotelPin, + onTilesLoaded, + onActivePoiChange, +}: InteractiveMapProps) { + const intl = useIntl() + const map = useMap() + const [hasInitializedBounds, setHasInitializedBounds] = useState(false) + const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = useZoomControls() + + const mapOptions: MapProps = { + defaultZoom: DEFAULT_ZOOM, + minZoom: MIN_ZOOM, + maxZoom: MAX_ZOOM, + defaultCenter: coordinates, + disableDefaultUI: true, + clickableIcons: false, + mapId, + gestureHandling: 'greedy', + restriction: MAP_RESTRICTIONS, + } + + useEffect(() => { + if (map && hotelPins?.length && !hasInitializedBounds) { + if (fitBounds) { + const bounds = new google.maps.LatLngBounds() + hotelPins.forEach((marker) => { + bounds.extend(marker.coordinates) + }) + map.fitBounds(bounds, 100) + } + setHasInitializedBounds(true) + } + }, [map, fitBounds, hotelPins, hasInitializedBounds]) + + return ( +
+ + {hotelPins && ( + + )} + {pointsOfInterest && markerInfo && ( + + )} + +
+ {closeButton} +
+ + + + + + + +
+
+
+ ) +} diff --git a/apps/scandic-web/components/Maps/InteractiveMap/interactiveMap.module.css b/packages/design-system/lib/components/Map/InteractiveMap/interactiveMap.module.css similarity index 99% rename from apps/scandic-web/components/Maps/InteractiveMap/interactiveMap.module.css rename to packages/design-system/lib/components/Map/InteractiveMap/interactiveMap.module.css index 3c4b9516b..7698a1e9e 100644 --- a/apps/scandic-web/components/Maps/InteractiveMap/interactiveMap.module.css +++ b/packages/design-system/lib/components/Map/InteractiveMap/interactiveMap.module.css @@ -21,7 +21,7 @@ } .mapContainer::after { - content: ""; + content: ''; position: absolute; top: 0; right: 0; diff --git a/apps/scandic-web/hooks/maps/useZoomControls.ts b/packages/design-system/lib/components/Map/InteractiveMap/useZoomControls.ts similarity index 76% rename from apps/scandic-web/hooks/maps/useZoomControls.ts rename to packages/design-system/lib/components/Map/InteractiveMap/useZoomControls.ts index d9608b9cc..642c62d15 100644 --- a/apps/scandic-web/hooks/maps/useZoomControls.ts +++ b/packages/design-system/lib/components/Map/InteractiveMap/useZoomControls.ts @@ -1,7 +1,6 @@ -import { useMap } from "@vis.gl/react-google-maps" -import { useEffect, useState } from "react" - -import { DEFAULT_ZOOM, MAX_ZOOM, MIN_ZOOM } from "@/constants/map" +import { useMap } from '@vis.gl/react-google-maps' +import { useEffect, useState } from 'react' +import { DEFAULT_ZOOM, MAX_ZOOM, MIN_ZOOM } from '../mapConstants' export function useZoomControls() { const map = useMap() @@ -29,7 +28,7 @@ export function useZoomControls() { } } - const listener = map.addListener("zoom_changed", handleZoomChanged) + const listener = map.addListener('zoom_changed', handleZoomChanged) return () => listener.remove() }, [map]) diff --git a/apps/scandic-web/components/Maps/Markers/DowntownCamper.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/DowntownCamper.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/DowntownCamper.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/DowntownCamper.tsx index 76e045c25..85e988b73 100644 --- a/apps/scandic-web/components/Maps/Markers/DowntownCamper.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/DowntownCamper.tsx @@ -1,4 +1,4 @@ -export default function DowntownCamperMarker({ +export function DowntownCamperMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/DowntownCamperSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/DowntownCamperSmall.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/DowntownCamperSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/DowntownCamperSmall.tsx index cb7989a9f..65fdf49b2 100644 --- a/apps/scandic-web/components/Maps/Markers/DowntownCamperSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/DowntownCamperSmall.tsx @@ -1,4 +1,4 @@ -export default function DowntownCamperSmallMarker({ +export function DowntownCamperSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/GrandHotel.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/GrandHotel.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/GrandHotel.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/GrandHotel.tsx index e3f7125ac..9706b10e2 100644 --- a/apps/scandic-web/components/Maps/Markers/GrandHotel.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/GrandHotel.tsx @@ -1,4 +1,4 @@ -export default function GrandHotelMarker({ +export function GrandHotelMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/GrandHotelSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/GrandHotelSmall.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/GrandHotelSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/GrandHotelSmall.tsx index 8da9c8c92..decd1ce1c 100644 --- a/apps/scandic-web/components/Maps/Markers/GrandHotelSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/GrandHotelSmall.tsx @@ -1,4 +1,4 @@ -export default function GrandHotelSmallMarker({ +export function GrandHotelSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/Haymarket.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Haymarket.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/Haymarket.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Haymarket.tsx index aaca7b723..862d6bb8c 100644 --- a/apps/scandic-web/components/Maps/Markers/Haymarket.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Haymarket.tsx @@ -1,4 +1,4 @@ -export default function HaymarketMarker({ +export function HaymarketMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/HaymarketSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HaymarketSmall.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/HaymarketSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HaymarketSmall.tsx index f15730e59..e54749ee4 100644 --- a/apps/scandic-web/components/Maps/Markers/HaymarketSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HaymarketSmall.tsx @@ -1,4 +1,4 @@ -export default function HaymarketSmallMarker({ +export function HaymarketSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/HotelNorge.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HotelNorge.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/HotelNorge.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HotelNorge.tsx index 1820bee12..5a12297a2 100644 --- a/apps/scandic-web/components/Maps/Markers/HotelNorge.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HotelNorge.tsx @@ -1,4 +1,4 @@ -export default function HotelNorgeMarker({ +export function HotelNorgeMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/HotelNorgeSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HotelNorgeSmall.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/HotelNorgeSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HotelNorgeSmall.tsx index 9ac8f719b..81addddb0 100644 --- a/apps/scandic-web/components/Maps/Markers/HotelNorgeSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/HotelNorgeSmall.tsx @@ -1,4 +1,4 @@ -export default function HotelNorgeSmallMarker({ +export function HotelNorgeSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/Marski.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Marski.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/Marski.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Marski.tsx index 0dd7b51a3..c0366dfa9 100644 --- a/apps/scandic-web/components/Maps/Markers/Marski.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Marski.tsx @@ -1,4 +1,4 @@ -export default function MarskiMarker({ +export function MarskiMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/MarskiSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/MarskiSmall.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/MarskiSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/MarskiSmall.tsx index c11160b86..670028448 100644 --- a/apps/scandic-web/components/Maps/Markers/MarskiSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/MarskiSmall.tsx @@ -1,4 +1,4 @@ -export default function MarskiSmallMarker({ +export function MarskiSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/Scandic.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Scandic.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/Scandic.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Scandic.tsx index aa44aecce..18ad3dc7e 100644 --- a/apps/scandic-web/components/Maps/Markers/Scandic.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/Scandic.tsx @@ -1,4 +1,4 @@ -export default function ScandicMarker({ +export function ScandicMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/ScandicGo.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicGo.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/ScandicGo.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicGo.tsx index 6ed53afa9..f1a6eb9ec 100644 --- a/apps/scandic-web/components/Maps/Markers/ScandicGo.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicGo.tsx @@ -1,4 +1,4 @@ -export default function ScandicGoMarker({ +export function ScandicGoMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/ScandicGoSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicGoSmall.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/ScandicGoSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicGoSmall.tsx index 9a9c59a11..b7ee95b62 100644 --- a/apps/scandic-web/components/Maps/Markers/ScandicGoSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicGoSmall.tsx @@ -1,4 +1,4 @@ -export default function ScandicGoSmallMarker({ +export function ScandicGoSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/ScandicSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicSmall.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/ScandicSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicSmall.tsx index 034013926..30fe6c260 100644 --- a/apps/scandic-web/components/Maps/Markers/ScandicSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/ScandicSmall.tsx @@ -1,4 +1,4 @@ -export default function ScandicSmallMarker({ +export function ScandicSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/TheDock.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/TheDock.tsx similarity index 99% rename from apps/scandic-web/components/Maps/Markers/TheDock.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/TheDock.tsx index 59c2d548f..7da7d44e5 100644 --- a/apps/scandic-web/components/Maps/Markers/TheDock.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/TheDock.tsx @@ -1,4 +1,4 @@ -export default function TheDockMarker({ +export function TheDockMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/TheDockSmall.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/TheDockSmall.tsx similarity index 98% rename from apps/scandic-web/components/Maps/Markers/TheDockSmall.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/TheDockSmall.tsx index 49f7056c8..9badd56bb 100644 --- a/apps/scandic-web/components/Maps/Markers/TheDockSmall.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/SignatureHotel/TheDockSmall.tsx @@ -1,4 +1,4 @@ -export default function TheDockSmallMarker({ +export function TheDockSmallMarker({ className, ...props }: React.SVGAttributes) { diff --git a/apps/scandic-web/components/Maps/Markers/HotelMarker/hotelMarker.module.css b/packages/design-system/lib/components/Map/Markers/HotelMarker/hotelMarker.module.css similarity index 100% rename from apps/scandic-web/components/Maps/Markers/HotelMarker/hotelMarker.module.css rename to packages/design-system/lib/components/Map/Markers/HotelMarker/hotelMarker.module.css diff --git a/apps/scandic-web/components/Maps/Markers/HotelMarker/index.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarker/index.tsx similarity index 96% rename from apps/scandic-web/components/Maps/Markers/HotelMarker/index.tsx rename to packages/design-system/lib/components/Map/Markers/HotelMarker/index.tsx index 896e2716d..8955da01b 100644 --- a/apps/scandic-web/components/Maps/Markers/HotelMarker/index.tsx +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/index.tsx @@ -1,11 +1,11 @@ -import { hotelMarkerVariants } from "./variants" +import { hotelMarkerVariants } from './variants' export default function HotelMarker({ className, color, ...props }: React.SVGAttributes & { - color?: "burgundy" | "white" + color?: 'burgundy' | 'white' }) { const classNames = hotelMarkerVariants({ color, className }) diff --git a/apps/scandic-web/components/Maps/Markers/HotelMarker/variants.ts b/packages/design-system/lib/components/Map/Markers/HotelMarker/variants.ts similarity index 61% rename from apps/scandic-web/components/Maps/Markers/HotelMarker/variants.ts rename to packages/design-system/lib/components/Map/Markers/HotelMarker/variants.ts index 298d0e063..8bf4a32a5 100644 --- a/apps/scandic-web/components/Maps/Markers/HotelMarker/variants.ts +++ b/packages/design-system/lib/components/Map/Markers/HotelMarker/variants.ts @@ -1,6 +1,6 @@ -import { cva } from "class-variance-authority" +import { cva } from 'class-variance-authority' -import styles from "./hotelMarker.module.css" +import styles from './hotelMarker.module.css' export const hotelMarkerVariants = cva(styles.icon, { variants: { @@ -10,6 +10,6 @@ export const hotelMarkerVariants = cva(styles.icon, { }, }, defaultVariants: { - color: "white", + color: 'white', }, }) diff --git a/packages/design-system/lib/components/Map/Markers/HotelMarkerByType.stories.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarkerByType.stories.tsx new file mode 100644 index 000000000..44d6ab436 --- /dev/null +++ b/packages/design-system/lib/components/Map/Markers/HotelMarkerByType.stories.tsx @@ -0,0 +1,166 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite' + +import { HotelMarkerByType } from './HotelMarkerByType' +import { SignatureHotelEnum } from '@scandic-hotels/common/constants/signatureHotels' +import { Typography } from 'lib/components/Typography' + +const meta: Meta = { + title: 'Components/Map/Hotel Marker By Type', + component: HotelMarkerByType, + argTypes: { + hotelType: { + control: 'select', + options: ['Regular', 'Signature', 'Scandic Go'], + description: 'Type of hotel', + table: { + type: { summary: "'Regular' | 'Signature' | 'Scandic Go'" }, + // defaultValue: { summary: 'Regular' }, + }, + mapping: { + Signature: 'signature', + 'Scandic Go': 'scandicgo', + Regular: 'regular', + }, + }, + hotelId: { + control: 'select', + description: 'ID of the hotel (e.g. "879" for Downtown Camper)', + options: ['Other', ...Object.keys(SignatureHotelEnum)], + mapping: { + Other: '', + ...SignatureHotelEnum, + }, + }, + size: { + control: 'select', + table: { + type: { summary: "'large' | 'small'" }, + }, + options: ['large', 'small'], + }, + }, +} + +export default meta + +type Story = StoryObj + +export const PrimaryDefault: Story = { + args: { + hotelId: 'Other', + hotelType: 'Regular', + size: 'large', + }, +} + +export const ScandicGo: Story = { + args: { + hotelId: 'Other', + hotelType: 'Scandic Go', + size: 'large', + }, + argTypes: { + hotelId: { + table: { + disable: true, + }, + }, + hotelType: { + table: { + disable: true, + }, + }, + }, +} + +export const Signature: Story = { + args: { + hotelId: 'DowntownCamper', + hotelType: 'Signature', + size: 'large', + }, + argTypes: { + hotelType: { + table: { + disable: true, + }, + }, + hotelId: { + control: 'select', + options: ['Other', ...Object.keys(SignatureHotelEnum)], + mapping: { + Other: '', + ...SignatureHotelEnum, + }, + }, + }, +} + +const exampleMarkers = [ + { + name: 'Default', + hotelId: 'Other', + hotelType: 'Regular', + }, + { + name: 'Scandic Go', + hotelId: 'Other', + hotelType: 'scandicgo', + }, + ...Object.entries(SignatureHotelEnum).map( + ([hotelName, hotelId]) => + ({ + name: hotelName, + hotelId, + hotelType: 'signature', + }) as const + ), +] as const + +export const Examples: Story = { + args: { + size: 'large', + }, + argTypes: { + hotelType: { + table: { + disable: true, + }, + }, + hotelId: { + table: { + disable: true, + }, + }, + }, + render: (args) => ( +
+ {exampleMarkers.map((exampleArgs, ix) => ( +
+ + +

{exampleArgs.name}

+
+
+ ))} +
+ ), +} diff --git a/packages/design-system/lib/components/Map/Markers/HotelMarkerByType.tsx b/packages/design-system/lib/components/Map/Markers/HotelMarkerByType.tsx new file mode 100644 index 000000000..6eeedc198 --- /dev/null +++ b/packages/design-system/lib/components/Map/Markers/HotelMarkerByType.tsx @@ -0,0 +1,98 @@ +import { HotelTypeEnum } from '@scandic-hotels/trpc/enums/hotelType' + +import { DowntownCamperMarker } from './HotelMarker/SignatureHotel/DowntownCamper' +import { DowntownCamperSmallMarker } from './HotelMarker/SignatureHotel/DowntownCamperSmall' +import { GrandHotelMarker } from './HotelMarker/SignatureHotel/GrandHotel' +import { GrandHotelSmallMarker } from './HotelMarker/SignatureHotel/GrandHotelSmall' +import { HaymarketMarker } from './HotelMarker/SignatureHotel/Haymarket' +import { HaymarketSmallMarker } from './HotelMarker/SignatureHotel/HaymarketSmall' +import { HotelNorgeMarker } from './HotelMarker/SignatureHotel/HotelNorge' +import { HotelNorgeSmallMarker } from './HotelMarker/SignatureHotel/HotelNorgeSmall' +import { MarskiMarker } from './HotelMarker/SignatureHotel/Marski' +import { MarskiSmallMarker } from './HotelMarker/SignatureHotel/MarskiSmall' +import { ScandicMarker } from './HotelMarker/SignatureHotel/Scandic' +import { ScandicGoMarker } from './HotelMarker/SignatureHotel/ScandicGo' +import { ScandicGoSmallMarker } from './HotelMarker/SignatureHotel/ScandicGoSmall' +import { ScandicSmallMarker } from './HotelMarker/SignatureHotel/ScandicSmall' +import { TheDockMarker } from './HotelMarker/SignatureHotel/TheDock' +import { TheDockSmallMarker } from './HotelMarker/SignatureHotel/TheDockSmall' + +import type { MarkerInfo } from '@scandic-hotels/trpc/types/marker' +import { SignatureHotelEnum } from '@scandic-hotels/common/constants/signatureHotels' + +export interface HotelMarkerByTypeProps + extends MarkerInfo, + React.SVGAttributes { + size?: 'large' | 'small' +} +type MarkerComponent = React.ComponentType< + React.SVGAttributes +> + +export function HotelMarkerByType({ + hotelId, + hotelType, + size = 'large', + ...props +}: HotelMarkerByTypeProps) { + const typeEntry = byHotelType[hotelType as keyof typeof byHotelType] + if (typeEntry) { + const Cmp = typeEntry[size] + return + } + + const sigatureHotelEntry = + bySignatureHotel[hotelId as keyof typeof bySignatureHotel] + if (sigatureHotelEntry) { + const Cmp = sigatureHotelEntry[size] + return + } + + const Cmp = defaultMarkers[size] + return +} + +const defaultMarkers: Record<'large' | 'small', MarkerComponent> = { + large: ScandicMarker, + small: ScandicSmallMarker, +} + +const byHotelType: Record< + Exclude, + Record<'large' | 'small', MarkerComponent> +> = { + [HotelTypeEnum.ScandicGo]: { + large: ScandicGoMarker, + small: ScandicGoSmallMarker, + }, +} + +const bySignatureHotel: Record< + SignatureHotelEnum, + Record<'large' | 'small', MarkerComponent> +> = { + [SignatureHotelEnum.Haymarket]: { + large: HaymarketMarker, + small: HaymarketSmallMarker, + }, + [SignatureHotelEnum.HotelNorge]: { + large: HotelNorgeMarker, + small: HotelNorgeSmallMarker, + }, + [SignatureHotelEnum.DowntownCamper]: { + large: DowntownCamperMarker, + small: DowntownCamperSmallMarker, + }, + [SignatureHotelEnum.GrandHotelOslo]: { + large: GrandHotelMarker, + small: GrandHotelSmallMarker, + }, + [SignatureHotelEnum.Marski]: { + large: MarskiMarker, + small: MarskiSmallMarker, + }, + [SignatureHotelEnum.TheDock]: { + large: TheDockMarker, + small: TheDockSmallMarker, + }, +} diff --git a/packages/design-system/lib/components/Map/Markers/PoiMarker/index.tsx b/packages/design-system/lib/components/Map/Markers/PoiMarker/index.tsx new file mode 100644 index 000000000..f0d38aed4 --- /dev/null +++ b/packages/design-system/lib/components/Map/Markers/PoiMarker/index.tsx @@ -0,0 +1,41 @@ +import { IconByIconName } from '@scandic-hotels/design-system/Icons/IconByIconName' + +import { getIconByPoiGroupAndCategory } from '../utils' +import { poiVariants } from './variants' + +import { VariantProps } from 'class-variance-authority' + +export type PointOfInterestGroup = + | 'Public transport' + | 'Attractions' + | 'Business' + | 'Location' + | 'Parking' + | 'Shopping & Dining' + +export interface PoiMarkerProps extends VariantProps { + group: PointOfInterestGroup + categoryName?: string + className?: string +} + +export function PoiMarker({ + group, + categoryName, + skipBackground, + size = 'small', + className = '', +}: PoiMarkerProps) { + const iconName = getIconByPoiGroupAndCategory(group, categoryName) + const classNames = poiVariants({ group, skipBackground, size, className }) + + return iconName ? ( + + + + ) : null +} diff --git a/apps/scandic-web/components/Maps/Markers/Poi/poi.module.css b/packages/design-system/lib/components/Map/Markers/PoiMarker/poi.module.css similarity index 100% rename from apps/scandic-web/components/Maps/Markers/Poi/poi.module.css rename to packages/design-system/lib/components/Map/Markers/PoiMarker/poi.module.css diff --git a/packages/design-system/lib/components/Map/Markers/PoiMarker/variants.ts b/packages/design-system/lib/components/Map/Markers/PoiMarker/variants.ts new file mode 100644 index 000000000..afe0b854d --- /dev/null +++ b/packages/design-system/lib/components/Map/Markers/PoiMarker/variants.ts @@ -0,0 +1,30 @@ +import { cva } from 'class-variance-authority' + +import styles from './poi.module.css' +import { PointOfInterestGroup } from '.' + +export const poiVariants = cva(styles.icon, { + variants: { + group: { + ['Attractions']: styles.attractions, + ['Business']: styles.business, + ['Location']: styles.location, + ['Parking']: styles.parking, + ['Public transport']: styles.publicTransport, + ['Shopping & Dining']: styles.shoppingDining, + } satisfies Record, + skipBackground: { + true: styles.transparent, + false: '', + }, + size: { + small: styles.small, + medium: styles.small, + large: styles.large, + }, + }, + defaultVariants: { + skipBackground: false, + size: 'small', + }, +}) diff --git a/packages/design-system/lib/components/Map/Markers/utils.ts b/packages/design-system/lib/components/Map/Markers/utils.ts new file mode 100644 index 000000000..533fcabf0 --- /dev/null +++ b/packages/design-system/lib/components/Map/Markers/utils.ts @@ -0,0 +1,23 @@ +import { IconName } from '@scandic-hotels/design-system/Icons/iconName' +import { PointOfInterestGroup } from './PoiMarker' + +export function getIconByPoiGroupAndCategory( + group: PointOfInterestGroup, + category?: string +) { + switch (group) { + case 'Public transport': + return category === 'Airport' ? IconName.Airplane : IconName.Train + case 'Attractions': + return category === 'Museum' ? IconName.Museum : IconName.Camera + case 'Business': + return IconName.Business + case 'Parking': + return IconName.Parking + case 'Shopping & Dining': + return category === 'Restaurant' ? IconName.Restaurant : IconName.Shopping + case 'Location': + default: + return IconName.Location + } +} diff --git a/apps/scandic-web/constants/map.ts b/packages/design-system/lib/components/Map/mapConstants.ts similarity index 100% rename from apps/scandic-web/constants/map.ts rename to packages/design-system/lib/components/Map/mapConstants.ts diff --git a/packages/design-system/lib/components/Map/types.ts b/packages/design-system/lib/components/Map/types.ts new file mode 100644 index 000000000..f3f3a4548 --- /dev/null +++ b/packages/design-system/lib/components/Map/types.ts @@ -0,0 +1,42 @@ +import { CurrencyEnum } from '@scandic-hotels/common/constants/currency' +import { FacilityEnum } from '@scandic-hotels/common/constants/facilities' + +export type HotelPin = { + bookingCode?: string | null + name: string + coordinates: { + lat: number + lng: number + } + chequePrice: { + numberOfCheques: number + additionalPricePerStay: number + currency: CurrencyEnum | undefined | null + } | null + publicPrice: number | null + memberPrice: number | null + redemptionPrice: number | null + voucherPrice: number | null + rateType: string | null + currency: string + image: { + url: string + alt: string + } + amenities: { + id: FacilityEnum + slug: string + filter: string + icon: string + name: string + public: boolean + sortOrder: number + }[] + + ratings?: { + tripAdvisor?: number | null + } + operaId: string + facilityIds: number[] + hasEnoughPoints: boolean +} diff --git a/packages/design-system/lib/components/TripAdvisorChip/TripdAdvisorChip.stories.tsx b/packages/design-system/lib/components/TripAdvisorChip/TripdAdvisorChip.stories.tsx new file mode 100644 index 000000000..2570a8e82 --- /dev/null +++ b/packages/design-system/lib/components/TripAdvisorChip/TripdAdvisorChip.stories.tsx @@ -0,0 +1,28 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite' + +import { TripAdvisorChip } from './index' + +const meta: Meta = { + title: 'Components/TripAdvisorChip', + component: TripAdvisorChip, + argTypes: { + rating: { + control: { + type: 'number', + min: 0, + max: 5, + step: 0.1, + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const PrimaryDefault: Story = { + args: { + rating: 4.5, + }, +} diff --git a/packages/booking-flow/lib/components/TripAdvisorChip/index.tsx b/packages/design-system/lib/components/TripAdvisorChip/index.tsx similarity index 59% rename from packages/booking-flow/lib/components/TripAdvisorChip/index.tsx rename to packages/design-system/lib/components/TripAdvisorChip/index.tsx index 321392453..2ee64a94e 100644 --- a/packages/booking-flow/lib/components/TripAdvisorChip/index.tsx +++ b/packages/design-system/lib/components/TripAdvisorChip/index.tsx @@ -1,13 +1,13 @@ -import Caption from "@scandic-hotels/design-system/Caption" -import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon" +import Caption from '@scandic-hotels/design-system/Caption' +import TripadvisorIcon from '@scandic-hotels/design-system/Icons/TripadvisorIcon' -import styles from "./tripAdvisorChip.module.css" +import styles from './tripAdvisorChip.module.css' type TripAdvisorProps = { rating: number } -export default function TripAdvisorChip({ rating }: TripAdvisorProps) { +export function TripAdvisorChip({ rating }: TripAdvisorProps) { return ( // Wrapping the chip in a transparent container with some padding to increase the touch target
diff --git a/packages/booking-flow/lib/components/TripAdvisorChip/tripAdvisorChip.module.css b/packages/design-system/lib/components/TripAdvisorChip/tripAdvisorChip.module.css similarity index 100% rename from packages/booking-flow/lib/components/TripAdvisorChip/tripAdvisorChip.module.css rename to packages/design-system/lib/components/TripAdvisorChip/tripAdvisorChip.module.css diff --git a/apps/partner-sas/public/_static/css/design-system-new-deprecated.css b/packages/design-system/lib/design-system-new-deprecated.css similarity index 88% rename from apps/partner-sas/public/_static/css/design-system-new-deprecated.css rename to packages/design-system/lib/design-system-new-deprecated.css index 8d98f0d51..8b1cad41e 100644 --- a/apps/partner-sas/public/_static/css/design-system-new-deprecated.css +++ b/packages/design-system/lib/design-system-new-deprecated.css @@ -1,218 +1,218 @@ :root { --typography-Body-Bold-Desktop-fontSize: 16px; - --typography-Body-Bold-fontFamily: "fira sans"; + --typography-Body-Bold-fontFamily: 'fira sans'; --typography-Body-Bold-fontSize: 16px; - --typography-Body-Bold-fontWeight: "medium"; + --typography-Body-Bold-fontWeight: 'medium'; --typography-Body-Bold-letterSpacing: 1.2000000476837158%; --typography-Body-Bold-lineHeight: 150%; --typography-Body-Bold-Mobile-fontSize: 16px; --typography-Body-Bold-Tablet-estimate-fontSize: 16px; - --typography-Body-Bold-textCase: "original"; - --typography-Body-Bold-textDecoration: "none"; + --typography-Body-Bold-textCase: 'original'; + --typography-Body-Bold-textDecoration: 'none'; --typography-Body-Inline-Desktop-fontSize: 16px; - --typography-Body-Inline-fontFamily: "fira sans"; + --typography-Body-Inline-fontFamily: 'fira sans'; --typography-Body-Inline-fontSize: 16px; - --typography-Body-Inline-fontWeight: "regular"; + --typography-Body-Inline-fontWeight: 'regular'; --typography-Body-Inline-letterSpacing: 1.2000000476837158%; --typography-Body-Inline-lineHeight: 150%; --typography-Body-Inline-Mobile-fontSize: 16px; --typography-Body-Inline-Tablet-estimate-fontSize: 16px; - --typography-Body-Inline-textCase: "original"; - --typography-Body-Inline-textDecoration: "underline"; + --typography-Body-Inline-textCase: 'original'; + --typography-Body-Inline-textDecoration: 'underline'; --typography-Body-Link-Desktop-fontSize: 16px; --typography-Body-Link-Mobile-fontSize: 16px; --typography-Body-Link-Tablet-estimate-fontSize: 16px; --typography-Body-Regular-Desktop-fontSize: 16px; - --typography-Body-Regular-fontFamily: "fira sans"; + --typography-Body-Regular-fontFamily: 'fira sans'; --typography-Body-Regular-fontSize: 16px; - --typography-Body-Regular-fontWeight: "regular"; + --typography-Body-Regular-fontWeight: 'regular'; --typography-Body-Regular-letterSpacing: 1.2000000476837158%; --typography-Body-Regular-lineHeight: 150%; --typography-Body-Regular-Mobile-fontSize: 16px; --typography-Body-Regular-Tablet-estimate-fontSize: 16px; - --typography-Body-Regular-textCase: "original"; - --typography-Body-Regular-textDecoration: "none"; - --typography-Body-Underline-fontFamily: "fira sans"; + --typography-Body-Regular-textCase: 'original'; + --typography-Body-Regular-textDecoration: 'none'; + --typography-Body-Underline-fontFamily: 'fira sans'; --typography-Body-Underline-fontSize: 16px; - --typography-Body-Underline-fontWeight: "medium"; + --typography-Body-Underline-fontWeight: 'medium'; --typography-Body-Underline-letterSpacing: 1.2000000476837158%; --typography-Body-Underline-lineHeight: 150%; - --typography-Body-Underline-textCase: "original"; - --typography-Body-Underline-textDecoration: "underline"; + --typography-Body-Underline-textCase: 'original'; + --typography-Body-Underline-textDecoration: 'underline'; --typography-Caption-Bold-Desktop-fontSize: 14px; - --typography-Caption-Bold-fontFamily: "fira sans"; + --typography-Caption-Bold-fontFamily: 'fira sans'; --typography-Caption-Bold-fontSize: 14px; - --typography-Caption-Bold-fontWeight: "medium"; + --typography-Caption-Bold-fontWeight: 'medium'; --typography-Caption-Bold-letterSpacing: 1.399999976158142%; --typography-Caption-Bold-lineHeight: 139.9999976158142%; --typography-Caption-Bold-Mobile-fontSize: 14px; --typography-Caption-Bold-Tablet-estimate-fontSize: 14px; - --typography-Caption-Bold-textCase: "original"; - --typography-Caption-Bold-textDecoration: "none"; + --typography-Caption-Bold-textCase: 'original'; + --typography-Caption-Bold-textDecoration: 'none'; --typography-Caption-Inline-Desktop-fontSize: 14px; - --typography-Caption-Inline-fontFamily: "fira sans"; + --typography-Caption-Inline-fontFamily: 'fira sans'; --typography-Caption-Inline-fontSize: 14px; - --typography-Caption-Inline-fontWeight: "regular"; + --typography-Caption-Inline-fontWeight: 'regular'; --typography-Caption-Inline-letterSpacing: 1.399999976158142%; --typography-Caption-Inline-lineHeight: 139.9999976158142%; --typography-Caption-Inline-Mobile-fontSize: 14px; --typography-Caption-Inline-Tablet-estimate-fontSize: 14px; - --typography-Caption-Inline-textCase: "original"; - --typography-Caption-Inline-textDecoration: "underline"; - --typography-Caption-Labels-fontFamily: "brandon text"; + --typography-Caption-Inline-textCase: 'original'; + --typography-Caption-Inline-textDecoration: 'underline'; + --typography-Caption-Labels-fontFamily: 'brandon text'; --typography-Caption-Labels-fontSize: 14px; - --typography-Caption-Labels-fontWeight: "bold"; + --typography-Caption-Labels-fontWeight: 'bold'; --typography-Caption-Labels-letterSpacing: 1.399999976158142%; --typography-Caption-Labels-lineHeight: 150%; - --typography-Caption-Labels-textCase: "upper"; - --typography-Caption-Labels-textDecoration: "none"; + --typography-Caption-Labels-textCase: 'upper'; + --typography-Caption-Labels-textDecoration: 'none'; --typography-Caption-Link-Desktop-fontSize: 14px; --typography-Caption-Link-Mobile-fontSize: 14px; --typography-Caption-Link-Tablet-estimate-fontSize: 14px; --typography-Caption-Regular-Desktop-fontSize: 14px; - --typography-Caption-Regular-fontFamily: "fira sans"; + --typography-Caption-Regular-fontFamily: 'fira sans'; --typography-Caption-Regular-fontSize: 14px; - --typography-Caption-Regular-fontWeight: "regular"; + --typography-Caption-Regular-fontWeight: 'regular'; --typography-Caption-Regular-letterSpacing: 1.399999976158142%; --typography-Caption-Regular-lineHeight: 139.9999976158142%; --typography-Caption-Regular-Mobile-fontSize: 14px; --typography-Caption-Regular-Tablet-estimate-fontSize: 14px; - --typography-Caption-Regular-textCase: "original"; - --typography-Caption-Regular-textDecoration: "none"; - --typography-Caption-Underline-fontFamily: "fira sans"; + --typography-Caption-Regular-textCase: 'original'; + --typography-Caption-Regular-textDecoration: 'none'; + --typography-Caption-Underline-fontFamily: 'fira sans'; --typography-Caption-Underline-fontSize: 14px; - --typography-Caption-Underline-fontWeight: "medium"; + --typography-Caption-Underline-fontWeight: 'medium'; --typography-Caption-Underline-letterSpacing: 1.399999976158142%; --typography-Caption-Underline-lineHeight: 139.9999976158142%; - --typography-Caption-Underline-textCase: "original"; - --typography-Caption-Underline-textDecoration: "underline"; + --typography-Caption-Underline-textCase: 'original'; + --typography-Caption-Underline-textDecoration: 'underline'; --typography-Foot-note-Bold-Desktop-fontSize: 12px; --typography-Foot-note-Bold-Mobile-fontSize: 12px; --typography-Foot-note-Bold-Tablet-estimate-fontSize: 12px; --typography-Foot-note-Regular-Desktop-fontSize: 12px; --typography-Foot-note-Regular-Mobile-fontSize: 12px; --typography-Foot-note-Regular-Tablet-estimate-fontSize: 12px; - --typography-Footnote-Bold-fontFamily: "fira sans"; + --typography-Footnote-Bold-fontFamily: 'fira sans'; --typography-Footnote-Bold-fontSize: 12px; - --typography-Footnote-Bold-fontWeight: "medium"; + --typography-Footnote-Bold-fontWeight: 'medium'; --typography-Footnote-Bold-letterSpacing: 1.399999976158142%; --typography-Footnote-Bold-lineHeight: 150%; - --typography-Footnote-Bold-textCase: "original"; - --typography-Footnote-Bold-textDecoration: "none"; - --typography-Footnote-Labels-fontFamily: "brandon text"; + --typography-Footnote-Bold-textCase: 'original'; + --typography-Footnote-Bold-textDecoration: 'none'; + --typography-Footnote-Labels-fontFamily: 'brandon text'; --typography-Footnote-Labels-fontSize: 12px; - --typography-Footnote-Labels-fontWeight: "bold"; + --typography-Footnote-Labels-fontWeight: 'bold'; --typography-Footnote-Labels-letterSpacing: 1.399999976158142%; --typography-Footnote-Labels-lineHeight: 150%; - --typography-Footnote-Labels-textCase: "upper"; - --typography-Footnote-Labels-textDecoration: "none"; - --typography-Footnote-Regular-fontFamily: "fira sans"; + --typography-Footnote-Labels-textCase: 'upper'; + --typography-Footnote-Labels-textDecoration: 'none'; + --typography-Footnote-Regular-fontFamily: 'fira sans'; --typography-Footnote-Regular-fontSize: 12px; - --typography-Footnote-Regular-fontWeight: "regular"; + --typography-Footnote-Regular-fontWeight: 'regular'; --typography-Footnote-Regular-letterSpacing: 1.399999976158142%; --typography-Footnote-Regular-lineHeight: 150%; - --typography-Footnote-Regular-textCase: "original"; - --typography-Footnote-Regular-textDecoration: "none"; + --typography-Footnote-Regular-textCase: 'original'; + --typography-Footnote-Regular-textDecoration: 'none'; --typography-Preamble-Desktop-fontSize: 20px; - --typography-Preamble-fontFamily: "fira sans"; + --typography-Preamble-fontFamily: 'fira sans'; --typography-Preamble-fontSize: 20px; - --typography-Preamble-fontWeight: "regular"; + --typography-Preamble-fontWeight: 'regular'; --typography-Preamble-letterSpacing: 1%; --typography-Preamble-lineHeight: 139.9999976158142%; --typography-Preamble-Mobile-fontSize: 18px; --typography-Preamble-Tablet-estimate-fontSize: 19px; - --typography-Preamble-textCase: "original"; - --typography-Preamble-textDecoration: "none"; + --typography-Preamble-textCase: 'original'; + --typography-Preamble-textDecoration: 'none'; --typography-Script-1-Desktop-fontSize: 32px; - --typography-Script-1-fontFamily: "biro script plus"; + --typography-Script-1-fontFamily: 'biro script plus'; --typography-Script-1-fontSize: 32px; - --typography-Script-1-fontWeight: "regular"; + --typography-Script-1-fontWeight: 'regular'; --typography-Script-1-letterSpacing: 2%; --typography-Script-1-lineHeight: 110.00000238418579%; --typography-Script-1-Mobile-fontSize: 24px; --typography-Script-1-Tablet-estimate-fontSize: 29px; - --typography-Script-1-textCase: "original"; - --typography-Script-1-textDecoration: "none"; + --typography-Script-1-textCase: 'original'; + --typography-Script-1-textDecoration: 'none'; --typography-Script-2-Desktop-fontSize: 24px; - --typography-Script-2-fontFamily: "biro script plus"; + --typography-Script-2-fontFamily: 'biro script plus'; --typography-Script-2-fontSize: 24px; - --typography-Script-2-fontWeight: "regular"; + --typography-Script-2-fontWeight: 'regular'; --typography-Script-2-letterSpacing: 2%; --typography-Script-2-lineHeight: 110.00000238418579%; --typography-Script-2-Mobile-fontSize: 20px; --typography-Script-2-Tablet-estimate-fontSize: 22px; - --typography-Script-2-textCase: "original"; - --typography-Script-2-textDecoration: "none"; + --typography-Script-2-textCase: 'original'; + --typography-Script-2-textDecoration: 'none'; --typography-Subtitle-1-Desktop-fontSize: 24px; - --typography-Subtitle-1-fontFamily: "fira sans"; + --typography-Subtitle-1-fontFamily: 'fira sans'; --typography-Subtitle-1-fontSize: 24px; - --typography-Subtitle-1-fontWeight: "medium"; + --typography-Subtitle-1-fontWeight: 'medium'; --typography-Subtitle-1-letterSpacing: 1%; --typography-Subtitle-1-lineHeight: 120.00000476837158%; --typography-Subtitle-1-Mobile-fontSize: 20px; --typography-Subtitle-1-Tablet-estimate-fontSize: 22px; - --typography-Subtitle-1-textCase: "original"; - --typography-Subtitle-1-textDecoration: "none"; + --typography-Subtitle-1-textCase: 'original'; + --typography-Subtitle-1-textDecoration: 'none'; --typography-Subtitle-2-Desktop-fontSize: 20px; - --typography-Subtitle-2-fontFamily: "fira sans"; + --typography-Subtitle-2-fontFamily: 'fira sans'; --typography-Subtitle-2-fontSize: 20px; - --typography-Subtitle-2-fontWeight: "medium"; + --typography-Subtitle-2-fontWeight: 'medium'; --typography-Subtitle-2-letterSpacing: 1%; --typography-Subtitle-2-lineHeight: 120.00000476837158%; --typography-Subtitle-2-Mobile-fontSize: 18px; --typography-Subtitle-2-Tablet-estimate-fontSize: 19px; - --typography-Subtitle-2-textCase: "original"; - --typography-Subtitle-2-textDecoration: "none"; + --typography-Subtitle-2-textCase: 'original'; + --typography-Subtitle-2-textDecoration: 'none'; --typography-Title-1-Desktop-fontSize: 64px; - --typography-Title-1-fontFamily: "brandon text"; + --typography-Title-1-fontFamily: 'brandon text'; --typography-Title-1-fontSize: 64px; - --typography-Title-1-fontWeight: "black"; + --typography-Title-1-fontWeight: 'black'; --typography-Title-1-letterSpacing: 0.25%; --typography-Title-1-lineHeight: 110.00000238418579%; --typography-Title-1-Mobile-fontSize: 48px; --typography-Title-1-Tablet-estimate-fontSize: 60px; - --typography-Title-1-textCase: "upper"; - --typography-Title-1-textDecoration: "none"; + --typography-Title-1-textCase: 'upper'; + --typography-Title-1-textDecoration: 'none'; --typography-Title-2-Desktop-fontSize: 48px; - --typography-Title-2-fontFamily: "brandon text"; + --typography-Title-2-fontFamily: 'brandon text'; --typography-Title-2-fontSize: 48px; - --typography-Title-2-fontWeight: "black"; + --typography-Title-2-fontWeight: 'black'; --typography-Title-2-letterSpacing: 0.25%; --typography-Title-2-lineHeight: 110.00000238418579%; --typography-Title-2-Mobile-fontSize: 36px; --typography-Title-2-Tablet-estimate-fontSize: 44px; - --typography-Title-2-textCase: "upper"; - --typography-Title-2-textDecoration: "none"; + --typography-Title-2-textCase: 'upper'; + --typography-Title-2-textDecoration: 'none'; --typography-Title-3-Desktop-fontSize: 36px; - --typography-Title-3-fontFamily: "brandon text"; + --typography-Title-3-fontFamily: 'brandon text'; --typography-Title-3-fontSize: 36px; - --typography-Title-3-fontWeight: "black"; + --typography-Title-3-fontWeight: 'black'; --typography-Title-3-letterSpacing: 0.25%; --typography-Title-3-lineHeight: 110.00000238418579%; --typography-Title-3-Mobile-fontSize: 30px; --typography-Title-3-Tablet-estimate-fontSize: 34px; - --typography-Title-3-textCase: "upper"; - --typography-Title-3-textDecoration: "none"; + --typography-Title-3-textCase: 'upper'; + --typography-Title-3-textDecoration: 'none'; --typography-Title-4-Desktop-fontSize: 28px; - --typography-Title-4-fontFamily: "brandon text"; + --typography-Title-4-fontFamily: 'brandon text'; --typography-Title-4-fontSize: 28px; - --typography-Title-4-fontWeight: "bold"; + --typography-Title-4-fontWeight: 'bold'; --typography-Title-4-letterSpacing: 0.25%; --typography-Title-4-lineHeight: 110.00000238418579%; --typography-Title-4-Mobile-fontSize: 24px; --typography-Title-4-Tablet-estimate-fontSize: 26px; - --typography-Title-4-textCase: "original"; - --typography-Title-4-textDecoration: "none"; + --typography-Title-4-textCase: 'original'; + --typography-Title-4-textDecoration: 'none'; --typography-Title-5-Desktop-fontSize: 24px; - --typography-Title-5-fontFamily: "brandon text"; + --typography-Title-5-fontFamily: 'brandon text'; --typography-Title-5-fontSize: 24px; - --typography-Title-5-fontWeight: "black"; + --typography-Title-5-fontWeight: 'black'; --typography-Title-5-letterSpacing: 0.25%; --typography-Title-5-lineHeight: 110.00000238418579%; --typography-Title-5-Mobile-fontSize: 20px; --typography-Title-5-Tablet-estimate-fontSize: 21px; - --typography-Title-5-textCase: "upper"; - --typography-Title-5-textDecoration: "none"; + --typography-Title-5-textCase: 'upper'; + --typography-Title-5-textDecoration: 'none'; } :root { --Base-Background-Primary-Elevated: var(--Scandic-Beige-00); diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 3cb23fed1..a4da7d289 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -8,6 +8,7 @@ "./Accordion/AccordionItem": "./lib/components/Accordion/AccordionItem/index.tsx", "./BackToTopButton": "./lib/components/BackToTopButton/index.tsx", "./Body": "./lib/components/Body/index.tsx", + "./BookingCodeChip": "./lib/components/BookingCodeChip/index.tsx", "./Button": "./lib/components/Button/index.tsx", "./ButtonLink": "./lib/components/ButtonLink/index.tsx", "./CampaignRateCard": "./lib/components/RateCard/Campaign/index.tsx", @@ -20,6 +21,7 @@ "./CodeRateCard": "./lib/components/RateCard/Code/index.tsx", "./DeprecatedSelect": "./lib/components/DeprecatedSelect/index.tsx", "./Divider": "./lib/components/Divider/index.tsx", + "./FacilityToIcon": "./lib/components/FacilityToIcon/index.tsx", "./Footnote": "./lib/components/Footnote/index.tsx", "./Form/Checkbox": "./lib/components/Form/Checkbox/index.tsx", "./Form/Country": "./lib/components/Form/Country/index.tsx", @@ -27,6 +29,11 @@ "./Form/ErrorMessage": "./lib/components/Form/ErrorMessage/index.tsx", "./Form/Phone": "./lib/components/Form/Phone/index.tsx", "./Form/RadioCard": "./lib/components/Form/RadioCard/index.tsx", + "./HotelCard": "./lib/components/HotelCard/index.tsx", + "./HotelCard/HotelCardDialogImage": "./lib/components/HotelCard/HotelCardDialogImage/index.tsx", + "./HotelCard/HotelPointsRow": "./lib/components/HotelCard/HotelPointsRow/index.tsx", + "./HotelCard/NoPriceAvailableCard": "./lib/components/HotelCard/NoPriceAvailableCard/index.tsx", + "./HotelCard/HotelCardSkeleton": "./lib/components/HotelCard/HotelCardSkeleton.tsx", "./IconButton": "./lib/components/IconButton/index.tsx", "./IconChip": "./lib/components/IconChip/index.tsx", "./Icons": "./lib/components/Icons/index.tsx", @@ -117,10 +124,13 @@ "./ImageFallback": "./lib/components/ImageFallback/index.tsx", "./ImageGallery": "./lib/components/ImageGallery/index.tsx", "./Input": "./lib/components/Input/index.tsx", - "./JsonToHtml": "./lib/components/JsonToHtml/JsonToHtml.tsx", "./Label": "./lib/components/Label/index.tsx", "./Lightbox": "./lib/components/Lightbox/index.tsx", "./Link": "./lib/components/Link/index.tsx", + "./Map/InteractiveMap": "./lib/components/Map/InteractiveMap/index.tsx", + "./Map/mapConstants": "./lib/components/Map/mapConstants.ts", + "./Map/Markers/HotelMarkerByType": "./lib/components/Map/Markers/HotelMarkerByType.tsx", + "./Map/Markers/PoiMarker": "./lib/components/Map/Markers/PoiMarker/index.tsx", "./Modal": "./lib/components/Modal/index.tsx", "./Modal/ModalContentWithActions": "./lib/components/Modal/ModalContentWithActions/index.tsx", "./NoRateAvailableCard": "./lib/components/RateCard/NoRateAvailable/index.tsx", @@ -140,7 +150,10 @@ "./Table": "./lib/components/Table/index.tsx", "./Title": "./lib/components/Title/index.tsx", "./Tooltip": "./lib/components/Tooltip/index.tsx", + "./TripAdvisorChip": "./lib/components/TripAdvisorChip/index.tsx", "./Typography": "./lib/components/Typography/index.tsx", + "./JsonToHtml": "./lib/components/JsonToHtml/JsonToHtml.tsx", + "./design-system-new-deprecated.css": "./lib/design-system-new-deprecated.css", "./style.css": "./lib/style.css", "./base.css": "./lib/base.css", "./globals.css": "./lib/globals.css", @@ -183,6 +196,7 @@ "peerDependencies": { "@internationalized/date": "^3.8.0", "@radix-ui/react-slot": "^1.2.2", + "@vis.gl/react-google-maps": "^1.5.2", "next": "^15", "react": "^19.1.0", "react-aria-components": "^1.8.0", @@ -209,6 +223,7 @@ "@typescript-eslint/parser": "^8.32.0", "@vitejs/plugin-react": "^5.0.0", "@vitest/browser": "^3.2.4", + "babel-plugin-formatjs": "^10.5.10", "class-variance-authority": "^0.7.1", "colord": "^2.9.3", "copy-to-clipboard": "^3.3.3", @@ -231,6 +246,7 @@ "rollup": "^4.40.2", "rollup-preserve-directives": "^1.1.3", "storybook": "^9.1.2", + "storybook-react-intl": "^4.0.7", "typescript": "^5.8.3", "vite": "^6.3.5", "vite-plugin-dts": "^4.5.3", diff --git a/packages/design-system/tsconfig.json b/packages/design-system/tsconfig.json index 19cd1da41..46b94c4d8 100644 --- a/packages/design-system/tsconfig.json +++ b/packages/design-system/tsconfig.json @@ -2,7 +2,9 @@ "extends": "@scandic-hotels/typescript-config/react-library.json", "compilerOptions": { "allowImportingTsExtensions": true, - "noEmit": true + "noEmit": true, + "baseUrl": ".", + "paths": {} }, "include": ["example", "lib"], "exclude": ["node_modules", "**/*.test.ts"] diff --git a/packages/trpc/lib/routers/hotels/output.ts b/packages/trpc/lib/routers/hotels/output.ts index 92ae65bed..dd56ea3ed 100644 --- a/packages/trpc/lib/routers/hotels/output.ts +++ b/packages/trpc/lib/routers/hotels/output.ts @@ -5,7 +5,7 @@ import { toLang } from "@scandic-hotels/common/utils/languages" import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator" import { RateEnum } from "../../enums/rate" -import { RateTypeEnum } from "../../enums/rateType" +import { RateTypeEnum } from "../../../../common/constants/rateType" import { RoomPackageCodeEnum } from "../../enums/roomFilter" import { AvailabilityEnum } from "../../enums/selectHotel" import { diff --git a/packages/trpc/lib/routers/hotels/query.ts b/packages/trpc/lib/routers/hotels/query.ts index 133fc8613..b95836316 100644 --- a/packages/trpc/lib/routers/hotels/query.ts +++ b/packages/trpc/lib/routers/hotels/query.ts @@ -10,7 +10,7 @@ import * as api from "../../api" import { SEARCH_TYPE_REDEMPTION } from "../../constants/booking" import { BreakfastPackageEnum } from "../../enums/breakfast" import { RateEnum } from "../../enums/rate" -import { RateTypeEnum } from "../../enums/rateType" +import { RateTypeEnum } from "../../../../common/constants/rateType" import { AvailabilityEnum } from "../../enums/selectHotel" import { badRequestError, unauthorizedError } from "../../errors" import { diff --git a/packages/trpc/lib/routers/hotels/schemas/hotel/detailedFacility.ts b/packages/trpc/lib/routers/hotels/schemas/hotel/detailedFacility.ts index ba646e6cd..df5c99875 100644 --- a/packages/trpc/lib/routers/hotels/schemas/hotel/detailedFacility.ts +++ b/packages/trpc/lib/routers/hotels/schemas/hotel/detailedFacility.ts @@ -1,11 +1,10 @@ import slugify from "slugify" import { z } from "zod" +import { FacilityEnum } from "@scandic-hotels/common/constants/facilities" import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator" import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator" -import { FacilityEnum } from "../../../../enums/facilities" - const rawDetailedFacilitySchema = z.object({ filter: nullableStringValidator, icon: nullableStringValidator, diff --git a/packages/trpc/lib/routers/hotels/schemas/productTypePrice.ts b/packages/trpc/lib/routers/hotels/schemas/productTypePrice.ts index c6e5bb790..6a805314f 100644 --- a/packages/trpc/lib/routers/hotels/schemas/productTypePrice.ts +++ b/packages/trpc/lib/routers/hotels/schemas/productTypePrice.ts @@ -4,7 +4,7 @@ import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" import { nullableNumberValidator } from "@scandic-hotels/common/utils/zod/numberValidator" import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator" -import { RateTypeEnum } from "../../../enums/rateType" +import { RateTypeEnum } from "../../../../../common/constants/rateType" export const corporateChequeSchema = z .object({ diff --git a/yarn.lock b/yarn.lock index eb4d25570..f71e4b58d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6186,6 +6186,7 @@ __metadata: "@typescript-eslint/parser": "npm:^8.32.0" "@vitejs/plugin-react": "npm:^5.0.0" "@vitest/browser": "npm:^3.2.4" + babel-plugin-formatjs: "npm:^10.5.10" class-variance-authority: "npm:^0.7.1" colord: "npm:^2.9.3" copy-to-clipboard: "npm:^3.3.3" @@ -6208,6 +6209,7 @@ __metadata: rollup: "npm:^4.40.2" rollup-preserve-directives: "npm:^1.1.3" storybook: "npm:^9.1.2" + storybook-react-intl: "npm:^4.0.7" typescript: "npm:^5.8.3" vite: "npm:^6.3.5" vite-plugin-dts: "npm:^4.5.3" @@ -6217,6 +6219,7 @@ __metadata: peerDependencies: "@internationalized/date": ^3.8.0 "@radix-ui/react-slot": ^1.2.2 + "@vis.gl/react-google-maps": ^1.5.2 next: ^15 react: ^19.1.0 react-aria-components: ^1.8.0 @@ -9285,7 +9288,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-formatjs@npm:^10.5.39": +"babel-plugin-formatjs@npm:^10.5.10, babel-plugin-formatjs@npm:^10.5.39": version: 10.5.39 resolution: "babel-plugin-formatjs@npm:10.5.39" dependencies: @@ -18850,6 +18853,30 @@ __metadata: languageName: node linkType: hard +"storybook-i18n@npm:^4.0.5": + version: 4.0.5 + resolution: "storybook-i18n@npm:4.0.5" + dependencies: + "@storybook/icons": "npm:^1.4.0" + peerDependencies: + storybook: ^9.0.0 + checksum: 10c0/826de957a7ee7ea4afab6a1c6d1f101370f8ea4dc1651ca0b9a7903f767dbef585ebe33621e5f52f186ec03a4da76d214e40d9ba464a0af5903558b7fcadd092 + languageName: node + linkType: hard + +"storybook-react-intl@npm:^4.0.7": + version: 4.0.7 + resolution: "storybook-react-intl@npm:4.0.7" + dependencies: + storybook-i18n: "npm:^4.0.5" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-intl: ^5.24.0 || ^6.0.0 || ^7.0.0 + storybook: ^9.0.0 + checksum: 10c0/78e9db4817fd7e9f856cf5436e214231ac7573437e513cf099ccf007a41204ef8d2e90cde4905e0ea8c828ac3bc9ca881df26cd99b72d8cbe5392eb0db5b5dcb + languageName: node + linkType: hard + "storybook@npm:^9.1.2": version: 9.1.2 resolution: "storybook@npm:9.1.2"