feat: SW-1422 Enabled booking code in booking widget

This commit is contained in:
Hrishikesh Vaipurkar
2025-01-23 20:25:37 +01:00
parent 46ebbbba8f
commit 1b5b09d7a6
16 changed files with 256 additions and 47 deletions

View File

@@ -23,6 +23,7 @@ import MobileToggleButton, {
import styles from "./bookingWidget.module.css"
import type {
BookingCodeSchema,
BookingWidgetClientProps,
BookingWidgetSchema,
BookingWidgetSearchData,
@@ -82,6 +83,10 @@ export default function BookingWidgetClient({
)
: undefined
const selectedBookingCode = bookingWidgetSearchData
? bookingWidgetSearchData.bookingCode
: undefined
const defaultRoomsData: BookingWidgetSchema["rooms"] =
bookingWidgetSearchData?.rooms?.map((room) => ({
adults: room.adults,
@@ -107,7 +112,10 @@ export default function BookingWidgetClient({
? parsedToDate.format("YYYY-MM-DD")
: now.utc().add(1, "day").format("YYYY-MM-DD"),
},
bookingCode: "",
bookingCode: {
value: selectedBookingCode ?? "",
remember: false,
},
redemption: false,
voucher: false,
rooms: defaultRoomsData,
@@ -164,7 +172,20 @@ export default function BookingWidgetClient({
!selectedLocation &&
sessionStorageSearchData &&
methods.setValue("location", encodeURIComponent(sessionStorageSearchData))
}, [methods, selectedLocation])
const storedBookingCode =
typeof window !== "undefined"
? localStorage.getItem("bookingCode")
: undefined
const initialBookingCode: BookingCodeSchema | undefined =
storedBookingCode && isValidJson(storedBookingCode)
? JSON.parse(storedBookingCode)
: undefined
!selectedBookingCode &&
initialBookingCode &&
initialBookingCode.remember &&
methods.setValue("bookingCode", initialBookingCode)
}, [methods, selectedLocation, selectedBookingCode])
return (
<FormProvider {...methods}>

View File

@@ -0,0 +1,22 @@
.bookingCodeLabel {
display: flex;
align-items: center;
gap: var(--Spacing-x-half);
}
.error {
display: flex;
gap: var(--Spacing-x-half);
}
.errorIcon {
min-width: 20px;
}
.bookingCodeRemember {
display: flex;
gap: var(--Spacing-x1);
/* ToDo: Remove once remember checkbox design are ready */
display: none;
}

View File

@@ -0,0 +1,90 @@
import { useFormContext } from "react-hook-form"
import { useIntl } from "react-intl"
import { ErrorCircleIcon, InfoCircleIcon } from "@/components/Icons"
import Modal from "@/components/Modal"
import Button from "@/components/TempDesignSystem/Button"
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Input from "../Input"
import styles from "./booking-code.module.css"
import type {
BookingCodeSchema,
BookingWidgetSchema,
} from "@/types/components/bookingWidget"
export default function BookingCode() {
const intl = useIntl()
const {
setValue,
formState: { errors },
getValues,
} = useFormContext<BookingWidgetSchema>()
const codeError = errors["bookingCode"]?.value
const codeVoucher = intl.formatMessage({ id: "Code / Voucher" })
const addCode = intl.formatMessage({ id: "Add code" })
const bookingCodeTooltipText = intl.formatMessage({
id: "booking.codes.information",
})
const bookingCode: BookingCodeSchema = getValues("bookingCode")
function updateBookingCodeFormValue(value: string) {
setValue("bookingCode.value", value, { shouldValidate: true })
}
return (
<>
<label htmlFor="booking-code">
<div className={styles.bookingCodeLabel}>
<Caption color="uiTextMediumContrast" type="bold" asChild>
<span>{codeVoucher}</span>
</Caption>
<Modal
trigger={
<Button intent="text">
<InfoCircleIcon
color="uiTextPlaceholder"
height={20}
width={20}
/>
</Button>
}
title={codeVoucher}
>
<Body color="uiTextHighContrast">{bookingCodeTooltipText}</Body>
</Modal>
</div>
<Input
type="text"
placeholder={addCode}
name="bookingCode"
id="booking-code"
onChange={(event) => updateBookingCodeFormValue(event.target.value)}
defaultValue={bookingCode?.value}
/>
</label>
{codeError && codeError.message ? (
<Caption color="red" className={styles.error}>
<ErrorCircleIcon color="red" className={styles.errorIcon} />
{intl.formatMessage({ id: codeError.message })}
</Caption>
) : null}
{/* ToDo: Update styles once designs are ready */}
<div className={styles.bookingCodeRemember}>
<Checkbox name="bookingCode.remember">
<Caption asChild>
<span>{intl.formatMessage({ id: "Remember code" })}</span>
</Caption>
</Checkbox>
<Button size="small" intent="primary" type="button">
{intl.formatMessage({ id: "Apply" })}
</Button>
</div>
</>
)
}

View File

@@ -6,6 +6,7 @@ import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { Tooltip } from "@/components/TempDesignSystem/Tooltip"
import BookingCode from "../BookingCode"
import Input from "../Input"
import styles from "./voucher.module.css"
@@ -13,11 +14,11 @@ import styles from "./voucher.module.css"
export default function Voucher() {
const intl = useIntl()
const vouchers = intl.formatMessage({ id: "Code / Voucher" })
const useVouchers = intl.formatMessage({ id: "Use code/voucher" })
const addVouchers = intl.formatMessage({ id: "Add code" })
const bonus = intl.formatMessage({ id: "Use bonus cheque" })
const reward = intl.formatMessage({ id: "Book reward night" })
// ToDo: Remove this when all three options are enabled
const disabledBookingOptionsHeader = intl.formatMessage({
id: "We're sorry",
})
@@ -27,55 +28,49 @@ export default function Voucher() {
return (
<div className={styles.optionsContainer}>
<Tooltip
heading={disabledBookingOptionsHeader}
text={disabledBookingOptionsText}
position="bottom"
arrow="left"
>
<div className={styles.vouchers}>
<label>
<Caption color="disabled" type="bold" asChild>
<span>{vouchers}</span>
<div className={styles.vouchers}>
<BookingCode />
</div>
<div className={styles.options}>
<div className={`${styles.option} ${styles.checkboxVoucher}`}>
<Checkbox name="useVouchers" registerOptions={{ disabled: true }}>
<Caption color="disabled" asChild>
<span>{useVouchers}</span>
</Caption>
{/* <InfoCircleIcon color="white" className={styles.infoIcon} /> Out of scope for this release */}
</label>
<Input type="text" placeholder={addVouchers} disabled />
</Checkbox>
{/* <InfoCircleIcon color="white" className={styles.infoIcon} /> Out of scope for this release */}
</div>
</Tooltip>
<Tooltip
heading={disabledBookingOptionsHeader}
text={disabledBookingOptionsText}
position="bottom"
arrow="left"
>
<div className={styles.options}>
<div className={`${styles.option} ${styles.checkboxVoucher}`}>
<Checkbox name="useVouchers" registerOptions={{ disabled: true }}>
<Caption color="disabled" asChild>
<span>{useVouchers}</span>
</Caption>
</Checkbox>
{/* <InfoCircleIcon color="white" className={styles.infoIcon} /> Out of scope for this release */}
</div>
<div className={styles.option}>
<div className={styles.option}>
<Tooltip
heading={disabledBookingOptionsHeader}
text={disabledBookingOptionsText}
position="bottom"
arrow="left"
>
<Checkbox name="useBonus" registerOptions={{ disabled: true }}>
<Caption color="disabled" asChild>
<span>{bonus}</span>
</Caption>
</Checkbox>
{/* <InfoCircleIcon color="white" className={styles.infoIcon} /> Out of scope for this release */}
</div>
<div className={styles.option}>
</Tooltip>
</div>
<div className={styles.option}>
<Tooltip
heading={disabledBookingOptionsHeader}
text={disabledBookingOptionsText}
position="bottom"
arrow="left"
>
<Checkbox name="useReward" registerOptions={{ disabled: true }}>
<Caption color="disabled" asChild>
<span>{reward}</span>
</Caption>
</Checkbox>
{/* <InfoCircleIcon color="white" className={styles.infoIcon} /> Out of scope for this release */}
</div>
</Tooltip>
</div>
</Tooltip>
</div>
</div>
)
}

View File

@@ -32,10 +32,6 @@
display: none;
}
.infoIcon {
stroke: var(--Base-Text-Disabled);
}
@media screen and (min-width: 768px) {
.vouchers {
display: none;

View File

@@ -86,6 +86,7 @@ export default function FormContent({
</Button>
</div>
</div>
{/* ToDo: Remove below additional voucher element which is only used in tablet mode better to have submit button twice instead */}
<div className={styles.voucherRow}>
<Voucher />
</div>

View File

@@ -44,10 +44,16 @@ export default function Form({
...(locationData.type == "cities"
? { city: locationData.name }
: { hotel: locationData.operaId || "" }),
...(data.bookingCode && data.bookingCode.value
? { bookingCode: data.bookingCode.value }
: {}),
})
onClose()
router.push(`${bookingFlowPage}?${bookingWidgetParams.toString()}`)
if (data.bookingCode?.remember) {
localStorage.setItem("bookingCode", JSON.stringify(data.bookingCode))
}
}
return (

View File

@@ -35,9 +35,30 @@ export const guestRoomSchema = z
export const guestRoomsSchema = z.array(guestRoomSchema)
export const bookingCodeSchema = z
.object({
value: z.string().refine(
(value) => {
if (
!value ||
/(^D\d*$)|(^DSH[0-9a-z]*$)|(^L\d*$)|(^LH[0-9a-z]*$)|(^B[a-z]{3}\d{6})|(^VO[0-9a-z]*$)|^[0-9a-z]*$/i.test(
value
)
) {
return true
} else {
return false
}
},
{ message: "Invalid booking code" }
),
remember: z.boolean(),
})
.optional()
export const bookingWidgetSchema = z
.object({
bookingCode: z.string(), // Update this as required when working with booking codes component
bookingCode: bookingCodeSchema,
date: z.object({
// Update this as required once started working with Date picker in Nights component
fromDate: z.string(),
@@ -70,7 +91,27 @@ export const bookingWidgetSchema = z
hotel: z.number().optional(),
city: z.string().optional(),
})
.refine((value) => value.hotel || value.city, {
message: "Destination required",
path: ["search"],
.superRefine((value, ctx) => {
if (!value.hotel && !value.city) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Destination required",
path: ["search"],
})
}
if (
value.rooms.length > 1 &&
value.bookingCode?.value.toLowerCase().startsWith("vo")
) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Multiroom with voucher error",
path: ["bookingCode.value"],
})
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Multiroom with voucher error",
path: ["rooms"],
})
}
})

View File

@@ -76,5 +76,6 @@
bottom: auto;
width: auto;
border-radius: var(--Corner-radius-Medium);
max-width: var(--max-width-page);
}
}

View File

@@ -38,6 +38,7 @@
"An error occurred when trying to update profile.": "Der opstod en fejl under forsøg på at opdatere profilen.",
"An error occurred. Please try again.": "Der opstod en fejl. Prøv venligst igen.",
"Any changes you've made will be lost.": "Alle ændringer, du har foretaget, går tabt.",
"Apply": "Vælg",
"Approx {value}.": "Ca. {value}",
"Approx.": "Ca.",
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Er du sikker på, at du vil fjerne kortet, der slutter me {lastFourDigits} fra din medlemsprofil?",
@@ -228,6 +229,7 @@
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
"Included": "Inkluderet",
"IndoorPool": "Indendørs pool",
"Invalid booking code": "Ugyldig reservationskode",
"Is there anything else you would like us to know before your arrival?": "Er der andet, du gerne vil have os til at vide, før din ankomst?",
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det er ikke muligt at administrere dine kommunikationspræferencer lige nu, prøv venligst igen senere eller kontakt support, hvis problemet fortsætter.",
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Det ser ud til, at ingen hoteller matcher dine filtre. Prøv at justere din søgning for at finde det perfekte ophold.",
@@ -290,6 +292,7 @@
"Mon-Fri {openingTime}-{closingTime}": "Man-Fre {openingTime}-{closingTime}",
"Monday": "Mandag",
"Month": "Måned",
"Multiroom with voucher error": "Det er ikke muligt at booke flere værelser med gavekort.",
"Museum": "Museum",
"Museums": "Museer",
"My communication preferences": "Mine kommunikationspræferencer",
@@ -391,6 +394,7 @@
"Redirecting you to my pages.": "Redirecting you to my pages.",
"Reference #{bookingNr}": "Reference #{bookingNr}",
"Relax": "Slap af",
"Remember code": "Husk kode",
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
"Request bedtype": "Anmod om sengetype",
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
@@ -562,6 +566,7 @@
"Zoom in": "Zoom ind",
"Zoom out": "Zoom ud",
"as of today": "pr. dags dato",
"booking.codes.information": "Hvis du bestiller et kampagnetilbud eller en firmaaftalepris, skal du bruge en bookingkode. Brug ikke specialtegn som (.) (,) (-) (:).Gem din bookingkode til næste gang du besøger siden ved at klikke “Husk bookingkode”. Vælg ikke dette, hvis du bruger en offentlig computer for at undgå uautoriseret anvendelse af din bookingkode.",
"booking.confirmation.text": "Tak fordi du bookede hos os! Vi glæder os til at byde dig velkommen og håber du får et behageligt ophold. Hvis du har spørgsmål eller har brug for at foretage ændringer i din reservation, bedes du <emailLink>kontakte os.</emailLink>",
"booking.confirmation.title": "Booking bekræftelse",
"booking.guests": "Maks {max, plural, one {{range} gæst} other {{range} gæster}}",

View File

@@ -38,6 +38,7 @@
"An error occurred when trying to update profile.": "Beim Versuch, das Profil zu aktualisieren, ist ein Fehler aufgetreten.",
"An error occurred. Please try again.": "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.",
"Any changes you've made will be lost.": "Alle Änderungen, die Sie vorgenommen haben, gehen verloren.",
"Apply": "Anwenden",
"Approx {value}.": "Ca. {value}",
"Approx.": "Ca.",
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Möchten Sie die Karte mit der Endung {lastFourDigits} wirklich aus Ihrem Mitgliedsprofil entfernen?",
@@ -227,6 +228,7 @@
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
"Included": "Iinklusive",
"IndoorPool": "Innenpool",
"Invalid booking code": "Ungültiger Buchungscode",
"Is there anything else you would like us to know before your arrival?": "Gibt es noch etwas, das Sie uns vor Ihrer Ankunft mitteilen möchten?",
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Es ist derzeit nicht möglich, Ihre Kommunikationseinstellungen zu verwalten. Bitte versuchen Sie es später erneut oder wenden Sie sich an den Support, wenn das Problem weiterhin besteht.",
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Es scheint, dass keine Hotels Ihren Filtern entsprechen. Versuchen Sie, Ihre Suche anzupassen, um den perfekten Aufenthalt zu finden.",
@@ -288,6 +290,7 @@
"Mon-Fri {openingTime}-{closingTime}": "Mo-Fr {openingTime}-{closingTime}",
"Monday": "Montag",
"Month": "Monat",
"Multiroom with voucher error": "Die Buchung mehrerer Zimmer ist nicht mit einem Gutschein möglich",
"Museum": "Museum",
"Museums": "Museen",
"My communication preferences": "Meine Kommunikationseinstellungen",
@@ -389,6 +392,7 @@
"Redirecting you to my pages.": "Redirecting you to my pages.",
"Reference #{bookingNr}": "Referenz #{bookingNr}",
"Relax": "Entspannen",
"Remember code": "Code merken",
"Remove card from member profile": "Karte aus dem Mitgliedsprofil entfernen",
"Request bedtype": "Bettentyp anfragen",
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
@@ -560,6 +564,7 @@
"Zoom in": "Vergrößern",
"Zoom out": "Verkleinern",
"as of today": "Stand heute",
"booking.codes.information": "Um ein Aktionsangebot oder einen Unternehmenstarif in Anspruch zu nehmen, benötigen Sie einen speziellen Buchungscode. Verwenden Sie keine Sonderzeichen wie (.) (,) (-) (:).Wählen Sie das Kästchen aus, um beim nächsten Besuch der Seite Ihren Buchungscode zu speichern. “Buchungscode speichern”. Deaktivieren Sie das Feld, wenn Sie einen öffentlich zugänglichen Computer verwenden, um unautorisierte Zugriffe auf Ihren Buchungscode zu verhindern.",
"booking.confirmation.text": "Vielen Dank, dass Sie bei uns gebucht haben! Wir freuen uns, Sie bei uns begrüßen zu dürfen und wünschen Ihnen einen angenehmen Aufenthalt. Wenn Sie Fragen haben oder Änderungen an Ihrer Buchung vornehmen müssen, <emailLink>kontaktieren Sie uns bitte.</emailLink>.",
"booking.confirmation.title": "Buchungsbestätigung",
"booking.guests": "Max {max, plural, one {{range} gast} other {{range} gäste}}",

View File

@@ -40,6 +40,7 @@
"An error occurred when trying to update profile.": "An error occurred when trying to update profile.",
"An error occurred. Please try again.": "An error occurred. Please try again.",
"Any changes you've made will be lost.": "Any changes you've made will be lost.",
"Apply": "Apply",
"Approx.": "Approx.",
"Approx. {value}": "Approx. {value}",
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?",
@@ -249,6 +250,7 @@
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
"Included": "Included",
"IndoorPool": "Indoor pool",
"Invalid booking code": "Invalid booking code",
"Is there anything else you would like us to know before your arrival?": "Is there anything else you would like us to know before your arrival?",
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.",
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
@@ -318,6 +320,7 @@
"Mon-Fri {openingTime}-{closingTime}": "Mon-Fri {openingTime}-{closingTime}",
"Monday": "Monday",
"Month": "Month",
"Multiroom with voucher error": "Multiroom booking is not compatible with a code or voucher",
"Museum": "Museum",
"Museums": "Museums",
"My communication preferences": "My communication preferences",
@@ -433,7 +436,9 @@
"Redirecting you to my pages.": "Redirecting you to my pages.",
"Reference #{bookingNr}": "Reference #{bookingNr}",
"Relax": "Relax",
"Remember code": "Remember code",
"Remove card from member profile": "Remove card from member profile",
"Remove room": "Remove room",
"Request bedtype": "Request bedtype",
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
"Reservation number {value}": "Reservation number {value}",
@@ -616,6 +621,7 @@
"Zoom in": "Zoom in",
"Zoom out": "Zoom out",
"as of today": "as of today",
"booking.codes.information": "If you're booking a promotional offer or a Corporate negotiated rate you'll need a special booking code. Don't use any special characters such as (.) (,) (-) (:). If you would like to make a booking with code VOF, please call us +46 8 517 517 20.Save your booking code for the next time you visit the page by ticking the box “Remember”. Don't tick the box if you're using a public computer to avoid unauthorized access to your booking code.",
"booking.selectRoom": "Select room",
"booking.thisRoomIsEquippedWith": "This room is equipped with",
"friday": "friday",

View File

@@ -38,6 +38,7 @@
"An error occurred when trying to update profile.": "Profiilia päivitettäessä tapahtui virhe.",
"An error occurred. Please try again.": "Tapahtui virhe. Yritä uudelleen.",
"Any changes you've made will be lost.": "Kaikki tekemäsi muutokset menetetään.",
"Apply": "Tallenna",
"Approx.": "N.",
"Approx. {value}": "N. {value}",
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Haluatko varmasti poistaa kortin, joka päättyy numeroon {lastFourDigits} jäsenprofiilistasi?",
@@ -228,6 +229,7 @@
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
"Included": "Sisälly hintaan",
"IndoorPool": "Sisäuima-allas",
"Invalid booking code": "Virheellinen varauskoodi",
"Is there anything else you would like us to know before your arrival?": "Onko jotain muuta, mitä haluaisit meidän tietävän ennen saapumistasi?",
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Viestintäasetuksiasi ei voi hallita juuri nyt. Yritä myöhemmin uudelleen tai ota yhteyttä tukeen, jos ongelma jatkuu.",
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Näyttää siltä, että mikään hotelli ei vastaa suodattimiasi. Yritä muokata hakuasi löytääksesi täydellisen oleskelun.",
@@ -290,6 +292,7 @@
"Mon-Fri {openingTime}-{closingTime}": "Ma-Pe {openingTime}-{closingTime}",
"Monday": "Maanantai",
"Month": "Kuukausi",
"Multiroom with voucher error": "Lahjakortilla ei voi varata monta huonetta",
"Museum": "Museo",
"Museums": "Museot",
"My communication preferences": "Viestintämieltymykseni",
@@ -391,6 +394,7 @@
"Redirecting you to my pages.": "Redirecting you to my pages.",
"Reference #{bookingNr}": "Referenssi #{bookingNr}",
"Relax": "Rentoutua",
"Remember code": "Muista koodi",
"Remove card from member profile": "Poista kortti jäsenprofiilista",
"Request bedtype": "Pyydä sänkytyyppiä",
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
@@ -560,6 +564,7 @@
"Zoom in": "Lähennä",
"Zoom out": "Loitonna",
"as of today": "tänään",
"booking.codes.information": "Jos varaat tarjoushinnalla tai yrityksen sopimushinnalla, tarvitset varauskoodin. Älä käytä erikoismerkkejä, kuten (.) (,) (-) (:).Jos haluat tallentaa varauskoodisi seuraavaa varausta varten, rastita tämä ruutu. Älä rastita ruutua, mikäli käytät yleistä tietokonetta ja haluat välttää varauskoodin väärinkäyttöä.",
"booking.confirmation.text": "Kiitos, että teit varauksen meiltä! Toivotamme sinut tervetulleeksi ja toivomme sinulle miellyttävää oleskelua. Jos sinulla on kysyttävää tai haluat tehdä muutoksia varaukseesi, <emailLink>ota meihin yhteyttä.</emailLink>",
"booking.confirmation.title": "Varausvahvistus",
"booking.guests": "Max {max, plural, one {{range} vieras} other {{range} vieraita}}",

View File

@@ -38,6 +38,7 @@
"An error occurred when trying to update profile.": "Det oppstod en feil under forsøk på å oppdatere profilen.",
"An error occurred. Please try again.": "Det oppsto en feil. Vennligst prøv igjen.",
"Any changes you've made will be lost.": "Eventuelle endringer du har gjort, går tapt.",
"Apply": "Velg",
"Approx.": "Ca.",
"Approx. {value}": "Ca. {value}",
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Er du sikker på at du vil fjerne kortet som slutter på {lastFourDigits} fra medlemsprofilen din?",
@@ -227,6 +228,7 @@
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
"Included": "Inkludert",
"IndoorPool": "Innendørs basseng",
"Invalid booking code": "Ugyldig bookingkode",
"Is there anything else you would like us to know before your arrival?": "Er det noe annet du vil at vi skal vite før ankomsten din?",
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det er ikke mulig å administrere kommunikasjonspreferansene dine akkurat nå, prøv igjen senere eller kontakt support hvis problemet vedvarer.",
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Det ser ut til at ingen hoteller samsvarer med filtrene dine. Prøv å justere søket for å finne det perfekte oppholdet.",
@@ -289,6 +291,7 @@
"Mon-Fri {openingTime}-{closingTime}": "Man-Fre {openingTime}-{closingTime}",
"Monday": "Mandag",
"Month": "Måned",
"Multiroom with voucher error": "Bestilling av flere rom er ikke mulig når du bestiller med voucher",
"Museum": "Museum",
"Museums": "Museums",
"My communication preferences": "Mine kommunikasjonspreferanser",
@@ -390,6 +393,7 @@
"Redirecting you to my pages.": "Redirecting you to my pages.",
"Reference #{bookingNr}": "Referanse #{bookingNr}",
"Relax": "Slappe av",
"Remember code": "Husk kode",
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
"Request bedtype": "Be om sengetype",
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
@@ -561,6 +565,7 @@
"Zoom in": "Zoom inn",
"Zoom out": "Zoom ut",
"as of today": "per i dag",
"booking.codes.information": "Om du bestiller et tilbud eller en avtalepris kreves en spesiell bookingkode. Ikke benytt spesialtegn som (.) (,) (-) (:). Lagre din bookingkode til neste gang du besøker siden ved å klikke på \"Husk\". Klikk ikke på \"Husk\" dersom du bruker en offentlig datamaskin, da uvedkommede kan få tilgang til din bookingkode.",
"booking.confirmation.text": "Takk for at du booket hos oss! Vi ser frem til å ønske deg velkommen og håper du får et hyggelig opphold. Hvis du har spørsmål eller trenger å gjøre endringer i bestillingen din, vennligst <emailLink>kontakt oss.</emailLink>",
"booking.confirmation.title": "Bestillingsbekreftelse",
"booking.guests": "Maks {max, plural, one {{range} gjest} other {{range} gjester}}",

View File

@@ -38,6 +38,7 @@
"An error occurred when trying to update profile.": "Ett fel uppstod när du försökte uppdatera profilen.",
"An error occurred. Please try again.": "Ett fel uppstod. Försök igen.",
"Any changes you've made will be lost.": "Alla ändringar du har gjort kommer att gå förlorade.",
"Apply": "Tillämpa",
"Approx.": "Ca.",
"Approx. {value}": "Ca. {value}",
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Är du säker på att du vill ta bort kortet som slutar med {lastFourDigits} från din medlemsprofil?",
@@ -227,6 +228,7 @@
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
"Included": "Inkluderad",
"IndoorPool": "Inomhuspool",
"Invalid booking code": "Ogiltig bokningskod",
"Is there anything else you would like us to know before your arrival?": "Är det något mer du vill att vi ska veta innan din ankomst?",
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det gick inte att hantera dina kommunikationsinställningar just nu, försök igen senare eller kontakta supporten om problemet kvarstår.",
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Det verkar som att inga hotell matchar dina filter. Prova att justera din sökning för att hitta den perfekta vistelsen.",
@@ -289,6 +291,7 @@
"Mon-Fri {openingTime}-{closingTime}": "Mån-Fre {openingTime}-{closingTime}",
"Monday": "Måndag",
"Month": "Månad",
"Multiroom with voucher error": "Flera rum kan inte bokas samtidigt med presentkort",
"Museum": "Museum",
"Museums": "Museer",
"My communication preferences": "Mina kommunikationspreferenser",
@@ -390,6 +393,7 @@
"Redirecting you to my pages.": "Redirecting you to my pages.",
"Reference #{bookingNr}": "Referens #{bookingNr}",
"Relax": "Koppla av",
"Remember code": "Kom ihåg kod",
"Remove card from member profile": "Ta bort kortet från medlemsprofilen",
"Request bedtype": "Request bedtype",
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
@@ -561,6 +565,7 @@
"Zoom in": "Zooma in",
"Zoom out": "Zooma ut",
"as of today": "från och med idag",
"booking.codes.information": "Om du bokar ett erbjudande eller avtalspris krävs en särskild bokningskod. Använd inga specialtecken som (.) (,) (-) (:). För bokning med koden VOF ber vi dig ringa oss 08-517 517 00.Spara din bokningskod till nästa gång du besöker sidan, genom att klicka i rutan \"Kom ihåg\". Klicka inte i rutan om du använder en allmän dator, då kan obehöriga komma åt din bokningskod.",
"booking.confirmation.text": "Tack för att du bokar hos oss! Vi ser fram emot att välkomna dig och hoppas att du får en trevlig vistelse. Om du har några frågor eller behöver göra ändringar i din bokning, vänligen <emailLink>kontakta oss.</emailLink>",
"booking.confirmation.title": "Bokningsbekräftelse",
"booking.guests": "Max {max, plural, one {{range} gäst} other {{range} gäster}}",

View File

@@ -3,11 +3,15 @@ import type { z } from "zod"
import type { SearchParams } from "@/types/params"
import type { Locations } from "@/types/trpc/routers/hotel/locations"
import type { bookingWidgetSchema } from "@/components/Forms/BookingWidget/schema"
import type {
bookingCodeSchema,
bookingWidgetSchema,
} from "@/components/Forms/BookingWidget/schema"
import type { bookingWidgetVariants } from "@/components/Forms/BookingWidget/variants"
import type { TGuestsRoom } from "./guestsRoomsPicker"
export type BookingWidgetSchema = z.output<typeof bookingWidgetSchema>
export type BookingCodeSchema = z.output<typeof bookingCodeSchema>
export type BookingWidgetSearchData = {
city?: string
@@ -15,6 +19,7 @@ export type BookingWidgetSearchData = {
fromDate?: string
toDate?: string
rooms?: TGuestsRoom[]
bookingCode?: string
}
export type BookingWidgetType = VariantProps<