chore(SW-3321): Moved Select rate context to booking-flow package * chore(SW-3321): Moved Select rate context to booking-flow package * chore(SW-3321): Optimised code Approved-by: Joakim Jäderberg
144 lines
3.9 KiB
TypeScript
144 lines
3.9 KiB
TypeScript
import { type Dayjs, dt } from "@scandic-hotels/common/dt"
|
|
import {
|
|
MaterialIcon,
|
|
type MaterialIconSetIconProps,
|
|
} from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
|
|
import { ChildBedTypeEnum } from "@scandic-hotels/trpc/enums/childBedTypeEnum"
|
|
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
|
|
|
import type { Package, Packages } from "@scandic-hotels/trpc/types/packages"
|
|
import type { JSX } from "react"
|
|
|
|
import type { RoomPackageCodes } from "../../types/components/selectRate/roomFilter"
|
|
|
|
interface IconForFeatureCodeProps {
|
|
featureCode: RoomPackageCodes
|
|
}
|
|
export function IconForFeatureCode({
|
|
featureCode,
|
|
...props
|
|
}: IconForFeatureCodeProps & MaterialIconSetIconProps): JSX.Element {
|
|
switch (featureCode) {
|
|
case RoomPackageCodeEnum.ACCESSIBILITY_ROOM:
|
|
return <MaterialIcon icon="accessible" {...props} />
|
|
case RoomPackageCodeEnum.ALLERGY_ROOM:
|
|
return <MaterialIcon icon="mode_fan" {...props} />
|
|
case RoomPackageCodeEnum.PET_ROOM:
|
|
default:
|
|
return <MaterialIcon icon="pets" {...props} />
|
|
}
|
|
}
|
|
|
|
export const invertedBedTypeMap: Record<ChildBedTypeEnum, string> = {
|
|
[ChildBedTypeEnum.ParentsBed]: ChildBedMapEnum[ChildBedMapEnum.IN_ADULTS_BED],
|
|
[ChildBedTypeEnum.Crib]: ChildBedMapEnum[ChildBedMapEnum.IN_CRIB],
|
|
[ChildBedTypeEnum.ExtraBed]: ChildBedMapEnum[ChildBedMapEnum.IN_EXTRA_BED],
|
|
[ChildBedTypeEnum.Unknown]: ChildBedMapEnum[ChildBedMapEnum.UNKNOWN],
|
|
}
|
|
|
|
export function sumPackages(
|
|
packages: Pick<Package, "localPrice">[] | undefined | null
|
|
) {
|
|
if (!packages || !packages.length) {
|
|
return {
|
|
currency: undefined,
|
|
price: 0,
|
|
}
|
|
}
|
|
return packages.reduce(
|
|
(total, pkg) => {
|
|
total.price = total.price + pkg.localPrice.totalPrice
|
|
return total
|
|
},
|
|
{
|
|
currency: packages[0].localPrice.currency,
|
|
price: 0,
|
|
}
|
|
)
|
|
}
|
|
|
|
export function sumPackagesRequestedPrice(packages: Packages | null) {
|
|
if (!packages || !packages.length) {
|
|
return {
|
|
currency: undefined,
|
|
price: 0,
|
|
}
|
|
}
|
|
return packages.reduce(
|
|
(total, pkg) => {
|
|
total.price = total.price + pkg.requestedPrice.totalPrice
|
|
return total
|
|
},
|
|
{
|
|
currency: packages[0].requestedPrice.currency,
|
|
price: 0,
|
|
}
|
|
)
|
|
}
|
|
|
|
export function calculateVat(priceInclVat: number, vat: number) {
|
|
const vatPercentage = vat / 100
|
|
const priceExclVat = priceInclVat / (1 + vatPercentage)
|
|
const vatAmount = priceInclVat - priceExclVat
|
|
return {
|
|
priceExclVat,
|
|
vatAmount,
|
|
}
|
|
}
|
|
|
|
export function filterOverlappingDates<
|
|
T extends {
|
|
startDate: Date | Dayjs | string | undefined | null
|
|
endDate: Date | Dayjs | string | undefined | null
|
|
},
|
|
>(dateRangeItems: T[], fromDate: Date | Dayjs, toDate: Date | Dayjs) {
|
|
const startDate = dt(fromDate)
|
|
const endDate = dt(toDate)
|
|
|
|
return dateRangeItems.filter((item) =>
|
|
hasOverlappingDates(item, startDate, endDate)
|
|
)
|
|
}
|
|
|
|
export function hasOverlappingDates(
|
|
dateRangeItem: {
|
|
startDate: Date | Dayjs | string | undefined | null
|
|
endDate: Date | Dayjs | string | undefined | null
|
|
},
|
|
fromDate: Date | Dayjs,
|
|
toDate: Date | Dayjs
|
|
) {
|
|
const startDate = dt(fromDate)
|
|
const endDate = dt(toDate)
|
|
|
|
if (dateRangeItem.endDate && dateRangeItem.startDate) {
|
|
const itemStartDate = dt(dateRangeItem.startDate)
|
|
const itemEndDate = dt(dateRangeItem.endDate)
|
|
|
|
const fromDateIsBetweenItemDates = startDate.isBetween(
|
|
itemStartDate,
|
|
itemEndDate,
|
|
"date",
|
|
"[]"
|
|
)
|
|
const toDateIsBetweenItemDates = endDate.isBetween(
|
|
itemStartDate,
|
|
itemEndDate,
|
|
"date",
|
|
"[]"
|
|
)
|
|
|
|
const itemFullyContained =
|
|
startDate.isSameOrBefore(itemStartDate, "date") &&
|
|
endDate.isSameOrAfter(itemEndDate, "date")
|
|
|
|
return (
|
|
fromDateIsBetweenItemDates ||
|
|
toDateIsBetweenItemDates ||
|
|
itemFullyContained
|
|
)
|
|
}
|
|
return true
|
|
}
|