From 8616e4ab768842c043f46331a75a7250b95d7f1f Mon Sep 17 00:00:00 2001 From: Pontus Dreij Date: Tue, 18 Feb 2025 14:20:54 +0000 Subject: [PATCH] Merged in feat/SW-1276-implement-design (pull request #1348) Feat/SW-1276 implement design * feat(SW-1276) UI implementation Desktop part 1 for MyStay * feat(SW-1276) UI implementation Desktop part 2 for MyStay * feat(SW-1276) UI implementation Mobile part 1 for MyStay * refactor: move files from MyStay/MyStay to MyStay * feat(SW-1276) Sidepeek implementation * feat(SW-1276): Refactoring * feat(SW-1276) UI implementation Mobile part 2 for MyStay * feat(SW-1276): translations * feat(SW-1276) fixed skeleton * feat(SW-1276): Added missing translations * feat(SW-1276): Removed console log * feat(SW-1276) fixed translations * feat(SW-1276): Added translations * feat(SW-1276) fix dynamic ID:s * feat(SW-1276) removed createElement * feat(SW-1276): Fixed build errors * feat(SW-1276): Updated label * feat(SW-1276): Rewrite SummaryCard Approved-by: Niclas Edenvin --- .../my-stay/[refId]/@sidePeek/page.tsx | 22 + .../my-stay/[refId]/layout.tsx | 15 + .../my-stay/[refId]/loading.tsx | 5 + .../hotelreservation/my-stay/[refId]/page.tsx | 4 +- .../EnterDetails/Header/ToggleSidePeek.tsx | 7 +- .../SelectedRoom/ToggleSidePeek.tsx | 3 +- .../Ancillaries/ancillaries.module.css | 0 .../MyStay/{MyStay => }/Ancillaries/index.tsx | 0 .../BookingSummary/SummaryCard/index.tsx | 74 + .../SummaryCard/summaryCard.module.css | 52 + .../BookingSummary/bookingSummary.module.css | 22 + .../MyStay/BookingSummary/index.tsx | 130 ++ .../MyStay/Header/header.module.css | 28 + .../HotelReservation/MyStay/Header/index.tsx | 22 + .../BookingActions/bookingActions.module.css | 9 - .../MyStay/MyStay/BookingActions/index.tsx | 25 - .../MyStay/MyStay/Header/index.tsx | 31 - .../HotelReservation/MyStay/MyStay/index.tsx | 47 - .../MyStay/MyStay/myStay.module.css | 48 - .../MyStay/MyStay/myStaySkeleton.tsx | 47 - .../HotelReservation/MyStay/Promo/index.tsx | 26 + .../MyStay/Promo/promo.module.css | 33 + .../MyStay/ReferenceCard/index.tsx | 131 ++ .../ReferenceCard/referenceCard.module.css | 44 + .../MyStay/Room/GuestDetails.tsx | 97 ++ .../HotelReservation/MyStay/Room/index.tsx | 298 ++++ .../MyStay/Room/room.module.css | 284 ++++ components/HotelReservation/MyStay/index.tsx | 71 + .../HotelReservation/MyStay/myStay.module.css | 98 ++ .../MyStay/myStaySkeleton.tsx | 34 + .../PriceDetailsModal/index.tsx | 1 + components/Icons/Diamond.tsx | 23 + components/Icons/Directions.tsx | 29 + components/Icons/Link.tsx | 29 + components/Icons/get-icon-by-icon-name.ts | 9 + components/Icons/index.tsx | 3 + components/SkeletonShimmer/index.tsx | 1 + .../IconChip/iconChip.module.css | 22 + .../TempDesignSystem/IconChip/index.tsx | 19 + .../TempDesignSystem/IconChip/variants.ts | 13 + .../Text/Body/body.module.css | 4 + .../TempDesignSystem/Text/Body/variants.ts | 1 + .../Text/Caption/caption.module.css | 7 + .../TempDesignSystem/Text/Caption/variants.ts | 2 + .../TempDesignSystem/Toasts/toasts.module.css | 3 +- i18n/dictionaries/da.json | 24 +- i18n/dictionaries/de.json | 24 +- i18n/dictionaries/en.json | 27 +- i18n/dictionaries/fi.json | 24 +- i18n/dictionaries/no.json | 24 +- i18n/dictionaries/sv.json | 24 +- public/_static/img/scandic-coin.svg | 1407 +++++++++++++++++ public/_static/img/scandic-service.svg | 958 +++++++++++ .../hotelReservation/toggleSidePeekProps.ts | 1 + types/components/icon.ts | 3 + types/enums/breakfast.ts | 1 + 56 files changed, 4163 insertions(+), 227 deletions(-) create mode 100644 app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/@sidePeek/page.tsx create mode 100644 app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/layout.tsx create mode 100644 app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/loading.tsx rename components/HotelReservation/MyStay/{MyStay => }/Ancillaries/ancillaries.module.css (100%) rename components/HotelReservation/MyStay/{MyStay => }/Ancillaries/index.tsx (100%) create mode 100644 components/HotelReservation/MyStay/BookingSummary/SummaryCard/index.tsx create mode 100644 components/HotelReservation/MyStay/BookingSummary/SummaryCard/summaryCard.module.css create mode 100644 components/HotelReservation/MyStay/BookingSummary/bookingSummary.module.css create mode 100644 components/HotelReservation/MyStay/BookingSummary/index.tsx create mode 100644 components/HotelReservation/MyStay/Header/header.module.css create mode 100644 components/HotelReservation/MyStay/Header/index.tsx delete mode 100644 components/HotelReservation/MyStay/MyStay/BookingActions/bookingActions.module.css delete mode 100644 components/HotelReservation/MyStay/MyStay/BookingActions/index.tsx delete mode 100644 components/HotelReservation/MyStay/MyStay/Header/index.tsx delete mode 100644 components/HotelReservation/MyStay/MyStay/index.tsx delete mode 100644 components/HotelReservation/MyStay/MyStay/myStay.module.css delete mode 100644 components/HotelReservation/MyStay/MyStay/myStaySkeleton.tsx create mode 100644 components/HotelReservation/MyStay/Promo/index.tsx create mode 100644 components/HotelReservation/MyStay/Promo/promo.module.css create mode 100644 components/HotelReservation/MyStay/ReferenceCard/index.tsx create mode 100644 components/HotelReservation/MyStay/ReferenceCard/referenceCard.module.css create mode 100644 components/HotelReservation/MyStay/Room/GuestDetails.tsx create mode 100644 components/HotelReservation/MyStay/Room/index.tsx create mode 100644 components/HotelReservation/MyStay/Room/room.module.css create mode 100644 components/HotelReservation/MyStay/index.tsx create mode 100644 components/HotelReservation/MyStay/myStay.module.css create mode 100644 components/HotelReservation/MyStay/myStaySkeleton.tsx create mode 100644 components/Icons/Diamond.tsx create mode 100644 components/Icons/Directions.tsx create mode 100644 components/Icons/Link.tsx create mode 100644 components/TempDesignSystem/IconChip/iconChip.module.css create mode 100644 components/TempDesignSystem/IconChip/index.tsx create mode 100644 components/TempDesignSystem/IconChip/variants.ts create mode 100644 public/_static/img/scandic-coin.svg create mode 100644 public/_static/img/scandic-service.svg diff --git a/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/@sidePeek/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/@sidePeek/page.tsx new file mode 100644 index 000000000..933780e59 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/@sidePeek/page.tsx @@ -0,0 +1,22 @@ +import { getHotel } from "@/lib/trpc/memoizedRequests" + +import SidePeek from "@/components/HotelReservation/SidePeek" + +import type { LangParams, PageArgs } from "@/types/params" + +export default async function HotelSidePeek({ + params, + searchParams, +}: PageArgs) { + if (!searchParams.hotel) { + return + } + + const hotel = await getHotel({ + hotelId: searchParams.hotel, + language: params.lang, + isCardOnlyPayment: false, + }) + + return +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/layout.tsx b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/layout.tsx new file mode 100644 index 000000000..51fd48cb2 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/layout.tsx @@ -0,0 +1,15 @@ +import type { LangParams, LayoutArgs } from "@/types/params" + +export default function HotelReservationLayout({ + children, + sidePeek, +}: React.PropsWithChildren> & { + sidePeek: React.ReactNode +}) { + return ( +
+ {children} + {sidePeek} +
+ ) +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/loading.tsx b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/loading.tsx new file mode 100644 index 000000000..92ff5739e --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/loading.tsx @@ -0,0 +1,5 @@ +import LoadingSpinner from "@/components/LoadingSpinner" + +export default function Loading() { + return +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/page.tsx index 47c5d1440..f4baef247 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/my-stay/[refId]/page.tsx @@ -1,7 +1,7 @@ import { Suspense } from "react" -import { MyStay } from "@/components/HotelReservation/MyStay/MyStay" -import { MyStaySkeleton } from "@/components/HotelReservation/MyStay/MyStay/myStaySkeleton" +import { MyStay } from "@/components/HotelReservation/MyStay" +import { MyStaySkeleton } from "@/components/HotelReservation/MyStay/myStaySkeleton" import { setLang } from "@/i18n/serverContext" import type { LangParams, PageArgs } from "@/types/params" diff --git a/components/HotelReservation/EnterDetails/Header/ToggleSidePeek.tsx b/components/HotelReservation/EnterDetails/Header/ToggleSidePeek.tsx index 350006c2d..635767498 100644 --- a/components/HotelReservation/EnterDetails/Header/ToggleSidePeek.tsx +++ b/components/HotelReservation/EnterDetails/Header/ToggleSidePeek.tsx @@ -11,7 +11,10 @@ import styles from "./header.module.css" import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek" import type { ToggleSidePeekProps } from "@/types/components/hotelReservation/toggleSidePeekProps" -export default function ToggleSidePeek({ hotelId }: ToggleSidePeekProps) { +export default function ToggleSidePeek({ + hotelId, + intent = "textInverted", +}: ToggleSidePeekProps) { const intl = useIntl() const openSidePeek = useSidePeekStore((state) => state.openSidePeek) @@ -21,7 +24,7 @@ export default function ToggleSidePeek({ hotelId }: ToggleSidePeekProps) { theme="base" size="small" variant="icon" - intent="textInverted" + intent={intent} wrapping className={styles.toggle} > diff --git a/components/HotelReservation/EnterDetails/SelectedRoom/ToggleSidePeek.tsx b/components/HotelReservation/EnterDetails/SelectedRoom/ToggleSidePeek.tsx index 909c2ee48..3d4754e33 100644 --- a/components/HotelReservation/EnterDetails/SelectedRoom/ToggleSidePeek.tsx +++ b/components/HotelReservation/EnterDetails/SelectedRoom/ToggleSidePeek.tsx @@ -13,6 +13,7 @@ import type { ToggleSidePeekProps } from "@/types/components/hotelReservation/to export default function ToggleSidePeek({ hotelId, roomTypeCode, + intent = "textInverted", }: ToggleSidePeekProps) { const intl = useIntl() const openSidePeek = useSidePeekStore((state) => state.openSidePeek) @@ -25,7 +26,7 @@ export default function ToggleSidePeek({ theme="base" size="small" variant="icon" - intent="text" + intent={intent} wrapping > {intl.formatMessage({ id: "See room details" })} diff --git a/components/HotelReservation/MyStay/MyStay/Ancillaries/ancillaries.module.css b/components/HotelReservation/MyStay/Ancillaries/ancillaries.module.css similarity index 100% rename from components/HotelReservation/MyStay/MyStay/Ancillaries/ancillaries.module.css rename to components/HotelReservation/MyStay/Ancillaries/ancillaries.module.css diff --git a/components/HotelReservation/MyStay/MyStay/Ancillaries/index.tsx b/components/HotelReservation/MyStay/Ancillaries/index.tsx similarity index 100% rename from components/HotelReservation/MyStay/MyStay/Ancillaries/index.tsx rename to components/HotelReservation/MyStay/Ancillaries/index.tsx diff --git a/components/HotelReservation/MyStay/BookingSummary/SummaryCard/index.tsx b/components/HotelReservation/MyStay/BookingSummary/SummaryCard/index.tsx new file mode 100644 index 000000000..3314861b1 --- /dev/null +++ b/components/HotelReservation/MyStay/BookingSummary/SummaryCard/index.tsx @@ -0,0 +1,74 @@ +import Image from "@/components/Image" +import Link from "@/components/TempDesignSystem/Link" +import Body from "@/components/TempDesignSystem/Text/Body" +import Caption from "@/components/TempDesignSystem/Text/Caption" + +import styles from "./summaryCard.module.css" + +interface SummaryCardProps { + title: string + image: { + src: string + alt: string + } + texts: string[] + supportingText?: string + links?: { + href: string + text: string + icon: React.ReactNode + }[] + chip?: React.ReactNode +} + +export default function SummaryCard({ + title, + texts, + image, + supportingText, + links, + chip, +}: SummaryCardProps) { + return ( +
+
+ {image.alt} +
+
+
+ + {title} + + {texts.map((text) => ( + + {text} + + ))} +
+ {supportingText && ( + {supportingText} + )} +
+ {chip} + {links && ( +
+ {links.map((link) => ( + + + {link.icon} + {link.text} + + + ))} +
+ )} +
+
+
+ ) +} diff --git a/components/HotelReservation/MyStay/BookingSummary/SummaryCard/summaryCard.module.css b/components/HotelReservation/MyStay/BookingSummary/SummaryCard/summaryCard.module.css new file mode 100644 index 000000000..801ecd792 --- /dev/null +++ b/components/HotelReservation/MyStay/BookingSummary/SummaryCard/summaryCard.module.css @@ -0,0 +1,52 @@ +.card { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--Spacing-x2); +} + +@media (min-width: 768px) { + .card { + align-items: flex-start; + flex-direction: row; + } +} + +.image { + width: 152px; + height: 152px; + + border-radius: var(--Corner-radius-Medium); +} + +@media (min-width: 768px) { + .image { + background-color: var(--Base-Surface-Secondary-light-Normal); + } +} + +.content { + display: flex; + flex-direction: column; + height: 100%; +} + +.topContent { + margin-bottom: 10px; +} + +.bottomContent { + margin-top: auto; +} + +.links { + display: flex; + gap: var(--Spacing-x2); + padding-bottom: 10px; +} + +.link { + display: flex; + align-items: center; + gap: var(--Spacing-x-half); +} diff --git a/components/HotelReservation/MyStay/BookingSummary/bookingSummary.module.css b/components/HotelReservation/MyStay/BookingSummary/bookingSummary.module.css new file mode 100644 index 000000000..0c6357107 --- /dev/null +++ b/components/HotelReservation/MyStay/BookingSummary/bookingSummary.module.css @@ -0,0 +1,22 @@ +.bookingSummary { + display: flex; + flex-direction: column; + gap: var(--Spacing-x5); +} + +.bookingSummaryContent { + display: flex; + flex-direction: column; + gap: 80px; +} + +@media (min-width: 768px) { + .bookingSummaryContent { + flex-direction: row; + } +} + +.toast { + width: var(--max-width-content); + margin: 0 auto; +} diff --git a/components/HotelReservation/MyStay/BookingSummary/index.tsx b/components/HotelReservation/MyStay/BookingSummary/index.tsx new file mode 100644 index 000000000..6b0bf7c4d --- /dev/null +++ b/components/HotelReservation/MyStay/BookingSummary/index.tsx @@ -0,0 +1,130 @@ +import { dt } from "@/lib/dt" + +import { + CheckCircleIcon, + DirectionsIcon, + EmailIcon, + LinkIcon, +} from "@/components/Icons" +import CrossCircleIcon from "@/components/Icons/CrossCircle" +import IconChip from "@/components/TempDesignSystem/IconChip" +import Body from "@/components/TempDesignSystem/Text/Body" +import Caption from "@/components/TempDesignSystem/Text/Caption" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import { Toast } from "@/components/TempDesignSystem/Toasts" +import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" +import { formatPrice } from "@/utils/numberFormatting" + +import SummaryCard from "./SummaryCard" + +import styles from "./bookingSummary.module.css" + +import type { Hotel } from "@/types/hotel" +import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation" + +interface BookingSummaryProps { + booking: BookingConfirmation["booking"] + hotel: Hotel +} + +export default async function BookingSummary({ + booking, + hotel, +}: BookingSummaryProps) { + const intl = await getIntl() + const lang = getLang() + + const directionsUrl = `https://www.google.com/maps/dir/?api=1&destination=${hotel.location.latitude},${hotel.location.longitude}` + const isPaid = + booking.rateDefinition.cancellationRule !== "CancellableBefore6PM" + const bookingDate = dt(booking.createDateTime) + .locale(lang) + .format("D MMMM YYYY") + + return ( +
+ + {intl.formatMessage({ id: "Booking summary" })} + +
+ + ) : ( + + ) + } + > + + {intl.formatMessage({ id: "Status" })}:{" "} + {isPaid + ? intl.formatMessage({ id: "Paid" }) + : intl.formatMessage({ id: "Unpaid" })} + + + } + /> + , + }, + { + href: `mailto:${hotel.contactInformation.email}`, + text: intl.formatMessage({ id: "Email" }), + icon: , + }, + { + href: hotel.contactInformation.websiteUrl, + text: intl.formatMessage({ id: "Homepage" }), + icon: , + }, + ]} + /> +
+ {hotel.specialAlerts.length > 0 && ( +
+ +
    + {hotel.specialAlerts.map((alert) => ( +
  • + {alert.text} +
  • + ))} +
+
+
+ )} +
+ ) +} diff --git a/components/HotelReservation/MyStay/Header/header.module.css b/components/HotelReservation/MyStay/Header/header.module.css new file mode 100644 index 000000000..714befb01 --- /dev/null +++ b/components/HotelReservation/MyStay/Header/header.module.css @@ -0,0 +1,28 @@ +header .title { + position: relative; + z-index: 2; + left: 0; + right: 0; + margin: 0 auto; + padding-top: var(--Spacing-x6); + margin-top: var(--Spacing-x2); +} + +.title .hotelName { + font-family: var(--typography-Title-3-fontFamily); + font-size: var(--typography-Title-3-fontSize); + font-weight: var(--typography-Title-3-fontWeight); + letter-spacing: var(--typography-Title-3-letterSpacing); + line-height: var(--typography-Title-3-lineHeight); + display: block; +} + +@media (min-width: 768px) { + .title .hotelName { + font-family: var(--typography-Title-1-fontFamily); + font-size: var(--typography-Title-1-fontSize); + font-weight: var(--typography-Title-1-fontWeight); + letter-spacing: var(--typography-Title-1-letterSpacing); + line-height: var(--typography-Title-1-lineHeight); + } +} diff --git a/components/HotelReservation/MyStay/Header/index.tsx b/components/HotelReservation/MyStay/Header/index.tsx new file mode 100644 index 000000000..4aad1deb6 --- /dev/null +++ b/components/HotelReservation/MyStay/Header/index.tsx @@ -0,0 +1,22 @@ +import BiroScript from "@/components/TempDesignSystem/Text/BiroScript" +import Title from "@/components/TempDesignSystem/Text/Title" +import { getIntl } from "@/i18n" + +import styles from "./header.module.css" + +import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation" + +export async function Header({ hotel }: Pick) { + const intl = await getIntl() + return ( +
+ + <BiroScript type="two" tilted="medium"> + {intl.formatMessage({ id: "My stay at" })}{" "} + </BiroScript> + <span className={styles.hotelName}>{hotel.name}</span> + {hotel.cityName} + +
+ ) +} diff --git a/components/HotelReservation/MyStay/MyStay/BookingActions/bookingActions.module.css b/components/HotelReservation/MyStay/MyStay/BookingActions/bookingActions.module.css deleted file mode 100644 index b67d478e9..000000000 --- a/components/HotelReservation/MyStay/MyStay/BookingActions/bookingActions.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.container { - display: flex; - justify-content: space-between; - align-items: center; -} - -.actions { - display: flex; -} diff --git a/components/HotelReservation/MyStay/MyStay/BookingActions/index.tsx b/components/HotelReservation/MyStay/MyStay/BookingActions/index.tsx deleted file mode 100644 index f6bf3af33..000000000 --- a/components/HotelReservation/MyStay/MyStay/BookingActions/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import Button from "@/components/TempDesignSystem/Button" -import { getIntl } from "@/i18n" - -import styles from "./bookingActions.module.css" - -export async function BookingActions() { - const intl = await getIntl() - return ( -
-
- {intl.formatMessage( - { - id: "Changes can be made until {time}, {date} pending availability.", - }, - { time: "15:00", date: "Mon 15 Aug" } - )} -
-
- - - -
-
- ) -} diff --git a/components/HotelReservation/MyStay/MyStay/Header/index.tsx b/components/HotelReservation/MyStay/MyStay/Header/index.tsx deleted file mode 100644 index b0f5cb386..000000000 --- a/components/HotelReservation/MyStay/MyStay/Header/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import Title from "@/components/TempDesignSystem/Text/Title" -import { getIntl } from "@/i18n" - -import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation" - -export async function Header({ - booking, - hotel, -}: Pick) { - const intl = await getIntl() - return ( -
- - {intl.formatMessage( - { id: "My stay at {hotelName}" }, - { - hotelName: hotel.name, - } - )} - - - {intl.formatMessage( - { id: "Reservation No. {reservationNumber}" }, - { - reservationNumber: booking.confirmationNumber, - } - )} - -
- ) -} diff --git a/components/HotelReservation/MyStay/MyStay/index.tsx b/components/HotelReservation/MyStay/MyStay/index.tsx deleted file mode 100644 index 47f0bb70d..000000000 --- a/components/HotelReservation/MyStay/MyStay/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { dt } from "@/lib/dt" -import { - getAncillaryPackages, - getBookingConfirmation, -} from "@/lib/trpc/memoizedRequests" - -import Divider from "@/components/TempDesignSystem/Divider" - -import HotelDetails from "../../BookingConfirmation/HotelDetails" -import PaymentDetails from "../../BookingConfirmation/PaymentDetails" -import Promos from "../../BookingConfirmation/Promos" -import Rooms from "../../BookingConfirmation/Rooms" -import { Ancillaries } from "./Ancillaries" -import { BookingActions } from "./BookingActions" -import { Header } from "./Header" - -import styles from "./myStay.module.css" - -export async function MyStay({ reservationId }: { reservationId: string }) { - const { booking, hotel, room } = await getBookingConfirmation(reservationId) - const fromDate = dt(booking.checkInDate).format("YYYY-MM-DD") - const toDate = dt(booking.checkOutDate).format("YYYY-MM-DD") - const hotelId = hotel.operaId - const ancillaryInput = { fromDate, hotelId, toDate } - void getAncillaryPackages(ancillaryInput) - const ancillaryPackages = await getAncillaryPackages(ancillaryInput) - - return ( -
-
- - {room && } - {booking.showAncillaries && ( - - )} - - - - - -
- ) -} diff --git a/components/HotelReservation/MyStay/MyStay/myStay.module.css b/components/HotelReservation/MyStay/MyStay/myStay.module.css deleted file mode 100644 index c72ce5dac..000000000 --- a/components/HotelReservation/MyStay/MyStay/myStay.module.css +++ /dev/null @@ -1,48 +0,0 @@ -.main { - background-color: var(--Base-Surface-Primary-light-Normal); - display: flex; - flex-direction: column; - gap: var(--Spacing-x5); - margin: 0 auto; - min-height: 100dvh; - padding-top: var(--Spacing-x5); - width: var(--max-width-page); -} - -.headerSkeleton { - display: flex; - flex-direction: column; - gap: var(--Spacing-x2); -} - -.bookingActionsSkeleton { - display: flex; - flex-direction: row; - gap: var(--Spacing-x2); - justify-content: space-between; - align-items: center; -} - -.bookingActionsSkeletonButtons { - display: flex; - flex-direction: row; - gap: var(--Spacing-x1); -} - -.ancillariesSkeleton { - display: flex; - flex-direction: row; - gap: var(--Spacing-x2); -} - -.paymentDetailsSkeleton { - display: flex; - flex-direction: column; - gap: var(--Spacing-x2); -} - -.hotelDetailsSkeleton { - display: flex; - flex-direction: column; - gap: var(--Spacing-x2); -} diff --git a/components/HotelReservation/MyStay/MyStay/myStaySkeleton.tsx b/components/HotelReservation/MyStay/MyStay/myStaySkeleton.tsx deleted file mode 100644 index e92292597..000000000 --- a/components/HotelReservation/MyStay/MyStay/myStaySkeleton.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import SkeletonShimmer from "@/components/SkeletonShimmer" -import Divider from "@/components/TempDesignSystem/Divider" - -import styles from "./myStay.module.css" - -export async function MyStaySkeleton() { - return ( -
-
- - -
-
- -
- - - -
-
-
- -
-
- - - - - -
- -
- - - - -
- -
- - - - -
-
- ) -} diff --git a/components/HotelReservation/MyStay/Promo/index.tsx b/components/HotelReservation/MyStay/Promo/index.tsx new file mode 100644 index 000000000..87b7f4748 --- /dev/null +++ b/components/HotelReservation/MyStay/Promo/index.tsx @@ -0,0 +1,26 @@ +import Button from "@/components/TempDesignSystem/Button" +import Link from "@/components/TempDesignSystem/Link" +import Body from "@/components/TempDesignSystem/Text/Body" +import Title from "@/components/TempDesignSystem/Text/Title" + +import styles from "./promo.module.css" + +import type { PromoProps } from "@/types/components/hotelReservation/bookingConfirmation/promo" + +export default function Promo({ buttonText, href, text, title }: PromoProps) { + return ( + +
+ + {title} + + + {text} + + +
+ + ) +} diff --git a/components/HotelReservation/MyStay/Promo/promo.module.css b/components/HotelReservation/MyStay/Promo/promo.module.css new file mode 100644 index 000000000..e6782faf0 --- /dev/null +++ b/components/HotelReservation/MyStay/Promo/promo.module.css @@ -0,0 +1,33 @@ +.promo { + align-items: center; + background-position: 50%; + background-repeat: no-repeat; + background-size: cover; + display: flex; + flex: 1 0 480px; + flex-direction: column; + gap: var(--Spacing-x2); + height: 480px; + justify-content: center; + padding: var(--Spacing-x4) var(--Spacing-x3); +} + +@media (min-width: 768px) { + .promo { + border-radius: var(--Medium, 8px); + } +} + +.link .promo { + background-image: linear-gradient( + 180deg, + rgba(0, 0, 0, 0) 0%, + rgba(0, 0, 0, 0.36) 37.88%, + rgba(0, 0, 0, 0.75) 100% + ), + url("/_static/img/Scandic_Family_Breakfast.jpg"); +} + +.text { + max-width: 400px; +} diff --git a/components/HotelReservation/MyStay/ReferenceCard/index.tsx b/components/HotelReservation/MyStay/ReferenceCard/index.tsx new file mode 100644 index 000000000..ae4fb795b --- /dev/null +++ b/components/HotelReservation/MyStay/ReferenceCard/index.tsx @@ -0,0 +1,131 @@ +import { dt } from "@/lib/dt" + +import Button from "@/components/TempDesignSystem/Button" +import Divider from "@/components/TempDesignSystem/Divider" +import Link from "@/components/TempDesignSystem/Link" +import Caption from "@/components/TempDesignSystem/Text/Caption" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" +import { formatPrice } from "@/utils/numberFormatting" + +import styles from "./referenceCard.module.css" + +import type { Hotel } from "@/types/hotel" +import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation" + +export async function ReferenceCard({ + booking, + hotel, +}: { + booking: BookingConfirmation["booking"] + hotel: Hotel +}) { + const intl = await getIntl() + const lang = getLang() + + const fromDate = dt(booking.checkInDate).locale(lang) + const toDate = dt(booking.checkOutDate).locale(lang) + + const directionsUrl = `https://www.google.com/maps/dir/?api=1&destination=${hotel.location.latitude},${hotel.location.longitude}` + + return ( +
+
+ + {intl.formatMessage({ id: "Reference" })} + + + {intl.formatMessage({ id: "Reference number" })} + + + {booking.confirmationNumber} + +
+ +
+ + {intl.formatMessage({ id: "Guests" })} + + + {booking.childrenAges.length > 0 + ? intl.formatMessage( + { id: "{adults} adults, {children} children" }, + { + adults: booking.adults, + children: booking.childrenAges.length, + } + ) + : intl.formatMessage( + { id: "{adults} adults" }, + { + adults: booking.adults, + } + )} + +
+
+ + {intl.formatMessage({ id: "Check-in" })} + + + {`${fromDate.format("dddd, D MMMM")} ${intl.formatMessage({ id: "from" })} ${fromDate.format("HH:mm")}`} + +
+
+ + {intl.formatMessage({ id: "Check-out" })} + + + {`${toDate.format("dddd, D MMMM")} ${intl.formatMessage({ id: "from" })} ${toDate.format("HH:mm")}`} + +
+ +
+ + {intl.formatMessage({ id: "Total paid" })} + + + {formatPrice(intl, booking.totalPrice, booking.currencyCode)} + +
+
+ + +
+ {booking.rateDefinition.cancellationRule !== "NotCancellable" && ( + + {intl.formatMessage( + { + id: "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.", + }, + { + date: fromDate.format("D MMMM"), + time: "18:00", + } + )} + + )} +
+ ) +} diff --git a/components/HotelReservation/MyStay/ReferenceCard/referenceCard.module.css b/components/HotelReservation/MyStay/ReferenceCard/referenceCard.module.css new file mode 100644 index 000000000..54d9e40c1 --- /dev/null +++ b/components/HotelReservation/MyStay/ReferenceCard/referenceCard.module.css @@ -0,0 +1,44 @@ +.referenceCard { + width: var(--max-width-content); + max-width: 588px; + margin: 0 auto; + padding: var(--Spacing-x3); + border-radius: var(--Corner-radius-Large); + background-color: var(--Base-Surface-Primary-light-Normal); + box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); +} + +.referenceRow { + display: flex; + justify-content: space-between; + padding-bottom: var(--Spacing-x-one-and-half); +} + +.divider { + margin-bottom: var(--Spacing-x-one-and-half); +} + +.actionArea { + display: flex; + gap: var(--Spacing-x3); + margin: var(--Spacing-x4) 0 var(--Spacing-x3); +} + +.referenceCard .note { + text-align: center; + width: 80%; + margin: 0 auto; +} + +.titleDesktop { + display: none; +} + +@media (min-width: 768px) { + .titleMobile { + display: none; + } + .titleDesktop { + display: block; + } +} diff --git a/components/HotelReservation/MyStay/Room/GuestDetails.tsx b/components/HotelReservation/MyStay/Room/GuestDetails.tsx new file mode 100644 index 000000000..a4e011f38 --- /dev/null +++ b/components/HotelReservation/MyStay/Room/GuestDetails.tsx @@ -0,0 +1,97 @@ +import { useIntl } from "react-intl" + +import { DiamondIcon, EditIcon } from "@/components/Icons" +import MembershipLevelIcon from "@/components/Levels/Icon" +import Button from "@/components/TempDesignSystem/Button" +import Body from "@/components/TempDesignSystem/Text/Body" +import Caption from "@/components/TempDesignSystem/Text/Caption" + +import styles from "./room.module.css" + +import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation" +import type { User } from "@/types/user" + +export default function GuestDetails({ + user, + booking, + isMobile = false, +}: { + user: User | null + booking: BookingConfirmation["booking"] + isMobile?: boolean +}) { + const intl = useIntl() + const containerClass = isMobile + ? styles.guestDetailsMobile + : styles.guestDetailsDesktop + + return ( +
+ {user?.membership && ( +
+
+
+ + {intl.formatMessage({ id: "Your member tier" })} + +
+ +
+
+ {isMobile && ( +
+ +
+ )} + + {intl.formatMessage({ id: "Total points" })} + + + + {user.membership.currentPoints} + +
+
+ )} +
+ + {booking.guest.firstName} {booking.guest.lastName} + + {user?.membership && ( + + {intl.formatMessage({ id: "Member no." })}{" "} + {user.membership.membershipNumber} + + )} + {booking.guest.email} + + {booking.guest.phoneNumber} + +
+ +
+ ) +} diff --git a/components/HotelReservation/MyStay/Room/index.tsx b/components/HotelReservation/MyStay/Room/index.tsx new file mode 100644 index 000000000..51ff9eb2b --- /dev/null +++ b/components/HotelReservation/MyStay/Room/index.tsx @@ -0,0 +1,298 @@ +"use client" + +import { useIntl } from "react-intl" + +import { dt } from "@/lib/dt" + +import { getIconForFeatureCode } from "@/components/HotelReservation/utils" +import { + BedDoubleIcon, + CoffeeIcon, + ContractIcon, + DoorOpenIcon, + PersonIcon, +} from "@/components/Icons" +import RocketLaunch from "@/components/Icons/Refresh" +import Image from "@/components/Image" +import Body from "@/components/TempDesignSystem/Text/Body" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import useLang from "@/hooks/useLang" +import { formatPrice } from "@/utils/numberFormatting" + +import ToggleSidePeek from "../../EnterDetails/SelectedRoom/ToggleSidePeek" +import PriceDetailsModal from "../../PriceDetailsModal" +import GuestDetails from "./GuestDetails" + +import styles from "./room.module.css" + +import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter" +import { BreakfastPackageEnum } from "@/types/enums/breakfast" +import type { Hotel, Room } from "@/types/hotel" +import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation" +import type { User } from "@/types/user" + +interface RoomProps { + booking: BookingConfirmation["booking"] + room: + | (Room & { + bedType: Room["roomTypes"][number] + }) + | null + hotel: Hotel + user: User | null +} + +function hasBreakfastPackage( + packages: BookingConfirmation["booking"]["packages"] +) { + return packages.some( + (p) => + p.code === BreakfastPackageEnum.REGULAR_BREAKFAST || + p.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST || + p.code === BreakfastPackageEnum.SPECIAL_PACKAGE_BREAKFAST + ) +} + +function RoomHeader({ + room, + hotel, +}: { + room: RoomProps["room"] + hotel: Hotel +}) { + if (!room) return null + + return ( +
+ + {room.name} + + +
+ ) +} + +export function Room({ booking, room, hotel, user }: RoomProps) { + const intl = useIntl() + const lang = useLang() + + if (!room) return null + + const fromDate = dt(booking.checkInDate).locale(lang) + + return ( +
+
+ +
+
+ {booking.packages + .filter((item) => + Object.values(RoomPackageCodeEnum).includes( + item.code as RoomPackageCodeEnum + ) + ) + .map((item) => { + const Icon = getIconForFeatureCode( + item.code as RoomPackageCodeEnum + ) + return ( + + + + ) + })} +
+
+ {room.images.slice(0, 2).map((image) => ( + {room?.name + ))} +
+
+
+
+ + + + {intl.formatMessage({ id: "Booking policy" })} + + +
+ + {booking.rateDefinition.title} + +
+
+
+ + + + {intl.formatMessage({ id: "Rebooking" })} + + +
+ + {intl.formatMessage( + { id: "Until {time}, {date}" }, + { time: "18:00", date: fromDate.format("dddd D MMM") } + )} + +
+
+ {booking.packages.some((item) => + Object.values(RoomPackageCodeEnum).includes( + item.code as RoomPackageCodeEnum + ) + ) && ( +
+ + + + {intl.formatMessage({ id: "Room type" })} + + +
+ + {booking.packages + .filter((item) => + Object.values(RoomPackageCodeEnum).includes( + item.code as RoomPackageCodeEnum + ) + ) + .map((item) => item.description) + .join(", ")} + +
+
+ )} +
+ + + + {intl.formatMessage({ id: "Guests" })} + + +
+ + {booking.childrenAges.length > 0 + ? intl.formatMessage( + { id: "{adults} adults, {children} children" }, + { + adults: booking.adults, + children: booking.childrenAges.length, + } + ) + : intl.formatMessage( + { id: "{adults} adults" }, + { + adults: booking.adults, + } + )} + +
+
+
+ + + + {intl.formatMessage({ id: "Breakfast" })} + + +
+ + {hasBreakfastPackage(booking.packages) + ? intl.formatMessage({ id: "Included" }) + : intl.formatMessage({ id: "Not included" })} + +
+
+
+ + + + {intl.formatMessage({ id: "Bed preference" })} + + +
+ + {room.bedType.mainBed.description} + {room.bedType.mainBed.widthRange.min === + room.bedType.mainBed.widthRange.max + ? ` (${room.bedType.mainBed.widthRange.min} ${intl.formatMessage({ id: "cm" })})` + : ` (${room.bedType.mainBed.widthRange.min} - ${room.bedType.mainBed.widthRange.max} ${intl.formatMessage({ id: "cm" })})`} + +
+
+
+ +
+
+
+
+
+ + {intl.formatMessage({ id: "Room total" })} + + + {formatPrice(intl, booking.totalPrice, booking.currencyCode)} + +
+ + +
+
+
+
+ +
+ ) +} diff --git a/components/HotelReservation/MyStay/Room/room.module.css b/components/HotelReservation/MyStay/Room/room.module.css new file mode 100644 index 000000000..31fbe647f --- /dev/null +++ b/components/HotelReservation/MyStay/Room/room.module.css @@ -0,0 +1,284 @@ +.room { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); + background-color: var(--Base-Background-Primary-Normal); + padding: var(--Spacing-x3) 0; +} + +@media (min-width: 768px) { + .room { + background-color: transparent; + padding: 0; + } +} + +.roomHeader { + display: flex; + flex-direction: column; + width: var(--max-width-content); + margin: 0 auto; + align-items: flex-start; + gap: var(--Spacing-x1); +} + +@media (min-width: 768px) { + .roomHeader { + justify-content: space-between; + align-items: center; + flex-direction: row; + } +} + +.booking { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); + position: relative; + width: var(--max-width-content); + margin: 0 auto; +} + +@media (min-width: 768px) { + .booking { + border-radius: var(--Corner-radius-Large); + background-color: var(--Base-Background-Primary-Normal); + padding: var(--Spacing-x2); + } +} + +.chipContainer { + position: absolute; + top: 300px; + left: 25px; + display: flex; + flex-direction: row; + gap: var(--Spacing-x1); +} + +.chip { + background-color: var(--Main-Grey-White); + padding: var(--Spacing-x-half) var(--Spacing-x1); + border-radius: var(--Corner-radius-Small); +} + +.images { + display: grid; + gap: var(--Spacing-x-one-and-half); + grid-template-columns: 1fr; + height: 210px; + overflow: hidden; +} + +@media (min-width: 768px) { + .images { + height: 320px; + grid-template-columns: 1fr 1fr; + } +} + +.image { + border-radius: var(--Corner-radius-Medium); + width: 100%; + height: 210px; + aspect-ratio: 16/9; + object-fit: cover; +} + +.image:last-child { + display: none; +} + +@media (min-width: 768px) { + .image { + height: 100%; + } + .image:last-child { + display: block; + } +} + +.roomDetails { + display: grid; + gap: var(--Spacing-x5); +} + +@media (min-width: 768px) { + .roomDetails { + grid-template-columns: minmax(0, 700px) 1fr; + } +} + +.bookingDetails { + max-width: 100%; + padding: 0 var(--Spacing-x2); +} + +@media (min-width: 768px) { + .bookingDetails { + padding: 0; + } +} + +.row { + display: flex; + flex-direction: column; + padding: var(--Spacing-x-one-and-half) 0; +} + +@media (min-width: 768px) { + .row { + border-bottom: 1px solid var(--Base-Border-Subtle); + flex-direction: row; + align-items: center; + justify-content: space-between; + } +} + +.row:last-child { + border-bottom: none; +} + +.rowTitle { + display: flex; + flex-direction: row; + gap: var(--Spacing-x1); +} + +.rowTitle svg { + width: 24px; + height: 24px; +} + +@media (min-width: 768px) { + .rowTitle svg { + width: 20px; + height: 20px; + } +} + +.rowContent { + padding-left: var(--Spacing-x4); +} + +.guestDetailsDesktop { + flex-direction: column; + align-items: flex-end; + display: none; +} + +@media (min-width: 768px) { + .guestDetailsDesktop { + display: flex; + } +} + +.guestDetailsMobile { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: var(--Spacing-x2); + background-color: var(--Main-Brand-PalePeach); + padding: var(--Spacing-x3) 0; +} + +.guestDetailsMobile .row { + align-items: center; +} + +.guestDetailsMobile .rowTitle { + margin-bottom: var(--Spacing-x1); +} + +.guestDetailsMobile .userDetails { + width: calc(100% - var(--Spacing-x4) - var(--Spacing-x4)); + border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider); + padding-bottom: var(--Spacing-x3); + margin-bottom: var(--Spacing-x3); +} + +.guestDetailsMobile .totalPoints { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: var(--Spacing-x1); + padding-top: var(--Spacing-x3); +} + +.guestDetailsMobile .totalPointsText { + margin-left: auto; +} + +.guestDetailsMobile .guest { + align-items: center; +} + +@media (min-width: 768px) { + .guestDetailsMobile { + display: none; + } + .totalPoints { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: var(--Spacing-x-one-and-half) 0; + } +} + +.guest { + display: flex; + flex-direction: column; + align-items: flex-end; + margin-bottom: var(--Spacing-x2); +} + +.bookingInformation { + display: flex; + flex-direction: column-reverse; + align-items: center; + gap: var(--Spacing-x2); +} + +@media (min-width: 768px) { + .bookingInformation { + flex-direction: row; + justify-content: space-between; + } +} + +.priceDetails { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--Spacing-x1); + border-top: 1px solid var(--Base-Border-Subtle); + border-bottom: 1px solid var(--Base-Border-Subtle); + padding: var(--Spacing-x-one-and-half) 0; + width: calc(100% - var(--Spacing-x4)); + justify-content: center; + margin: 0 auto; +} + +@media (min-width: 768px) { + .priceDetails { + border: none; + margin: 0; + width: auto; + flex-direction: column; + align-items: flex-end; + } +} +@media (min-width: 768px) { + .price { + display: flex; + gap: var(--Spacing-x1); + } +} + +.userDetails { + width: 100%; + border-bottom: 1px solid var(--Base-Border-Subtle); + margin-bottom: var(--Spacing-x1); +} diff --git a/components/HotelReservation/MyStay/index.tsx b/components/HotelReservation/MyStay/index.tsx new file mode 100644 index 000000000..426fd8ecd --- /dev/null +++ b/components/HotelReservation/MyStay/index.tsx @@ -0,0 +1,71 @@ +import { homeHrefs } from "@/constants/homeHrefs" +import { env } from "@/env/server" +import { dt } from "@/lib/dt" +import { + getAncillaryPackages, + getBookingConfirmation, + getProfileSafely, +} from "@/lib/trpc/memoizedRequests" + +import Image from "@/components/Image" +import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" + +import { Ancillaries } from "./Ancillaries" +import BookingSummary from "./BookingSummary" +import { Header } from "./Header" +import Promo from "./Promo" +import { ReferenceCard } from "./ReferenceCard" +import { Room } from "./Room" + +import styles from "./myStay.module.css" + +export async function MyStay({ reservationId }: { reservationId: string }) { + const { booking, hotel, room } = await getBookingConfirmation(reservationId) + const userResponse = await getProfileSafely() + const user = userResponse && !("error" in userResponse) ? userResponse : null + const intl = await getIntl() + const lang = getLang() + const homeUrl = homeHrefs[env.NODE_ENV][lang] + const fromDate = dt(booking.checkInDate).format("YYYY-MM-DD") + const toDate = dt(booking.checkOutDate).format("YYYY-MM-DD") + const hotelId = hotel.operaId + const ancillaryInput = { fromDate, hotelId, toDate } + void getAncillaryPackages(ancillaryInput) + const ancillaryPackages = await getAncillaryPackages(ancillaryInput) + + return ( +
+
+
+ {hotel.gallery?.heroImages[0].imageSizes.large && ( + {hotel.name} + )} +
+
+
+
+ +
+ {booking.showAncillaries && ( + + )} + + + +
+
+ ) +} diff --git a/components/HotelReservation/MyStay/myStay.module.css b/components/HotelReservation/MyStay/myStay.module.css new file mode 100644 index 000000000..9be3e07e7 --- /dev/null +++ b/components/HotelReservation/MyStay/myStay.module.css @@ -0,0 +1,98 @@ +.main { + background-color: var(--Base-Surface-Primary-light-Normal); + min-height: 100dvh; +} + +.imageContainer { + position: absolute; + width: 100%; + height: 480px; +} + +.blurOverlay { + position: absolute; + inset: 0; + backdrop-filter: blur(12px); + pointer-events: none; + z-index: 1; + mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, transparent 100%); + background: linear-gradient( + to bottom, + rgba(0, 0, 0, 0.5) 0%, + transparent 100% + ); +} + +.image { + object-fit: cover; + object-position: center; +} + +.headerContainer { + display: flex; + flex-direction: column; + gap: var(--Spacing-x4); +} + +.content { + width: 100%; + display: flex; + flex-direction: column; + gap: 80px; + margin: 0 auto; + position: relative; + z-index: 2; + padding-bottom: var(--Spacing-x3); +} + +@media (min-width: 768px) { + .content { + width: var(--max-width-content); + padding-bottom: 160px; + } +} + +.headerSkeleton { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); + align-items: center; + padding: var(--Spacing-x6) var(--Spacing-x2) 0; +} + +.section { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); + padding: 0 var(--Spacing-x2); +} + +.cardSkeleton { + max-width: 100%; + margin: -30px auto 0; + padding: 0 var(--Spacing-x2); +} + +.ancillariesSkeleton { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); +} + +@media (min-width: 768px) { + .ancillariesSkeleton { + flex-direction: row; + } +} + +.paymentDetailsSkeleton { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); +} + +.hotelDetailsSkeleton { + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); +} diff --git a/components/HotelReservation/MyStay/myStaySkeleton.tsx b/components/HotelReservation/MyStay/myStaySkeleton.tsx new file mode 100644 index 000000000..83488d0f0 --- /dev/null +++ b/components/HotelReservation/MyStay/myStaySkeleton.tsx @@ -0,0 +1,34 @@ +import SkeletonShimmer from "@/components/SkeletonShimmer" + +import styles from "./myStay.module.css" + +export async function MyStaySkeleton() { + return ( +
+
+ + + +
+
+ +
+
+ +
+ + + + + +
+
+
+ +
+ +
+
+
+ ) +} diff --git a/components/HotelReservation/PriceDetailsModal/index.tsx b/components/HotelReservation/PriceDetailsModal/index.tsx index 1fe296edc..da64b9a01 100644 --- a/components/HotelReservation/PriceDetailsModal/index.tsx +++ b/components/HotelReservation/PriceDetailsModal/index.tsx @@ -1,3 +1,4 @@ +"use client" import { useIntl } from "react-intl" import ChevronRightSmallIcon from "@/components/Icons/ChevronRightSmall" diff --git a/components/Icons/Diamond.tsx b/components/Icons/Diamond.tsx new file mode 100644 index 000000000..9d89c9b6d --- /dev/null +++ b/components/Icons/Diamond.tsx @@ -0,0 +1,23 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function DiamondIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + ) +} diff --git a/components/Icons/Directions.tsx b/components/Icons/Directions.tsx new file mode 100644 index 000000000..ce798a1b4 --- /dev/null +++ b/components/Icons/Directions.tsx @@ -0,0 +1,29 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function DirectionsIcon({ + className, + color, + width = "20", + height = "20", + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + ) +} diff --git a/components/Icons/Link.tsx b/components/Icons/Link.tsx new file mode 100644 index 000000000..81b775ad7 --- /dev/null +++ b/components/Icons/Link.tsx @@ -0,0 +1,29 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function LinkIcon({ + className, + color, + width = "20", + height = "20", + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + ) +} diff --git a/components/Icons/get-icon-by-icon-name.ts b/components/Icons/get-icon-by-icon-name.ts index 68d6864a7..9a05e6c51 100644 --- a/components/Icons/get-icon-by-icon-name.ts +++ b/components/Icons/get-icon-by-icon-name.ts @@ -34,6 +34,8 @@ import { CulturalIcon, CutleryOneIcon, CutleryTwoIcon, + DiamondIcon, + DirectionsIcon, DoorOpenIcon, DresserIcon, ElectricBikeIcon, @@ -67,6 +69,7 @@ import { KidsMocktailIcon, LampIcon, LaundryMachineIcon, + LinkIcon, LocalBarIcon, LocationIcon, LockIcon, @@ -191,6 +194,10 @@ export function getIconByIconName( return CutleryOneIcon case IconName.CutleryTwo: return CutleryTwoIcon + case IconName.Diamond: + return DiamondIcon + case IconName.Directions: + return DirectionsIcon case IconName.DoorOpen: return DoorOpenIcon case IconName.Dresser: @@ -257,6 +264,8 @@ export function getIconByIconName( return LampIcon case IconName.LaundryMachine: return LaundryMachineIcon + case IconName.Link: + return LinkIcon case IconName.LocalBar: return LocalBarIcon case IconName.Location: diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index 686409df5..af881a2b9 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -65,7 +65,9 @@ export { default as CutleryOneIcon } from "./CutleryOne" export { default as CutleryTwoIcon } from "./CutleryTwo" export { default as DeleteIcon } from "./Delete" export { default as DeskIcon } from "./Desk" +export { default as DiamondIcon } from "./Diamond" export { default as DiningIcon } from "./Dining" +export { default as DirectionsIcon } from "./Directions" export { default as DiscountIcon } from "./Discount" export { default as DoorClosedIcon } from "./DoorClosed" export { default as DoorOpenIcon } from "./DoorOpen" @@ -112,6 +114,7 @@ export { default as KidsMocktailIcon } from "./KidsMocktail" export { default as LampIcon } from "./Lamp" export { default as LaptopIcon } from "./Laptop" export { default as LaundryMachineIcon } from "./LaundryMachine" +export { default as LinkIcon } from "./Link" export { default as LocalBarIcon } from "./LocalBar" export { default as LocationIcon } from "./Location" export { default as LockIcon } from "./Lock" diff --git a/components/SkeletonShimmer/index.tsx b/components/SkeletonShimmer/index.tsx index c060d9006..ea9ba325f 100644 --- a/components/SkeletonShimmer/index.tsx +++ b/components/SkeletonShimmer/index.tsx @@ -29,6 +29,7 @@ export default function SkeletonShimmer({ style={{ height: height, width: width, + maxWidth: "100%", }} /> ) diff --git a/components/TempDesignSystem/IconChip/iconChip.module.css b/components/TempDesignSystem/IconChip/iconChip.module.css new file mode 100644 index 000000000..13fafb092 --- /dev/null +++ b/components/TempDesignSystem/IconChip/iconChip.module.css @@ -0,0 +1,22 @@ +.chip { + display: flex; + align-items: center; + gap: var(--Spacing-x1); + padding: var(--Spacing-x1) var(--Spacing-x-one-and-half); + border-radius: var(--Corner-radius-Small); +} + +.blue { + background-color: var(--Scandic-Blue-00); + color: var(--UI-Semantic-Information); +} + +.green { + background-color: var(--Scandic-Green-00); + color: var(--UI-Semantic-Success); +} + +.red { + background-color: var(--Scandic-Red-00); + color: var(--UI-Semantic-Error); +} diff --git a/components/TempDesignSystem/IconChip/index.tsx b/components/TempDesignSystem/IconChip/index.tsx new file mode 100644 index 000000000..561cb00a1 --- /dev/null +++ b/components/TempDesignSystem/IconChip/index.tsx @@ -0,0 +1,19 @@ +import { iconChipVariants } from "./variants" + +interface IconChipProps { + color: "blue" | "green" | "red" | null | undefined + icon: React.ReactNode + children: React.ReactNode +} + +export default function IconChip({ color, icon, children }: IconChipProps) { + const classNames = iconChipVariants({ + color: color, + }) + return ( +
+ {icon} + {children} +
+ ) +} diff --git a/components/TempDesignSystem/IconChip/variants.ts b/components/TempDesignSystem/IconChip/variants.ts new file mode 100644 index 000000000..f4ee78c25 --- /dev/null +++ b/components/TempDesignSystem/IconChip/variants.ts @@ -0,0 +1,13 @@ +import { cva } from "class-variance-authority" + +import styles from "./iconChip.module.css" + +export const iconChipVariants = cva(styles.chip, { + variants: { + color: { + blue: styles.blue, + green: styles.green, + red: styles.red, + }, + }, +}) diff --git a/components/TempDesignSystem/Text/Body/body.module.css b/components/TempDesignSystem/Text/Body/body.module.css index 5cd96c0ae..919194c04 100644 --- a/components/TempDesignSystem/Text/Body/body.module.css +++ b/components/TempDesignSystem/Text/Body/body.module.css @@ -143,3 +143,7 @@ .baseText { color: var(--Base-Text-Inverted); } + +.success { + color: var(--UI-Semantic-Success); +} diff --git a/components/TempDesignSystem/Text/Body/variants.ts b/components/TempDesignSystem/Text/Body/variants.ts index 00ee46a3d..b2c908dcf 100644 --- a/components/TempDesignSystem/Text/Body/variants.ts +++ b/components/TempDesignSystem/Text/Body/variants.ts @@ -26,6 +26,7 @@ const config = { primaryDim: styles.primaryDim, primaryStrong: styles.primaryStrong, baseText: styles.baseText, + success: styles.success, }, textAlign: { center: styles.textAlignCenter, diff --git a/components/TempDesignSystem/Text/Caption/caption.module.css b/components/TempDesignSystem/Text/Caption/caption.module.css index 7d2cbe752..331b285be 100644 --- a/components/TempDesignSystem/Text/Caption/caption.module.css +++ b/components/TempDesignSystem/Text/Caption/caption.module.css @@ -110,3 +110,10 @@ p.caption { .left { text-align: left; } + +.green { + color: var(--UI-Semantic-Success); +} +.blue { + color: var(--UI-Semantic-Information); +} diff --git a/components/TempDesignSystem/Text/Caption/variants.ts b/components/TempDesignSystem/Text/Caption/variants.ts index 96cfab491..643365762 100644 --- a/components/TempDesignSystem/Text/Caption/variants.ts +++ b/components/TempDesignSystem/Text/Caption/variants.ts @@ -18,6 +18,8 @@ const config = { textMediumContrast: styles.textMediumContrast, red: styles.red, white: styles.white, + green: styles.green, + blue: styles.blue, uiTextHighContrast: styles.uiTextHighContrast, uiTextActive: styles.uiTextActive, uiTextMediumContrast: styles.uiTextMediumContrast, diff --git a/components/TempDesignSystem/Toasts/toasts.module.css b/components/TempDesignSystem/Toasts/toasts.module.css index e5f811cb4..c9490ec93 100644 --- a/components/TempDesignSystem/Toasts/toasts.module.css +++ b/components/TempDesignSystem/Toasts/toasts.module.css @@ -9,8 +9,7 @@ } .content { - padding: var(--Spacing-x-one-and-half) var(--Spacing-x3) - var(--Spacing-x-one-and-half) var(--Spacing-x2); + padding: var(--Spacing-x-one-and-half) var(--Spacing-x3); } @media screen and (min-width: 768px) { diff --git a/i18n/dictionaries/da.json b/i18n/dictionaries/da.json index 16cd7a3d9..7618ac3d1 100644 --- a/i18n/dictionaries/da.json +++ b/i18n/dictionaries/da.json @@ -62,6 +62,7 @@ "Based on availability": "Baseret på tilgængelighed", "Bed": "Seng type", "Bed options": "Sengemuligheder", + "Bed preference": "Sengvalg", "Bed type": "Seng type", "Bike friendly": "Cykelvenlig", "Birth date": "Fødselsdato", @@ -78,6 +79,7 @@ "Booking": "Booking", "Booking confirmation": "Booking bekræftelse", "Booking number": "Bookingnummer", + "Booking policy": "Booking politik", "Booking summary": "Opsummering", "Breakfast": "Morgenmad", "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Morgenmad ({totalAdults, plural, one {# voksen} other {# voksne}}) x {totalBreakfasts}", @@ -101,6 +103,7 @@ "Cancel": "Afbestille", "Cancellation policy": "Cancellation policy", "Change room": "Skift værelse", + "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.": "Ændringer kan gøres indtil {time} på {date}, under forudsætning af tilgængelighed. Priserne for værelserne kan variere.", "Check for level upgrade": "Check for level upgrade", "Check in": "Check ind", "Check in from: {checkInTime}": "Indtjekning fra: {checkInTime}", @@ -162,6 +165,7 @@ "Dialog": "Dialog", "Didn't receive a code? Resend code": "Didn't receive a code? Resend code", "Dimensions": "Dimensioner", + "Directions": "Retninger", "Discard changes": "Kassér ændringer", "Discard unsaved changes?": "Slette ændringer, der ikke er gemt?", "Discounted rooms": "Værelser med rabat", @@ -229,6 +233,8 @@ "Full circle": "Full circle", "Full price rooms": "Fuld pris værelser", "Garage": "Garage", + "Get directions": "Få retninger", + "Get hotel directions": "Få hotel retninger", "Get inspired": "Bliv inspireret", "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.": "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.", "Get the member price: {amount}": "Betal kun {amount}", @@ -239,6 +245,7 @@ "Go to profile": "Go to profile", "Guarantee booking with credit card": "Garantere booking med kreditkort", "Guest information": "Gæsteinformation", + "Guests": "Gæster", "Guests & Rooms": "Gæster & værelser", "Gym": "Fitnesscenter", "Half circle": "Half circle", @@ -248,6 +255,7 @@ "Highest level": "Højeste niveau", "Hiking": "Vandring", "Home": "Hjem", + "Homepage": "Hjemmeside", "Hospital": "Hospital", "Hotel": "Hotel", "Hotel details": "Hoteloplysninger", @@ -320,6 +328,7 @@ "Main menu": "Hovedmenu", "Manage booking": "Manage booking", "Manage preferences": "Administrer præferencer", + "Manage stay": "Administrer ophold", "Map": "Kort", "Map of the city center": "Kort over byens centrum", "Map of the country": "Kort over landet", @@ -330,6 +339,7 @@ "Meetings & Conferences": "Møder & Konferencer", "Member Since: {value}": "Member Since: {value}", "Member discount": "Member discount", + "Member no.": "Medlemsnummer", "Member price": "Medlemspris", "Member price activated": "Medlemspris aktiveret", "Member price from": "Medlemspris fra", @@ -344,6 +354,7 @@ "Menu": "Menu", "Menus": "Menukort", "Modify": "Ændre", + "Modify guest details": "Ændre gæstdetaljer", "Mon-Fri Always open": "Man-Fre Altid åben", "Mon-Fri {openingTime}-{closingTime}": "Man-Fre {openingTime}-{closingTime}", "Monday": "Mandag", @@ -360,7 +371,7 @@ "My pages": "Mine sider", "My pages menu": "Mine sider menu", "My payment cards": "Mine betalingskort", - "My stay at {hotelName}": "My stay at {hotelName}", + "My stay at": "My stay at", "My wishes": "Mine ønsker", "N/A": "N/A", "Name": "Navn", @@ -408,6 +419,7 @@ "Outdoor pool": "Udendørs pool", "Overview": "Oversigt", "PETR": "Kæledyr", + "Paid": "Betalt", "Parking": "Parkering", "Parking / Garage": "Parkering / Garage", "Parking can be reserved in advance": "Parkering kan reserveres på forhånd", @@ -470,6 +482,7 @@ "Redeemed & valid through:": "Redeemed & valid through:", "Redirecting you to SAS": "Redirecting you to SAS", "Redirecting you to my pages.": "Redirecting you to my pages.", + "Reference": "Reference", "Reference #{bookingNr}": "Reference #{bookingNr}", "Relax": "Slap af", "Remember code": "Husk kode", @@ -485,6 +498,7 @@ "Room & Terms": "Værelse & Vilkår", "Room charge": "Værelsesafgift", "Room facilities": "Værelsesfaciliteter", + "Room total": "Værelse total", "Room {roomIndex}": "Værelse {roomIndex}", "Rooms": "Værelser", "Rooms & Guests": "Værelser & gæster", @@ -544,6 +558,7 @@ "Sports": "Sport", "Standard price": "Standardpris", "Standing table": "Standing table", + "Status": "Status", "Stay at {hotelName} | Hotel in {destination}": "Bo på {hotelName} | Hotel i {destination}", "Street": "Gade", "Submit": "Submit", @@ -573,8 +588,9 @@ "To get the member price {price}, log in or join when completing the booking.": "For at få medlemsprisen {price}, log ind eller tilmeld dig, når du udfylder bookingen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "For at sikre din reservation, beder vi om at du giver os dine betalingsoplysninger. Du kan så være sikker på, at ingen gebyrer vil blive opkrævet på dette tidspunkt.", "Total": "Total", - "Total Points": "Samlet antal point", "Total cost": "Total cost", + "Total paid": "Total betalt", + "Total points": "Samlet antal point", "Total price": "Samlet pris", "Total price (incl VAT)": "Samlet pris (inkl. moms)", "Tourist": "Turist", @@ -587,6 +603,8 @@ "Type of room": "Værelsestype", "U-shape": "U-form", "Unlink accounts": "Unlink accounts", + "Unpaid": "Ikke betalt", + "Until {time}, {date}": "Indtil {time} den {date}", "Upgrade expires {upgradeExpires, date, short}": "Upgrade expires {upgradeExpires, date, short}", "Upgrade your stay": "Opgrader dit ophold", "Use Bonus Cheque": "Brug Bonus Cheque", @@ -662,6 +680,7 @@ "Your details": "Dine oplysninger", "Your hotel": "Your hotel", "Your level": "Dit niveau", + "Your member tier": "Dit medlemskabsniveau", "Your points to spend": "Dine brugbare point", "Your room": "Dit værelse", "Your selected bed type will be provided based on availability": "Din valgte sengtype vil blive stillet til rådighed baseret på tilgængelighed", @@ -676,6 +695,7 @@ "booking.selectRoom": "Zimmer auswählen", "booking.thisRoomIsEquippedWith": "Dette værelse er udstyret med", "friday": "fredag", + "from": "fra", "max {seatings} pers": "max {seatings} pers", "monday": "mandag", "next level: {nextLevel}": "next level: {nextLevel}", diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json index c7865dc8d..37418dbad 100644 --- a/i18n/dictionaries/de.json +++ b/i18n/dictionaries/de.json @@ -63,6 +63,7 @@ "Based on availability": "Je nach Verfügbarkeit", "Bed": "Bettentyp", "Bed options": "Bettoptionen", + "Bed preference": "Betttyp", "Bed type": "Bettentyp", "Bike friendly": "Fahrradfreundlich", "Birth date": "Geburtsdatum", @@ -79,6 +80,7 @@ "Booking": "Booking", "Booking confirmation": "Buchungsbestätigung", "Booking number": "Buchungsnummer", + "Booking policy": "Buchungsbedingungen", "Booking summary": "Zusammenfassung", "Breakfast": "Frühstück", "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frühstück ({totalAdults, plural, one {# erwachsene} other {# erwachsene}}) x {totalBreakfasts}", @@ -102,6 +104,7 @@ "Cancel": "Stornieren", "Cancellation policy": "Cancellation policy", "Change room": "Zimmer ändern", + "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.": "Änderungen können bis {time} am {date} vorgenommen werden, vorausgesetzt, dass die Zimmer noch verfügbar sind. Die Zimmerpreise können variieren.", "Check for level upgrade": "Check for level upgrade", "Check in": "Einchecken", "Check in from: {checkInTime}": "Check-in ab: {checkInTime}", @@ -163,6 +166,7 @@ "Dialog": "Dialog", "Didn't receive a code? Resend code": "Didn't receive a code? Resend code", "Dimensions": "Abmessungen", + "Directions": "Richtungen", "Discard changes": "Änderungen verwerfen", "Discard unsaved changes?": "Nicht gespeicherte Änderungen verwerfen?", "Discounted rooms": "Zimmer mit Rabatt", @@ -230,6 +234,8 @@ "Full circle": "Full circle", "Full price rooms": "Zimmer zum vollen Preis", "Garage": "Garage", + "Get directions": "Richtungen erhalten", + "Get hotel directions": "Hotel Richtungen", "Get inspired": "Lassen Sie sich inspieren", "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.": "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.", "Get the member price: {amount}": "Nur bezahlen {amount}", @@ -240,6 +246,7 @@ "Go to profile": "Go to profile", "Guarantee booking with credit card": "Buchung mit Kreditkarte garantieren", "Guest information": "Informationen für Gäste", + "Guests": "Gäste", "Guests & Rooms": "Gäste & Zimmer", "Gym": "Fitnessstudio", "Half circle": "Half circle", @@ -249,6 +256,7 @@ "Highest level": "Höchstes Level", "Hiking": "Wandern", "Home": "Heim", + "Homepage": "Startseite", "Hospital": "Krankenhaus", "Hotel": "Hotel", "Hotel details": "Hotelinformationen", @@ -321,6 +329,7 @@ "Main menu": "Hauptmenü", "Manage booking": "Manage booking", "Manage preferences": "Verwalten von Voreinstellungen", + "Manage stay": "Aufenthalt verwalten", "Map": "Karte", "Map of the city center": "Karte des Stadtzentrums", "Map of the country": "Karte des Landes", @@ -331,6 +340,7 @@ "Meetings & Conferences": "Tagungen & Konferenzen", "Member Since: {value}": "Member Since: {value}", "Member discount": "Member discount", + "Member no.": "Mitgliedsnummer", "Member price": "Mitgliederpreis", "Member price activated": "Mitgliederpreis aktiviert", "Member price from": "Mitgliederpreis ab", @@ -345,6 +355,7 @@ "Menu": "Menü", "Menus": "Menüs", "Modify": "Ändern", + "Modify guest details": "Gastdetails ändern", "Mon-Fri Always open": "Mo-Fr Immer geöffnet", "Mon-Fri {openingTime}-{closingTime}": "Mo-Fr {openingTime}-{closingTime}", "Monday": "Montag", @@ -361,7 +372,7 @@ "My pages": "Meine Seiten", "My pages menu": "Meine Seite Menü", "My payment cards": "Meine Zahlungskarten", - "My stay at {hotelName}": "My stay at {hotelName}", + "My stay at": "My stay at", "My wishes": "Meine Wünsche", "N/A": "N/A", "Name": "Name", @@ -409,6 +420,7 @@ "Outdoor pool": "Außenpool", "Overview": "Übersicht", "PETR": "Haustier", + "Paid": "Bezahlt", "Parking": "Parken", "Parking / Garage": "Parken / Garage", "Parking can be reserved in advance": "Parkplätze können im Voraus reserviert werden", @@ -471,6 +483,7 @@ "Redeemed & valid through:": "Redeemed & valid through:", "Redirecting you to SAS": "Redirecting you to SAS", "Redirecting you to my pages.": "Redirecting you to my pages.", + "Reference": "Referenz", "Reference #{bookingNr}": "Referenz #{bookingNr}", "Relax": "Entspannen", "Remember code": "Code merken", @@ -486,6 +499,7 @@ "Room & Terms": "Zimmer & Bedingungen", "Room charge": "Zimmerpreis", "Room facilities": "Zimmerausstattung", + "Room total": "Zimmer total", "Room {roomIndex}": "Zimmer {roomIndex}", "Rooms": "Räume", "Rooms & Guests": "Zimmer & Gäste", @@ -545,6 +559,7 @@ "Sports": "Sport", "Standard price": "Standardpreis", "Standing table": "Standing table", + "Status": "Status", "Stay at {hotelName} | Hotel in {destination}": "Übernachten Sie im {hotelName} | Hotel in {destination}", "Street": "Straße", "Submit": "Submit", @@ -573,8 +588,9 @@ "To get the member price {price}, log in or join when completing the booking.": "Um den Mitgliederpreis von {price} zu erhalten, loggen Sie sich ein oder treten Sie Scandic Friends bei, wenn Sie die Buchung abschließen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "Um Ihre Reservierung zu sichern, bitten wir Sie, Ihre Zahlungskarteninformationen zu geben. Sie können sicher sein, dass keine Gebühren zu diesem Zeitpunkt erhoben werden.", "Total": "Gesamt", - "Total Points": "Gesamtpunktzahl", "Total cost": "Total cost", + "Total paid": "Gesamt bezahlt", + "Total points": "Gesamtpunktzahl", "Total price": "Gesamtpreis", "Total price (incl VAT)": "Gesamtpreis (inkl. MwSt.)", "Tourist": "Tourist", @@ -587,6 +603,8 @@ "Type of room": "Zimmerart", "U-shape": "U-shape", "Unlink accounts": "Unlink accounts", + "Unpaid": "Nicht bezahlt", + "Until {time}, {date}": "Bis {time} am {date}", "Upgrade expires {upgradeExpires, date, short}": "Upgrade expires {upgradeExpires, date, short}", "Upgrade your stay": "Werten Sie Ihren Aufenthalt auf", "Use Bonus Cheque": "Bonusscheck nutzen", @@ -662,6 +680,7 @@ "Your details": "Ihre Angaben", "Your hotel": "Your hotel", "Your level": "Dein level", + "Your member tier": "Ihr Mitgliedsniveau", "Your points to spend": "Meine Punkte", "Your room": "Ihr Zimmer", "Your selected bed type will be provided based on availability": "Ihre ausgewählte Bettart wird basierend auf der Verfügbarkeit bereitgestellt", @@ -676,6 +695,7 @@ "booking.selectRoom": "Vælg værelse", "booking.thisRoomIsEquippedWith": "Dieses Zimmer ist ausgestattet mit", "friday": "freitag", + "from": "von", "max {seatings} pers": "max {seatings} pers", "monday": "montag", "next level: {nextLevel}": "next level: {nextLevel}", diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json index 5293a4bd2..e99b966f2 100644 --- a/i18n/dictionaries/en.json +++ b/i18n/dictionaries/en.json @@ -63,6 +63,7 @@ "Based on availability": "Based on availability", "Bed": "Bed", "Bed options": "Bed options", + "Bed preference": "Bed preference", "Bed type": "Bed type", "Bike friendly": "Bike friendly", "Birth date": "Birth date", @@ -79,6 +80,7 @@ "Booking": "Booking", "Booking confirmation": "Booking confirmation", "Booking number": "Booking number", + "Booking policy": "Booking policy", "Booking summary": "Booking summary", "Breakfast": "Breakfast", "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}", @@ -103,7 +105,7 @@ "Cancel booking": "Cancel booking", "Cancellation policy": "Cancellation policy", "Change room": "Change room", - "Changes can be made until {time}, {date} pending availability.": "Changes can be made until {time}, {date} pending availability.", + "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.": "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.", "Check for level upgrade": "Check for level upgrade", "Check in": "Check in", "Check in from: {checkInTime}": "Check in from: {checkInTime}", @@ -166,6 +168,7 @@ "Dialog": "Dialog", "Didn't receive a code? Resend code": "Didn't receive a code? Resend code", "Dimensions": "Dimensions", + "Directions": "Directions", "Discard changes": "Discard changes", "Discard unsaved changes?": "Discard unsaved changes?", "Discounted rooms": "Discounted rooms", @@ -233,6 +236,8 @@ "Full circle": "Full circle", "Full price rooms": "Full price rooms", "Garage": "Garage", + "Get directions": "Get directions", + "Get hotel directions": "Get hotel directions", "Get inspired": "Get inspired", "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.": "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.", "Get the member price: {amount}": "Get the member price: {amount}", @@ -243,6 +248,7 @@ "Go to profile": "Go to profile", "Guarantee booking with credit card": "Guarantee booking with credit card", "Guest information": "Guest information", + "Guests": "Guests", "Guests & Rooms": "Guests & Rooms", "Gym": "Gym", "Half circle": "Half circle", @@ -252,6 +258,7 @@ "Highest level": "Highest level", "Hiking": "Hiking", "Home": "Home", + "Homepage": "Homepage", "Hospital": "Hospital", "Hotel": "Hotel", "Hotel details": "Hotel details", @@ -325,6 +332,7 @@ "Main menu": "Main menu", "Manage booking": "Manage booking", "Manage preferences": "Manage preferences", + "Manage stay": "Manage stay", "Map": "Map", "Map of the city center": "Map of the city center", "Map of the country": "Map of the country", @@ -335,6 +343,7 @@ "Meetings & Conferences": "Meetings & Conferences", "Member Since: {value}": "Member Since: {value}", "Member discount": "Member discount", + "Member no.": "Member no.", "Member price": "Member price", "Member price activated": "Member price activated", "Member price from": "Member price from", @@ -350,6 +359,7 @@ "Menus": "Menus", "Modify": "Modify", "Modify dates": "Modify dates", + "Modify guest details": "Modify guest details", "Mon-Fri Always open": "Mon-Fri Always open", "Mon-Fri {openingTime}-{closingTime}": "Mon-Fri {openingTime}-{closingTime}", "Monday": "Monday", @@ -366,7 +376,7 @@ "My pages": "My pages", "My pages menu": "My pages menu", "My payment cards": "My payment cards", - "My stay at {hotelName}": "My stay at {hotelName}", + "My stay at": "My stay at", "My wishes": "My wishes", "N/A": "N/A", "Name": "Name", @@ -414,6 +424,7 @@ "Outdoor pool": "Outdoor pool", "Overview": "Overview", "PETR": "Pet", + "Paid": "Paid", "Parking": "Parking", "Parking / Garage": "Parking / Garage", "Parking can be reserved in advance": "Parking can be reserved in advance", @@ -476,7 +487,9 @@ "Redeemed & valid through:": "Redeemed & valid through:", "Redirecting you to SAS": "Redirecting you to SAS", "Redirecting you to my pages.": "Redirecting you to my pages.", + "Reference": "Reference", "Reference #{bookingNr}": "Reference #{bookingNr}", + "Reference number": "Reference number", "Relax": "Relax", "Remember code": "Remember code", "Remove card from member profile": "Remove card from member profile", @@ -492,6 +505,7 @@ "Room & Terms": "Room & Terms", "Room charge": "Room charge", "Room facilities": "Room facilities", + "Room total": "Room total", "Room {roomIndex}": "Room {roomIndex}", "Rooms": "Rooms", "Rooms & Guests": "Rooms & Guests", @@ -551,6 +565,7 @@ "Sports": "Sports", "Standard price": "Standard price", "Standing table": "Standing table", + "Status": "Status", "Stay at {hotelName} | Hotel in {destination}": "Stay at {hotelName} | Hotel in {destination}", "Street": "Street", "Submit": "Submit", @@ -580,8 +595,9 @@ "To get the member price {price}, log in or join when completing the booking.": "To get the member price {price}, log in or join when completing the booking.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.", "Total": "Total", - "Total Points": "Total Points", "Total cost": "Total cost", + "Total paid": "Total paid", + "Total points": "Total points", "Total price": "Total price", "Tourist": "Tourist", "Transaction date": "Transaction date", @@ -593,6 +609,8 @@ "Type of room": "Type of room", "U-shape": "U-shape", "Unlink accounts": "Unlink accounts", + "Unpaid": "Unpaid", + "Until {time}, {date}": "Until {time}, {date}", "Upgrade expires {upgradeExpires, date, short}": "Upgrade expires {upgradeExpires, date, short}", "Upgrade your stay": "Upgrade your stay", "Use Bonus Cheque": "Use Bonus Cheque", @@ -668,6 +686,7 @@ "Your details": "Your details", "Your hotel": "Your hotel", "Your level": "Your level", + "Your member tier": "Your member tier", "Your points to spend": "Your points to spend", "Your room": "Your room", "Your selected bed type will be provided based on availability": "Your selected bed type will be provided based on availability", @@ -678,7 +697,9 @@ "as of today": "as of today", "booking.selectRoom": "Select room", "booking.thisRoomIsEquippedWith": "This room is equipped with", + "cm": "cm", "friday": "friday", + "from": "from", "max {seatings} pers": "max {seatings} pers", "monday": "monday", "next level: {nextLevel}": "next level: {nextLevel}", diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json index d6eafdb04..df57296bb 100644 --- a/i18n/dictionaries/fi.json +++ b/i18n/dictionaries/fi.json @@ -61,6 +61,7 @@ "Based on availability": "Saatavuuden mukaan", "Bed": "Vuodetyyppi", "Bed options": "Vuodevaihtoehdot", + "Bed preference": "Vuodetyyppi", "Bed type": "Vuodetyyppi", "Bike friendly": "Pyöräystävällinen", "Birth date": "Syntymäaika", @@ -77,6 +78,7 @@ "Booking": "Booking", "Booking confirmation": "Varausvahvistus", "Booking number": "Varausnumero", + "Booking policy": "Varauskäytäntö", "Booking summary": "Yhteenveto", "Breakfast": "Aamiainen", "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Aamiainen ({totalAdults, plural, one {# aikuinen} other {# aikuiset}}) x {totalBreakfasts}", @@ -100,6 +102,7 @@ "Cancel": "Peruuttaa", "Cancellation policy": "Cancellation policy", "Change room": "Vaihda huonetta", + "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.": "Muutoksia voi tehdä {time} päivänä {date}, olettaen saatavuuden olemassaolon. Huonehinnat voivat muuttua.", "Check for level upgrade": "Check for level upgrade", "Check in": "Sisäänkirjautuminen", "Check in from: {checkInTime}": "Sisäänkirjautuminen alkaen: {checkInTime}", @@ -162,6 +165,7 @@ "Dialog": "Dialog", "Didn't receive a code? Resend code": "Didn't receive a code? Resend code", "Dimensions": "Mitat", + "Directions": "Suunnat", "Discard changes": "Hylkää muutokset", "Discard unsaved changes?": "Hylkäätkö tallentamattomat muutokset?", "Discounted rooms": "Alennetut huoneet", @@ -229,6 +233,8 @@ "Full circle": "Full circle", "Full price rooms": "Täyshintaiset huoneet", "Garage": "Autotalli", + "Get directions": "Hae suunnat", + "Get hotel directions": "Hae hotellin suunnat", "Get inspired": "Inspiroidu", "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.": "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.", "Get the member price: {amount}": "Vain maksaa {amount}", @@ -239,6 +245,7 @@ "Go to profile": "Go to profile", "Guarantee booking with credit card": "Varmista varaus luottokortilla", "Guest information": "Vieraan tiedot", + "Guests": "Vierailijat", "Guests & Rooms": "Vieraat & Huoneet", "Gym": "Kuntosali", "Half circle": "Half circle", @@ -248,6 +255,7 @@ "Highest level": "Korkein taso", "Hiking": "Hiking", "Home": "Kotiin", + "Homepage": "Kotisivu", "Hospital": "Sairaala", "Hotel": "Hotelli", "Hotel details": "Hotellin tiedot", @@ -320,6 +328,7 @@ "Main menu": "Päävalikko", "Manage booking": "Manage booking", "Manage preferences": "Asetusten hallinta", + "Manage stay": "Hallitse majoituksesi", "Map": "Kartta", "Map of the city center": "Kartta kaupungin keskustasta", "Map of the country": "Kartta maasta", @@ -330,6 +339,7 @@ "Meetings & Conferences": "Kokoukset & Konferenssit", "Member Since: {value}": "Member Since: {value}", "Member discount": "Member discount", + "Member no.": "Jäsenyysnumero", "Member price": "Jäsenhinta", "Member price activated": "Jäsenhinta aktivoitu", "Member price from": "Jäsenhinta alkaen", @@ -344,6 +354,7 @@ "Menu": "Valikko", "Menus": "Valikot", "Modify": "Muokkaa", + "Modify guest details": "Muuta vierailijoiden tietoja", "Mon-Fri Always open": "Ma-Pe Aina auki", "Mon-Fri {openingTime}-{closingTime}": "Ma-Pe {openingTime}-{closingTime}", "Monday": "Maanantai", @@ -360,7 +371,7 @@ "My pages": "Omat sivut", "My pages menu": "Omat sivut -valikko", "My payment cards": "Minun maksukortit", - "My stay at {hotelName}": "My stay at {hotelName}", + "My stay at": "My stay at", "My wishes": "Toiveeni", "N/A": "N/A", "Name": "Nimi", @@ -408,6 +419,7 @@ "Outdoor pool": "Ulkouima-allas", "Overview": "Yleiskatsaus", "PETR": "Lemmikki", + "Paid": "Maksettu", "Parking": "Pysäköinti", "Parking / Garage": "Pysäköinti / Autotalli", "Parking can be reserved in advance": "Pysäköintipaikan voi varata etukäteen", @@ -470,6 +482,7 @@ "Redeemed & valid through:": "Redeemed & valid through:", "Redirecting you to SAS": "Redirecting you to SAS", "Redirecting you to my pages.": "Redirecting you to my pages.", + "Reference": "Viite", "Reference #{bookingNr}": "Referenssi #{bookingNr}", "Relax": "Rentoutua", "Remember code": "Muista koodi", @@ -485,6 +498,7 @@ "Room & Terms": "Huone & Ehdot", "Room charge": "Huonemaksu", "Room facilities": "Huoneen varustelu", + "Room total": "Huoneen kokonaishinta", "Room {roomIndex}": "Huone {roomIndex}", "Rooms": "Huoneet", "Rooms & Guests": "Huoneet & Vieraat", @@ -545,6 +559,7 @@ "Sports": "Urheilu", "Standard price": "Normaali hinta", "Standing table": "Standing table", + "Status": "Status", "Stay at {hotelName} | Hotel in {destination}": "Majoitu kohteessa {hotelName} | Hotelli kohteessa {destination}", "Street": "Katu", "Submit": "Submit", @@ -573,8 +588,9 @@ "To get the member price {price}, log in or join when completing the booking.": "Jäsenhintaan saavat sisäänkirjautuneet tai liittyneet jäsenet.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "Varmistaaksesi varauksen, pyydämme sinua antamaan meille maksukortin tiedot. Varmista, että ei veloiteta maksusi tällä hetkellä.", "Total": "Kokonais", - "Total Points": "Kokonaispisteet", "Total cost": "Total cost", + "Total paid": "Kokonais maksamasi", + "Total points": "Kokonaispisteet", "Total price": "Kokonaishinta", "Total price (incl VAT)": "Kokonaishinta (sis. ALV)", "Tourist": "Turisti", @@ -587,6 +603,8 @@ "Type of room": "Huonetyyppi", "U-shape": "U-muoto", "Unlink accounts": "Unlink accounts", + "Unpaid": "Maksettaa", + "Until {time}, {date}": "Asti {time}, {date}", "Upgrade expires {upgradeExpires, date, short}": "Upgrade expires {upgradeExpires, date, short}", "Upgrade your stay": "Päivitä oleskelusi", "Use Bonus Cheque": "Käytä bonussekkiä", @@ -662,6 +680,7 @@ "Your details": "Tietosi", "Your hotel": "Your hotel", "Your level": "Tasosi", + "Your member tier": "Sinun jäsenyysluokkasi", "Your points to spend": "Käytettävissä olevat pisteesi", "Your room": "Sinun huoneesi", "Your selected bed type will be provided based on availability": "Valitun vuodetyypin toimitetaan saatavuuden mukaan", @@ -676,6 +695,7 @@ "booking.selectRoom": "Valitse huone", "booking.thisRoomIsEquippedWith": "Tämä huone on varustettu", "friday": "perjantai", + "from": "alkaa", "max {seatings} pers": "max {seatings} pers", "monday": "maanantai", "next level: {nextLevel}": "next level: {nextLevel}", diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json index e48e5ab44..b049c8baf 100644 --- a/i18n/dictionaries/no.json +++ b/i18n/dictionaries/no.json @@ -61,6 +61,7 @@ "Based on availability": "Basert på tilgjengelighet", "Bed": "Seng type", "Bed options": "Sengemuligheter", + "Bed preference": "Sengvalg", "Bed type": "Seng type", "Bike friendly": "Sykkelvennlig", "Birth date": "Fødselsdato", @@ -77,6 +78,7 @@ "Booking": "Booking", "Booking confirmation": "Bestillingsbekreftelse", "Booking number": "Bestillingsnummer", + "Booking policy": "Bestillingsbetingelser", "Booking summary": "Sammendrag", "Breakfast": "Frokost", "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frokost ({totalAdults, plural, one {# voksen} other {# voksne}}) x {totalBreakfasts}", @@ -100,6 +102,7 @@ "Cancel": "Avbryt", "Cancellation policy": "Cancellation policy", "Change room": "Endre rom", + "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.": "Endringer kan gjøres til {time} på {date}, under forutsetning av tilgjengelighet. Rompriser kan variere.", "Check for level upgrade": "Check for level upgrade", "Check in": "Sjekk inn", "Check in from: {checkInTime}": "Innsjekking fra: {checkInTime}", @@ -161,6 +164,7 @@ "Dialog": "Dialog", "Didn't receive a code? Resend code": "Didn't receive a code? Resend code", "Dimensions": "Dimensjoner", + "Directions": "Retninger", "Discard changes": "Forkaste endringer", "Discard unsaved changes?": "Forkaste endringer som ikke er lagret?", "Discounted rooms": "Rabatterte rom", @@ -228,6 +232,8 @@ "Full circle": "Full circle", "Full price rooms": "Full pris rom", "Garage": "Garasje", + "Get directions": "Få retninger", + "Get hotel directions": "Få hotel retninger", "Get inspired": "Bli inspirert", "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.": "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.", "Get the member price: {amount}": "Bare betal {amount}", @@ -238,6 +244,7 @@ "Go to profile": "Go to profile", "Guarantee booking with credit card": "Garantere booking med kredittkort", "Guest information": "Informasjon til gjester", + "Guests": "Gjester", "Guests & Rooms": "Gjester & rom", "Gym": "Treningsstudio", "Half circle": "Half circle", @@ -247,6 +254,7 @@ "Highest level": "Høyeste nivå", "Hiking": "Fotturer", "Home": "Hjem", + "Homepage": "Hjemmeside", "Hospital": "Sykehus", "Hotel": "Hotel", "Hotel details": "Detaljer om hotellet", @@ -319,6 +327,7 @@ "Main menu": "Hovedmeny", "Manage booking": "Manage booking", "Manage preferences": "Administrer preferanser", + "Manage stay": "Administrer ophold", "Map": "Kart", "Map of the city center": "Kart over sentrum", "Map of the country": "Kart over landet", @@ -329,6 +338,7 @@ "Meetings & Conferences": "Møter & Konferanser", "Member Since: {value}": "Member Since: {value}", "Member discount": "Member discount", + "Member no.": "Medlemsnummer", "Member price": "Medlemspris", "Member price activated": "Medlemspris aktivert", "Member price from": "Medlemspris fra", @@ -343,6 +353,7 @@ "Menu": "Menu", "Menus": "Menyer", "Modify": "Endre", + "Modify guest details": "Endre gjestdetaljer", "Mon-Fri Always open": "Man-Fre Alltid åpen", "Mon-Fri {openingTime}-{closingTime}": "Man-Fre {openingTime}-{closingTime}", "Monday": "Mandag", @@ -359,7 +370,7 @@ "My pages": "Mine sider", "My pages menu": "Mine sider-menyen", "My payment cards": "Mine betalingskort", - "My stay at {hotelName}": "My stay at {hotelName}", + "My stay at": "My stay at", "My wishes": "Mine ønsker", "N/A": "N/A", "Name": "Navn", @@ -407,6 +418,7 @@ "Outdoor pool": "Utendørs basseng", "Overview": "Oversikt", "PETR": "Kjæledyr", + "Paid": "Betalt", "Parking": "Parkering", "Parking / Garage": "Parkering / Garasje", "Parking can be reserved in advance": "Parkering kan reserveres på forhånd", @@ -469,6 +481,7 @@ "Redeemed & valid through:": "Redeemed & valid through:", "Redirecting you to SAS": "Redirecting you to SAS", "Redirecting you to my pages.": "Redirecting you to my pages.", + "Reference": "Referanse", "Reference #{bookingNr}": "Referanse #{bookingNr}", "Relax": "Slappe av", "Remember code": "Husk kode", @@ -484,6 +497,7 @@ "Room & Terms": "Rom & Vilkår", "Room charge": "Pris for rom", "Room facilities": "Romfasiliteter", + "Room total": "Rom total", "Room {roomIndex}": "Rom {roomIndex}", "Rooms": "Rom", "Rooms & Guests": "Rom og gjester", @@ -543,6 +557,7 @@ "Sports": "Sport", "Standard price": "Standardpris", "Standing table": "Standing table", + "Status": "Status", "Stay at {hotelName} | Hotel in {destination}": "Bo på {hotelName} | Hotell i {destination}", "Street": "Gate", "Submit": "Submit", @@ -571,9 +586,10 @@ "To get the member price {price}, log in or join when completing the booking.": "For å få medlemsprisen {price}, logg inn eller bli med når du fullfører bestillingen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "For å sikre din reservasjon, ber vi om at du gir oss dine betalingskortdetaljer. Vær sikker på at ingen gebyrer vil bli belastet på dette tidspunktet.", "Total": "Total", - "Total Points": "Totale poeng", "Total cost": "Total cost", "Total incl VAT": "Sum inkl mva", + "Total paid": "Total betalt", + "Total points": "Totale poeng", "Total price": "Totalpris", "Tourist": "Turist", "Transaction date": "Transaksjonsdato", @@ -585,6 +601,8 @@ "Type of room": "Romtype", "U-shape": "U-form", "Unlink accounts": "Unlink accounts", + "Unpaid": "Ikke betalt", + "Until {time}, {date}": "Til {time}, {date}", "Upgrade expires {upgradeExpires, date, short}": "Upgrade expires {upgradeExpires, date, short}", "Upgrade your stay": "Oppgrader oppholdet ditt", "Use Bonus Cheque": "Bruk bonussjekk", @@ -660,6 +678,7 @@ "Your details": "Dine detaljer", "Your hotel": "Your hotel", "Your level": "Ditt nivå", + "Your member tier": "Ditt medlemskapsnivå", "Your points to spend": "Dine brukbare poeng", "Your room": "Rommet ditt", "Your selected bed type will be provided based on availability": "Din valgte sengtype vil blive stillet til rådighed baseret på tilgængelighed", @@ -674,6 +693,7 @@ "booking.selectRoom": "Velg rom", "booking.thisRoomIsEquippedWith": "Dette rommet er utstyrt med", "friday": "fredag", + "from": "fra", "max {seatings} pers": "max {seatings} pers", "monday": "mandag", "next level: {nextLevel}": "next level: {nextLevel}", diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json index 4e9388f59..23de44b1f 100644 --- a/i18n/dictionaries/sv.json +++ b/i18n/dictionaries/sv.json @@ -61,6 +61,7 @@ "Based on availability": "Baserat på tillgänglighet", "Bed": "Sängtyp", "Bed options": "Sängalternativ", + "Bed preference": "Sängval", "Bed type": "Sängtyp", "Bike friendly": "Cykelvänligt", "Birth date": "Födelsedatum", @@ -77,6 +78,7 @@ "Booking": "Booking", "Booking confirmation": "Bokningsbekräftelse", "Booking number": "Bokningsnummer", + "Booking policy": "Bokningsvillkor", "Booking summary": "Sammanfattning", "Breakfast": "Frukost", "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frukost ({totalAdults, plural, one {# vuxen} other {# vuxna}}) x {totalBreakfasts}", @@ -100,6 +102,7 @@ "Cancel": "Avbryt", "Cancellation policy": "Cancellation policy", "Change room": "Ändra rum", + "Changes can be made until {time} on {date}, subject to availability. Room rates may vary.": "Ändringar kan göras tills {time} den {date}, under förutsättning av tillgänglighet. Priserna för rummen kan variera.", "Check for level upgrade": "Check for level upgrade", "Check in": "Checka in", "Check in from: {checkInTime}": "Incheckning från: {checkInTime}", @@ -161,6 +164,7 @@ "Dialog": "Dialog", "Didn't receive a code? Resend code": "Didn't receive a code? Resend code", "Dimensions": "Dimensioner", + "Directions": "Vägbeskrivning", "Discard changes": "Ignorera ändringar", "Discard unsaved changes?": "Vill du ignorera ändringar som inte har sparats?", "Discounted rooms": "Rabatterade rum", @@ -228,6 +232,8 @@ "Full circle": "Full circle", "Full price rooms": "Fullpris rum", "Garage": "Garage", + "Get directions": "Hämta vägbeskrivning", + "Get hotel directions": "Hämta vägbeskrivning till hotellet", "Get inspired": "Bli inspirerad", "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.": "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.", "Get the member price: {amount}": "Betala endast {amount}", @@ -238,6 +244,7 @@ "Go to profile": "Go to profile", "Guarantee booking with credit card": "Garantera bokning med kreditkort", "Guest information": "Information till gästerna", + "Guests": "Gäster", "Guests & Rooms": "Gäster & rum", "Gym": "Gym", "Half circle": "Half circle", @@ -247,6 +254,7 @@ "Highest level": "Högsta nivå", "Hiking": "Vandring", "Home": "Hem", + "Homepage": "Hemsida", "Hospital": "Sjukhus", "Hotel": "Hotell", "Hotel details": "Detaljer om hotellet", @@ -319,6 +327,7 @@ "Main menu": "Huvudmeny", "Manage booking": "Manage booking", "Manage preferences": "Hantera inställningar", + "Manage stay": "Hantera vistelse", "Map": "Karta", "Map of the city center": "Karta över stadskärnan", "Map of the country": "Karta över landet", @@ -329,6 +338,7 @@ "Meetings & Conferences": "Möten & Konferenser", "Member Since: {value}": "Member Since: {value}", "Member discount": "Member discount", + "Member no.": "Medlemsnummer", "Member price": "Medlemspris", "Member price activated": "Medlemspris aktiverat", "Member price from": "Medlemspris från", @@ -343,6 +353,7 @@ "Menu": "Meny", "Menus": "Menyer", "Modify": "Ändra", + "Modify guest details": "Ändra gästinformation", "Mon-Fri Always open": "Mån-Fre Alltid öppet", "Mon-Fri {openingTime}-{closingTime}": "Mån-Fre {openingTime}-{closingTime}", "Monday": "Måndag", @@ -359,7 +370,7 @@ "My pages": "Mina sidor", "My pages menu": "Mina sidor meny", "My payment cards": "Mina betalningskort", - "My stay at {hotelName}": "My stay at {hotelName}", + "My stay at": "My stay at", "My wishes": "Mina önskningar", "N/A": "N/A", "Name": "Namn", @@ -407,6 +418,7 @@ "Outdoor pool": "Utomhuspool", "Overview": "Översikt", "PETR": "Husdjur", + "Paid": "Betalt", "Parking": "Parkering", "Parking / Garage": "Parkering / Garage", "Parking can be reserved in advance": "Parkering kan reserveras i förväg", @@ -469,6 +481,7 @@ "Redeemed & valid through:": "Redeemed & valid through:", "Redirecting you to SAS": "Redirecting you to SAS", "Redirecting you to my pages.": "Redirecting you to my pages.", + "Reference": "Referens", "Reference #{bookingNr}": "Referens #{bookingNr}", "Relax": "Koppla av", "Remember code": "Kom ihåg kod", @@ -484,6 +497,7 @@ "Room & Terms": "Rum & Villkor", "Room charge": "Rumspris", "Room facilities": "Rumfaciliteter", + "Room total": "Rum total", "Room {roomIndex}": "Rum {roomIndex}", "Rooms": "Rum", "Rooms & Guests": "Rum och gäster", @@ -543,6 +557,7 @@ "Sports": "Sport", "Standard price": "Standardpris", "Standing table": "Ståbord", + "Status": "Status", "Stay at {hotelName} | Hotel in {destination}": "Bo på {hotelName} | Hotell i {destination}", "Street": "Gata", "Submit": "Submit", @@ -571,9 +586,10 @@ "To get the member price {price}, log in or join when completing the booking.": "För att få medlemsprisen {price}, logga in eller bli medlem när du slutför bokningen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "För att säkra din bokning ber vi om att du ger oss dina betalkortdetaljer. Välj säker på att ingen avgifter kommer att debiteras just nu.", "Total": "Totalt", - "Total Points": "Poäng totalt", "Total cost": "Total cost", "Total incl VAT": "Totalt inkl moms", + "Total paid": "Total betalt", + "Total points": "Poäng totalt", "Total price": "Totalpris", "Tourist": "Turist", "Transaction date": "Transaktionsdatum", @@ -585,6 +601,8 @@ "Type of room": "Rumstyp", "U-shape": "U-form", "Unlink accounts": "Unlink accounts", + "Unpaid": "Ej betalt", + "Until {time}, {date}": "Tills {time} den {date}", "Upgrade expires {upgradeExpires, date, short}": "Upgrade expires {upgradeExpires, date, short}", "Upgrade your stay": "Uppgradera din vistelse", "Use Bonus Cheque": "Använd bonuscheck", @@ -660,6 +678,7 @@ "Your details": "Dina uppgifter", "Your hotel": "Your hotel", "Your level": "Din nivå", + "Your member tier": "Din medlemskapsnivå", "Your points to spend": "Dina spenderbara poäng", "Your room": "Ditt rum", "Your selected bed type will be provided based on availability": "Din valda sängtyp kommer att tillhandahållas baserat på tillgänglighet", @@ -674,6 +693,7 @@ "booking.selectRoom": "Välj rum", "booking.thisRoomIsEquippedWith": "Detta rum är utrustat med", "friday": "fredag", + "from": "från", "max {seatings} pers": "max {seatings} pers", "monday": "måndag", "next level: {nextLevel}": "next level: {nextLevel}", diff --git a/public/_static/img/scandic-coin.svg b/public/_static/img/scandic-coin.svg new file mode 100644 index 000000000..07e5e86e8 --- /dev/null +++ b/public/_static/img/scandic-coin.svg @@ -0,0 +1,1407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/_static/img/scandic-service.svg b/public/_static/img/scandic-service.svg new file mode 100644 index 000000000..2689cf238 --- /dev/null +++ b/public/_static/img/scandic-service.svg @@ -0,0 +1,958 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/types/components/hotelReservation/toggleSidePeekProps.ts b/types/components/hotelReservation/toggleSidePeekProps.ts index 6c4282059..d7303c122 100644 --- a/types/components/hotelReservation/toggleSidePeekProps.ts +++ b/types/components/hotelReservation/toggleSidePeekProps.ts @@ -1,4 +1,5 @@ export type ToggleSidePeekProps = { hotelId: string roomTypeCode?: string + intent?: "text" | "textInverted" } diff --git a/types/components/icon.ts b/types/components/icon.ts index dc0975fc7..9071bb13e 100644 --- a/types/components/icon.ts +++ b/types/components/icon.ts @@ -42,6 +42,8 @@ export enum IconName { Cultural = "Cultural", CutleryOne = "CutleryOne", CutleryTwo = "CutleryTwo", + Diamond = "Diamond", + Directions = "Directions", DoorOpen = "DoorOpen", Dresser = "Dresser", ElectricBike = "ElectricBike", @@ -76,6 +78,7 @@ export enum IconName { Kids = "Kids", Lamp = "Lamp", LaundryMachine = "LaundryMachine", + Link = "Link", LocalBar = "LocalBar", Location = "Location", Lock = "Lock", diff --git a/types/enums/breakfast.ts b/types/enums/breakfast.ts index 723326c37..8baf581d2 100644 --- a/types/enums/breakfast.ts +++ b/types/enums/breakfast.ts @@ -1,4 +1,5 @@ export enum BreakfastPackageEnum { FREE_MEMBER_BREAKFAST = "BRF0", REGULAR_BREAKFAST = "BRF1", + SPECIAL_PACKAGE_BREAKFAST = "F01S", }