Merged in feat/sw-1688-list-breakfast (pull request #1615)
Feat/sw-1688 list breakfast Approved-by: Pontus Dreij
This commit is contained in:
@@ -80,7 +80,7 @@ export default function Breakfast() {
|
|||||||
ancillary={{
|
ancillary={{
|
||||||
title: intl.formatMessage({ id: "Breakfast buffet" }),
|
title: intl.formatMessage({ id: "Breakfast buffet" }),
|
||||||
price: {
|
price: {
|
||||||
total: pkg.localPrice.price,
|
totalPrice: pkg.localPrice.price,
|
||||||
currency: pkg.localPrice.currency,
|
currency: pkg.localPrice.currency,
|
||||||
included:
|
included:
|
||||||
pkg.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST,
|
pkg.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST,
|
||||||
@@ -100,7 +100,7 @@ export default function Breakfast() {
|
|||||||
ancillary={{
|
ancillary={{
|
||||||
title: intl.formatMessage({ id: "No breakfast" }),
|
title: intl.formatMessage({ id: "No breakfast" }),
|
||||||
price: {
|
price: {
|
||||||
total: 0,
|
totalPrice: 0,
|
||||||
currency: packages?.[0].localPrice.currency ?? "",
|
currency: packages?.[0].localPrice.currency ?? "",
|
||||||
},
|
},
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default function PriceSummary({
|
|||||||
label={intl.formatMessage({ id: "Price including VAT" })}
|
label={intl.formatMessage({ id: "Price including VAT" })}
|
||||||
value={formatPrice(
|
value={formatPrice(
|
||||||
intl,
|
intl,
|
||||||
selectedAncillary.price.total,
|
selectedAncillary.price.totalPrice,
|
||||||
selectedAncillary.price.currency
|
selectedAncillary.price.currency
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default function PriceDetails({
|
|||||||
}
|
}
|
||||||
const totalPrice =
|
const totalPrice =
|
||||||
quantityWithCard && selectedAncillary
|
quantityWithCard && selectedAncillary
|
||||||
? selectedAncillary.price.total * quantityWithCard
|
? selectedAncillary.price.totalPrice * quantityWithCard
|
||||||
: null
|
: null
|
||||||
|
|
||||||
const totalPoints =
|
const totalPoints =
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import Select from "@/components/TempDesignSystem/Form/Select"
|
|||||||
import styles from "./selectQuantityStep.module.css"
|
import styles from "./selectQuantityStep.module.css"
|
||||||
|
|
||||||
import type { SelectQuantityStepProps } from "@/types/components/myPages/myStay/ancillaries"
|
import type { SelectQuantityStepProps } from "@/types/components/myPages/myStay/ancillaries"
|
||||||
|
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||||
|
|
||||||
export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
@@ -46,6 +47,13 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
|||||||
? intl.formatMessage({ id: "Insufficient points" })
|
? intl.formatMessage({ id: "Insufficient points" })
|
||||||
: intl.formatMessage({ id: "Select quantity" })
|
: intl.formatMessage({ id: "Select quantity" })
|
||||||
|
|
||||||
|
// TODO: Remove this when add breakfast is implemented
|
||||||
|
if (
|
||||||
|
selectedAncillary?.id === BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST
|
||||||
|
) {
|
||||||
|
return "Breakfast TBI"
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.selectContainer}>
|
<div className={styles.selectContainer}>
|
||||||
{selectedAncillary?.points && user && (
|
{selectedAncillary?.points && user && (
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import Steps from "./Steps"
|
|||||||
import styles from "./addAncillaryFlowModal.module.css"
|
import styles from "./addAncillaryFlowModal.module.css"
|
||||||
|
|
||||||
import type { AddAncillaryFlowModalProps } from "@/types/components/myPages/myStay/ancillaries"
|
import type { AddAncillaryFlowModalProps } from "@/types/components/myPages/myStay/ancillaries"
|
||||||
|
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||||
|
|
||||||
export default function AddAncillaryFlowModal({
|
export default function AddAncillaryFlowModal({
|
||||||
booking,
|
booking,
|
||||||
@@ -218,6 +219,7 @@ export default function AddAncillaryFlowModal({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalTitle =
|
const modalTitle =
|
||||||
currentStep === AncillaryStepEnum.selectAncillary
|
currentStep === AncillaryStepEnum.selectAncillary
|
||||||
? intl.formatMessage({ id: "Upgrade your stay" })
|
? intl.formatMessage({ id: "Upgrade your stay" })
|
||||||
@@ -251,7 +253,7 @@ export default function AddAncillaryFlowModal({
|
|||||||
<p>
|
<p>
|
||||||
{formatPrice(
|
{formatPrice(
|
||||||
intl,
|
intl,
|
||||||
selectedAncillary.price.total,
|
selectedAncillary.price.totalPrice,
|
||||||
selectedAncillary.price.currency
|
selectedAncillary.price.currency
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
@@ -290,7 +292,10 @@ export default function AddAncillaryFlowModal({
|
|||||||
<Steps user={user} savedCreditCards={savedCreditCards} />
|
<Steps user={user} savedCreditCards={savedCreditCards} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{currentStep === AncillaryStepEnum.selectAncillary ? null : (
|
{/* TODO: Remove the berakfast check when add breakfast is implemented */}
|
||||||
|
{currentStep === AncillaryStepEnum.selectAncillary ||
|
||||||
|
selectedAncillary?.id ===
|
||||||
|
BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST ? null : (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
currentStep === AncillaryStepEnum.confirmation
|
currentStep === AncillaryStepEnum.confirmation
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import { useMemo } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { Carousel } from "@/components/Carousel"
|
import { Carousel } from "@/components/Carousel"
|
||||||
@@ -17,46 +18,145 @@ import type {
|
|||||||
Ancillaries,
|
Ancillaries,
|
||||||
AncillariesProps,
|
AncillariesProps,
|
||||||
Ancillary,
|
Ancillary,
|
||||||
|
SelectedAncillary,
|
||||||
} from "@/types/components/myPages/myStay/ancillaries"
|
} from "@/types/components/myPages/myStay/ancillaries"
|
||||||
|
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||||
|
import type { User } from "@/types/user"
|
||||||
|
|
||||||
|
function filterPoints(ancillaries: Ancillaries, user: User | null) {
|
||||||
|
return ancillaries.map((ancillary) => {
|
||||||
|
return {
|
||||||
|
...ancillary,
|
||||||
|
ancillaryContent: ancillary.ancillaryContent.map(
|
||||||
|
({ points, ...ancillary }) => ({
|
||||||
|
...ancillary,
|
||||||
|
points: user ? points : undefined,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateUniqueAncillaries(
|
||||||
|
ancillaries: Ancillaries
|
||||||
|
): Ancillary["ancillaryContent"] {
|
||||||
|
const uniqueAncillaries = new Map(
|
||||||
|
ancillaries.flatMap((a) => {
|
||||||
|
return a.ancillaryContent.map((ancillary) => [ancillary.id, ancillary])
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return [...uniqueAncillaries.values()]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the breakfast package to the ancillaries
|
||||||
|
*
|
||||||
|
* Returns the ancillaries array with the breakfast package added to the
|
||||||
|
* specified category. If the category doesn't exist it's created.
|
||||||
|
*/
|
||||||
|
function addBreakfastPackage(
|
||||||
|
ancillaries: Ancillaries,
|
||||||
|
breakfast: SelectedAncillary | undefined,
|
||||||
|
categoryName: string
|
||||||
|
): Ancillaries {
|
||||||
|
if (!breakfast) return ancillaries
|
||||||
|
|
||||||
|
const category = ancillaries.find((a) => a.categoryName === categoryName)
|
||||||
|
|
||||||
|
if (category) {
|
||||||
|
const newCategory = {
|
||||||
|
...category,
|
||||||
|
ancillaryContent: [breakfast, ...category.ancillaryContent],
|
||||||
|
}
|
||||||
|
|
||||||
|
return ancillaries.map((ancillary) =>
|
||||||
|
ancillary.categoryName === categoryName ? newCategory : ancillary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return [{ categoryName, ancillaryContent: [breakfast] }, ...ancillaries]
|
||||||
|
}
|
||||||
|
|
||||||
export function Ancillaries({
|
export function Ancillaries({
|
||||||
ancillaries,
|
ancillaries,
|
||||||
booking,
|
booking,
|
||||||
|
packages,
|
||||||
user,
|
user,
|
||||||
savedCreditCards,
|
savedCreditCards,
|
||||||
refId,
|
refId,
|
||||||
}: AncillariesProps) {
|
}: AncillariesProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A constructed ancillary for breakfast
|
||||||
|
*
|
||||||
|
* This is a "fake" ancillary for breakfast, since breakfast isn't really an
|
||||||
|
* ancillary in the system. This makes it play nicely with the add ancillary
|
||||||
|
* flow. If the user shouldn't be able to add breakfast this will be `undefined`.
|
||||||
|
*/
|
||||||
|
const breakfastAncillary = useMemo(() => {
|
||||||
|
// This is the logic deciding if breakfast should be addable or not
|
||||||
|
if (
|
||||||
|
booking.rateDefinition.breakfastIncluded ||
|
||||||
|
booking.packages.some((p) =>
|
||||||
|
Object.values(BreakfastPackageEnum).includes(
|
||||||
|
p.code as unknown as BreakfastPackageEnum
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const breakfastPackage = packages?.find(
|
||||||
|
(p) => p.code === BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST
|
||||||
|
)
|
||||||
|
|
||||||
|
const breakfastAncillary: SelectedAncillary | undefined = breakfastPackage
|
||||||
|
? {
|
||||||
|
description: intl.formatMessage({ id: "Buffet" }),
|
||||||
|
id: breakfastPackage.code,
|
||||||
|
title: intl.formatMessage({ id: "Breakfast" }),
|
||||||
|
price: breakfastPackage.localPrice,
|
||||||
|
// TODO: Change this to the correct URL, whatever that is
|
||||||
|
imageUrl:
|
||||||
|
"https://images-test.scandichotels.com/publishedmedia/hcf9hchiad7zrvlkc2pt/Breakfast_-_Scandic_Sweden_-_Free_to_use.jpg",
|
||||||
|
requiresDeliveryTime: false,
|
||||||
|
loyaltyCode: undefined,
|
||||||
|
points: undefined,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
return breakfastAncillary
|
||||||
|
}, [
|
||||||
|
booking.packages,
|
||||||
|
booking.rateDefinition.breakfastIncluded,
|
||||||
|
intl,
|
||||||
|
packages,
|
||||||
|
])
|
||||||
|
|
||||||
|
const allAncillaries = useMemo(() => {
|
||||||
|
if (!ancillaries?.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const withBreakfastPopular = addBreakfastPackage(
|
||||||
|
ancillaries,
|
||||||
|
breakfastAncillary,
|
||||||
|
"Popular"
|
||||||
|
)
|
||||||
|
const withBreakfastFood = addBreakfastPackage(
|
||||||
|
withBreakfastPopular,
|
||||||
|
breakfastAncillary,
|
||||||
|
"Food"
|
||||||
|
)
|
||||||
|
const filtered = filterPoints(withBreakfastFood, user)
|
||||||
|
return filtered
|
||||||
|
}, [ancillaries, breakfastAncillary, user])
|
||||||
|
|
||||||
if (!ancillaries?.length) {
|
if (!ancillaries?.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterPoints(ancillaries: Ancillaries) {
|
|
||||||
return ancillaries.map((ancillary) => {
|
|
||||||
return {
|
|
||||||
...ancillary,
|
|
||||||
ancillaryContent: ancillary.ancillaryContent.map(
|
|
||||||
({ points, ...ancillary }) => ({
|
|
||||||
...ancillary,
|
|
||||||
points: user ? points : undefined,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateUniqueAncillaries(
|
|
||||||
ancillaries: Ancillaries
|
|
||||||
): Ancillary["ancillaryContent"] {
|
|
||||||
const uniqueAncillaries = new Map(
|
|
||||||
ancillaries.flatMap((a) =>
|
|
||||||
a.ancillaryContent.map((ancillary) => [ancillary.id, ancillary])
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return [...uniqueAncillaries.values()]
|
|
||||||
}
|
|
||||||
const allAncillaries = filterPoints(ancillaries)
|
|
||||||
const uniqueAncillaries = generateUniqueAncillaries(allAncillaries)
|
const uniqueAncillaries = generateUniqueAncillaries(allAncillaries)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -77,7 +177,7 @@ export function Ancillaries({
|
|||||||
|
|
||||||
<div className={styles.mobileAncillaries}>
|
<div className={styles.mobileAncillaries}>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
<Carousel.Content className={styles.carouselContainer}>
|
<Carousel.Content>
|
||||||
{uniqueAncillaries.map((ancillary) => {
|
{uniqueAncillaries.map((ancillary) => {
|
||||||
return (
|
return (
|
||||||
<Carousel.Item key={ancillary.id}>
|
<Carousel.Item key={ancillary.id}>
|
||||||
@@ -86,8 +186,8 @@ export function Ancillaries({
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Carousel.Content>
|
</Carousel.Content>
|
||||||
<Carousel.Previous className={styles.navigationButton} />
|
<Carousel.Previous />
|
||||||
<Carousel.Next className={styles.navigationButton} />
|
<Carousel.Next />
|
||||||
<Carousel.Dots />
|
<Carousel.Dots />
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ export function SingleRoom({ bedType, image, hotel, user }: RoomProps) {
|
|||||||
const adultsAndChildrenMsg = [adultsMsg, childrenMsg].join(", ")
|
const adultsAndChildrenMsg = [adultsMsg, childrenMsg].join(", ")
|
||||||
|
|
||||||
const hasPackages = packages?.some((item) =>
|
const hasPackages = packages?.some((item) =>
|
||||||
Object.values(RoomPackageCodeEnum).includes(item.code)
|
Object.values(RoomPackageCodeEnum).includes(
|
||||||
|
item.code as RoomPackageCodeEnum
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -270,7 +272,7 @@ export function SingleRoom({ bedType, image, hotel, user }: RoomProps) {
|
|||||||
{packages!
|
{packages!
|
||||||
.filter((item) =>
|
.filter((item) =>
|
||||||
Object.values(RoomPackageCodeEnum).includes(
|
Object.values(RoomPackageCodeEnum).includes(
|
||||||
item.code
|
item.code as RoomPackageCodeEnum
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map((item) => item.description)
|
.map((item) => item.description)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { dt } from "@/lib/dt"
|
|||||||
import {
|
import {
|
||||||
getAncillaryPackages,
|
getAncillaryPackages,
|
||||||
getBookingConfirmation,
|
getBookingConfirmation,
|
||||||
|
getPackages,
|
||||||
getProfileSafely,
|
getProfileSafely,
|
||||||
getSavedPaymentCardsSafely,
|
getSavedPaymentCardsSafely,
|
||||||
} from "@/lib/trpc/memoizedRequests"
|
} from "@/lib/trpc/memoizedRequests"
|
||||||
@@ -33,6 +34,8 @@ import Rooms from "./Rooms"
|
|||||||
|
|
||||||
import styles from "./myStay.module.css"
|
import styles from "./myStay.module.css"
|
||||||
|
|
||||||
|
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||||
|
|
||||||
export async function MyStay({ refId }: { refId: string }) {
|
export async function MyStay({ refId }: { refId: string }) {
|
||||||
const value = decrypt(refId)
|
const value = decrypt(refId)
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@@ -58,6 +61,21 @@ export async function MyStay({ refId }: { refId: string }) {
|
|||||||
hotelId: hotel.operaId,
|
hotelId: hotel.operaId,
|
||||||
toDate: dt(booking.checkOutDate).format("YYYY-MM-DD"),
|
toDate: dt(booking.checkOutDate).format("YYYY-MM-DD"),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const packages = await getPackages({
|
||||||
|
startDate: dt(booking.checkInDate).format("YYYY-MM-DD"),
|
||||||
|
hotelId: hotel.operaId,
|
||||||
|
endDate: dt(booking.checkOutDate).format("YYYY-MM-DD"),
|
||||||
|
adults: booking.adults,
|
||||||
|
children: booking.childrenAges.length,
|
||||||
|
packageCodes: [
|
||||||
|
BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST,
|
||||||
|
BreakfastPackageEnum.ANCILLARY_CHILD_PAYING_BREAKFAST,
|
||||||
|
BreakfastPackageEnum.FREE_CHILD_BREAKFAST,
|
||||||
|
],
|
||||||
|
lang,
|
||||||
|
})
|
||||||
|
|
||||||
const supportedCards = hotel.merchantInformationData.cards
|
const supportedCards = hotel.merchantInformationData.cards
|
||||||
const savedCreditCards = await getSavedPaymentCardsSafely({
|
const savedCreditCards = await getSavedPaymentCardsSafely({
|
||||||
supportedCards,
|
supportedCards,
|
||||||
@@ -97,6 +115,7 @@ export async function MyStay({ refId }: { refId: string }) {
|
|||||||
<Ancillaries
|
<Ancillaries
|
||||||
ancillaries={ancillaryPackages}
|
ancillaries={ancillaryPackages}
|
||||||
booking={booking}
|
booking={booking}
|
||||||
|
packages={packages}
|
||||||
user={user}
|
user={user}
|
||||||
savedCreditCards={savedCreditCards}
|
savedCreditCards={savedCreditCards}
|
||||||
refId={refId}
|
refId={refId}
|
||||||
|
|||||||
@@ -230,7 +230,9 @@ export default function BookedRoomSidePeek({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{packages?.some((item) =>
|
{packages?.some((item) =>
|
||||||
Object.values(RoomPackageCodeEnum).includes(item.code)
|
Object.values(RoomPackageCodeEnum).includes(
|
||||||
|
item.code as RoomPackageCodeEnum
|
||||||
|
)
|
||||||
) && (
|
) && (
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<span className={styles.rowTitle}>
|
<span className={styles.rowTitle}>
|
||||||
@@ -244,7 +246,9 @@ export default function BookedRoomSidePeek({
|
|||||||
<p color="uiTextHighContrast">
|
<p color="uiTextHighContrast">
|
||||||
{packages
|
{packages
|
||||||
?.filter((item) =>
|
?.filter((item) =>
|
||||||
Object.values(RoomPackageCodeEnum).includes(item.code)
|
Object.values(RoomPackageCodeEnum).includes(
|
||||||
|
item.code as RoomPackageCodeEnum
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.map((item) => item.description)
|
.map((item) => item.description)
|
||||||
.join(", ")}
|
.join(", ")}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type { AncillaryCardProps } from "@/types/components/ancillaryCard"
|
|||||||
export function AncillaryCard({ ancillary }: AncillaryCardProps) {
|
export function AncillaryCard({ ancillary }: AncillaryCardProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
const priceMsg = `${formatPrice(intl, ancillary.price.total, ancillary.price.currency)} ${ancillary.price.text ?? ""}`
|
const priceMsg = `${formatPrice(intl, ancillary.price.totalPrice, ancillary.price.currency)} ${ancillary.price.text ?? ""}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.ancillaryCard}>
|
<article className={styles.ancillaryCard}>
|
||||||
|
|||||||
@@ -131,6 +131,7 @@
|
|||||||
"Breakfast included": "Morgenmad inkluderet",
|
"Breakfast included": "Morgenmad inkluderet",
|
||||||
"Breakfast is included.": "Morgenmad er inkluderet.",
|
"Breakfast is included.": "Morgenmad er inkluderet.",
|
||||||
"Breakfast selection in next step.": "Valg af morgenmad i næste trin.",
|
"Breakfast selection in next step.": "Valg af morgenmad i næste trin.",
|
||||||
|
"Buffet": "Buffet",
|
||||||
"Bus terminal": "Busstation",
|
"Bus terminal": "Busstation",
|
||||||
"Business": "Forretning",
|
"Business": "Forretning",
|
||||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Ved at acceptere <termsAndConditionsLink>vilkårene og betingelserne for Scandic Friends</termsAndConditionsLink>, forstår jeg, at mine personlige oplysninger vil blive behandlet i overensstemmelse med <privacyPolicy>Scandics privatlivspolitik</privacyPolicy>.",
|
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Ved at acceptere <termsAndConditionsLink>vilkårene og betingelserne for Scandic Friends</termsAndConditionsLink>, forstår jeg, at mine personlige oplysninger vil blive behandlet i overensstemmelse med <privacyPolicy>Scandics privatlivspolitik</privacyPolicy>.",
|
||||||
|
|||||||
@@ -132,6 +132,7 @@
|
|||||||
"Breakfast included": "Frühstück inbegriffen",
|
"Breakfast included": "Frühstück inbegriffen",
|
||||||
"Breakfast is included.": "Frühstück ist inbegriffen.",
|
"Breakfast is included.": "Frühstück ist inbegriffen.",
|
||||||
"Breakfast selection in next step.": "Frühstücksauswahl in nächsten Schritt.",
|
"Breakfast selection in next step.": "Frühstücksauswahl in nächsten Schritt.",
|
||||||
|
"Buffet": "Büfett",
|
||||||
"Bus terminal": "Bus terminal",
|
"Bus terminal": "Bus terminal",
|
||||||
"Business": "Geschäft",
|
"Business": "Geschäft",
|
||||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Mit der Annahme der <termsAndConditionsLink>Allgemeinen Geschäftsbedingungen für Scandic Friends</termsAndConditionsLink> erkläre ich mich damit einverstanden, dass meine persönlichen Daten in Übereinstimmung mit der <privacyPolicy>Datenschutzrichtlinie von Scandic verarbeitet werden</privacyPolicy>.",
|
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Mit der Annahme der <termsAndConditionsLink>Allgemeinen Geschäftsbedingungen für Scandic Friends</termsAndConditionsLink> erkläre ich mich damit einverstanden, dass meine persönlichen Daten in Übereinstimmung mit der <privacyPolicy>Datenschutzrichtlinie von Scandic verarbeitet werden</privacyPolicy>.",
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
"Breakfast included": "Breakfast included",
|
"Breakfast included": "Breakfast included",
|
||||||
"Breakfast is included.": "Breakfast is included.",
|
"Breakfast is included.": "Breakfast is included.",
|
||||||
"Breakfast selection in next step.": "Breakfast selection in next step.",
|
"Breakfast selection in next step.": "Breakfast selection in next step.",
|
||||||
|
"Buffet": "Buffet",
|
||||||
"Bus terminal": "Bus terminal",
|
"Bus terminal": "Bus terminal",
|
||||||
"Business": "Business",
|
"Business": "Business",
|
||||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.",
|
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.",
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
"Breakfast included": "Aamiainen sisältyy",
|
"Breakfast included": "Aamiainen sisältyy",
|
||||||
"Breakfast is included.": "Aamiainen sisältyy.",
|
"Breakfast is included.": "Aamiainen sisältyy.",
|
||||||
"Breakfast selection in next step.": "Aamiaisvalinta seuraavassa vaiheessa.",
|
"Breakfast selection in next step.": "Aamiaisvalinta seuraavassa vaiheessa.",
|
||||||
|
"Buffet": "Buffet",
|
||||||
"Bus terminal": "Bussiasema",
|
"Bus terminal": "Bussiasema",
|
||||||
"Business": "Business",
|
"Business": "Business",
|
||||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Kyllä, <termsAndConditionsLink>hyväksyn Scandic Friends -jäsenyyttä</termsAndConditionsLink> koskevat ehdot ja ymmärrän, että Scandic käsittelee henkilötietojani <privacyPolicy>Scandicin Tietosuojaselosteen mukaisesti</privacyPolicy>.",
|
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Kyllä, <termsAndConditionsLink>hyväksyn Scandic Friends -jäsenyyttä</termsAndConditionsLink> koskevat ehdot ja ymmärrän, että Scandic käsittelee henkilötietojani <privacyPolicy>Scandicin Tietosuojaselosteen mukaisesti</privacyPolicy>.",
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
"Breakfast included": "Frokost inkludert",
|
"Breakfast included": "Frokost inkludert",
|
||||||
"Breakfast is included.": "Frokost er inkludert.",
|
"Breakfast is included.": "Frokost er inkludert.",
|
||||||
"Breakfast selection in next step.": "Frokostvalg i neste steg.",
|
"Breakfast selection in next step.": "Frokostvalg i neste steg.",
|
||||||
|
"Buffet": "Buffet",
|
||||||
"Bus terminal": "Bussterminal",
|
"Bus terminal": "Bussterminal",
|
||||||
"Business": "Forretnings",
|
"Business": "Forretnings",
|
||||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Ved å akseptere <termsAndConditionsLink>vilkårene og betingelsene for Scandic Friends</termsAndConditionsLink>, er jeg inneforstått med at mine personopplysninger vil bli behandlet i samsvar med <privacyPolicy>Scandics personvernpolicy</privacyPolicy>.",
|
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Ved å akseptere <termsAndConditionsLink>vilkårene og betingelsene for Scandic Friends</termsAndConditionsLink>, er jeg inneforstått med at mine personopplysninger vil bli behandlet i samsvar med <privacyPolicy>Scandics personvernpolicy</privacyPolicy>.",
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
"Breakfast included": "Frukost ingår",
|
"Breakfast included": "Frukost ingår",
|
||||||
"Breakfast is included.": "Frukost ingår.",
|
"Breakfast is included.": "Frukost ingår.",
|
||||||
"Breakfast selection in next step.": "Frukostval i nästa steg.",
|
"Breakfast selection in next step.": "Frukostval i nästa steg.",
|
||||||
|
"Buffet": "Buffé",
|
||||||
"Bus terminal": "Bussterminal",
|
"Bus terminal": "Bussterminal",
|
||||||
"Business": "Business",
|
"Business": "Business",
|
||||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Genom att acceptera <termsAndConditionsLink>villkoren för Scandic Friends</termsAndConditionsLink> förstår jag att mina personuppgifter kommer att behandlas i enlighet med <privacyPolicy>Scandics Integritetspolicy</privacyPolicy>.",
|
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Genom att acceptera <termsAndConditionsLink>villkoren för Scandic Friends</termsAndConditionsLink> förstår jag att mina personuppgifter kommer att behandlas i enlighet med <privacyPolicy>Scandics Integritetspolicy</privacyPolicy>.",
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ export const ancillaryPackagesSchema = z
|
|||||||
description: item.descriptions.html,
|
description: item.descriptions.html,
|
||||||
imageUrl: item.images[0]?.imageSizes.small,
|
imageUrl: item.images[0]?.imageSizes.small,
|
||||||
price: {
|
price: {
|
||||||
total: item.variants.ancillary.price.totalPrice,
|
totalPrice: item.variants.ancillary.price.totalPrice,
|
||||||
currency: item.variants.ancillary.price.currency,
|
currency: item.variants.ancillary.price.currency,
|
||||||
},
|
},
|
||||||
points: item.variants.ancillaryLoyalty?.points,
|
points: item.variants.ancillaryLoyalty?.points,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { z } from "zod"
|
|||||||
import { imageSizesSchema } from "./image"
|
import { imageSizesSchema } from "./image"
|
||||||
|
|
||||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||||
|
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||||
import { PackageTypeEnum } from "@/types/enums/packages"
|
import { PackageTypeEnum } from "@/types/enums/packages"
|
||||||
|
|
||||||
// TODO: Remove optional and default when the API change has been deployed
|
// TODO: Remove optional and default when the API change has been deployed
|
||||||
@@ -41,7 +42,7 @@ export const ancillaryContentSchema = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const packageSchema = z.object({
|
export const packageSchema = z.object({
|
||||||
code: z.nativeEnum(RoomPackageCodeEnum),
|
code: z.nativeEnum({ ...RoomPackageCodeEnum, ...BreakfastPackageEnum }),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
inventories: z.array(inventorySchema),
|
inventories: z.array(inventorySchema),
|
||||||
itemCode: z.string().default(""),
|
itemCode: z.string().default(""),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export interface AncillaryCardProps {
|
|||||||
imageUrl: string
|
imageUrl: string
|
||||||
imageOpacity?: number
|
imageOpacity?: number
|
||||||
price: {
|
price: {
|
||||||
total: number
|
totalPrice: number
|
||||||
currency: string
|
currency: string
|
||||||
text?: string
|
text?: string
|
||||||
included?: boolean
|
included?: boolean
|
||||||
|
|||||||
@@ -2,14 +2,19 @@ import type { z } from "zod"
|
|||||||
|
|
||||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||||
import type { CreditCard, User } from "@/types/user"
|
import type { CreditCard, User } from "@/types/user"
|
||||||
import type { ancillaryPackagesSchema } from "@/server/routers/hotels/output"
|
import type {
|
||||||
|
ancillaryPackagesSchema,
|
||||||
|
packagesSchema,
|
||||||
|
} from "@/server/routers/hotels/output"
|
||||||
|
|
||||||
export type Ancillaries = z.output<typeof ancillaryPackagesSchema>
|
export type Ancillaries = z.output<typeof ancillaryPackagesSchema>
|
||||||
export type Ancillary = Ancillaries[number]
|
export type Ancillary = Ancillaries[number]
|
||||||
export type SelectedAncillary = Ancillary["ancillaryContent"][number]
|
export type SelectedAncillary = Ancillary["ancillaryContent"][number]
|
||||||
|
export type Packages = z.output<typeof packagesSchema>
|
||||||
|
|
||||||
export interface AncillariesProps extends Pick<BookingConfirmation, "booking"> {
|
export interface AncillariesProps extends Pick<BookingConfirmation, "booking"> {
|
||||||
ancillaries: Ancillaries | null
|
ancillaries: Ancillaries | null
|
||||||
|
packages: Packages | null
|
||||||
user: User | null
|
user: User | null
|
||||||
savedCreditCards: CreditCard[] | null
|
savedCreditCards: CreditCard[] | null
|
||||||
refId: string
|
refId: string
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
export enum BreakfastPackageEnum {
|
export enum BreakfastPackageEnum {
|
||||||
FREE_MEMBER_BREAKFAST = "BRF0",
|
FREE_MEMBER_BREAKFAST = "BRF0",
|
||||||
|
FREE_CHILD_BREAKFAST = "BRFINF",
|
||||||
REGULAR_BREAKFAST = "BRF1",
|
REGULAR_BREAKFAST = "BRF1",
|
||||||
SPECIAL_PACKAGE_BREAKFAST = "F01S",
|
SPECIAL_PACKAGE_BREAKFAST = "F01S",
|
||||||
|
ANCILLARY_REGULAR_BREAKFAST = "BRF2",
|
||||||
|
ANCILLARY_CHILD_PAYING_BREAKFAST = "BRF2C",
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user