fix/SW-902-update-response-city-availability (pull request #917)
Fix/SW-902 update response city availability * fix(SW-902): update response for API changes * fix(SW-902): add total row for pricePerStay * fix(SW-902): fix optional requestedPrice * fix(SW-902): fix bookingCode output * feat(SW-903): fix sorting Approved-by: Pontus Dreij Approved-by: Niclas Edenvin
This commit is contained in:
committed by
Joakim Jäderberg
parent
e078c59ac1
commit
d49e301634
@@ -71,20 +71,24 @@ export default async function SummaryPage({
|
||||
price: availability.memberRate.localPrice.pricePerStay,
|
||||
currency: availability.memberRate.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: availability.memberRate.requestedPrice.pricePerStay,
|
||||
currency: availability.memberRate.requestedPrice.currency,
|
||||
},
|
||||
euro: availability.memberRate.requestedPrice
|
||||
? {
|
||||
price: availability.memberRate.requestedPrice.pricePerStay,
|
||||
currency: availability.memberRate.requestedPrice.currency,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
: {
|
||||
local: {
|
||||
price: availability.publicRate.localPrice.pricePerStay,
|
||||
currency: availability.publicRate.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: availability.publicRate.requestedPrice.pricePerStay,
|
||||
currency: availability.publicRate.requestedPrice.currency,
|
||||
},
|
||||
euro: availability.publicRate.requestedPrice
|
||||
? {
|
||||
price: availability.publicRate.requestedPrice.pricePerStay,
|
||||
currency: availability.publicRate.requestedPrice.currency,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,8 +9,6 @@ import type {
|
||||
CategorizedFilters,
|
||||
Filter,
|
||||
} from "@/types/components/hotelReservation/selectHotel/hotelFilters"
|
||||
import type { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
|
||||
import { HotelListingEnum } from "@/types/enums/hotelListing"
|
||||
|
||||
const hotelSurroundingsFilterNames = [
|
||||
"Hotel surroundings",
|
||||
@@ -29,24 +27,8 @@ export async function fetchAvailableHotels(
|
||||
if (!availableHotels) throw new Error()
|
||||
|
||||
const language = getLang()
|
||||
const hotelMap = new Map<number, any>()
|
||||
|
||||
availableHotels.availability.forEach((hotel) => {
|
||||
const existingHotel = hotelMap.get(hotel.hotelId)
|
||||
if (existingHotel) {
|
||||
if (hotel.ratePlanSet === HotelListingEnum.RatePlanSet.PUBLIC) {
|
||||
existingHotel.bestPricePerNight.regularAmount =
|
||||
hotel.bestPricePerNight?.regularAmount
|
||||
} else if (hotel.ratePlanSet === HotelListingEnum.RatePlanSet.MEMBER) {
|
||||
existingHotel.bestPricePerNight.memberAmount =
|
||||
hotel.bestPricePerNight?.memberAmount
|
||||
}
|
||||
} else {
|
||||
hotelMap.set(hotel.hotelId, { ...hotel })
|
||||
}
|
||||
})
|
||||
|
||||
const hotels = Array.from(hotelMap.values()).map(async (hotel) => {
|
||||
const hotels = availableHotels.availability.map(async (hotel) => {
|
||||
const hotelData = await getHotelData({
|
||||
hotelId: hotel.hotelId.toString(),
|
||||
language,
|
||||
@@ -56,7 +38,7 @@ export async function fetchAvailableHotels(
|
||||
|
||||
return {
|
||||
hotelData: hotelData.data.attributes,
|
||||
price: hotel.bestPricePerNight,
|
||||
price: hotel.productType,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -80,7 +80,9 @@ export default function Summary({
|
||||
) || { local: 0, euro: 0 }
|
||||
|
||||
const roomsPriceLocal = room.localPrice.price + additionalPackageCost.local
|
||||
const roomsPriceEuro = room.euroPrice.price + additionalPackageCost.euro
|
||||
const roomsPriceEuro = room.euroPrice
|
||||
? room.euroPrice.price + additionalPackageCost.euro
|
||||
: undefined
|
||||
|
||||
useEffect(() => {
|
||||
setChosenBed(bedType)
|
||||
@@ -92,10 +94,15 @@ export default function Summary({
|
||||
price: roomsPriceLocal + parseInt(breakfast.localPrice.totalPrice),
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: roomsPriceEuro + parseInt(breakfast.requestedPrice.totalPrice),
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
euro:
|
||||
room.euroPrice && roomsPriceEuro
|
||||
? {
|
||||
price:
|
||||
roomsPriceEuro +
|
||||
parseInt(breakfast.requestedPrice.totalPrice),
|
||||
currency: room.euroPrice.currency,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
} else {
|
||||
setTotalPrice({
|
||||
@@ -103,10 +110,13 @@ export default function Summary({
|
||||
price: roomsPriceLocal,
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: roomsPriceEuro,
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
euro:
|
||||
room.euroPrice && roomsPriceEuro
|
||||
? {
|
||||
price: roomsPriceEuro,
|
||||
currency: room.euroPrice.currency,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
}
|
||||
}, [
|
||||
@@ -114,7 +124,7 @@ export default function Summary({
|
||||
breakfast,
|
||||
roomsPriceLocal,
|
||||
room.localPrice.currency,
|
||||
room.euroPrice.currency,
|
||||
room.euroPrice,
|
||||
roomsPriceEuro,
|
||||
setTotalPrice,
|
||||
])
|
||||
@@ -269,16 +279,18 @@ export default function Summary({
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}{" "}
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: intl.formatNumber(totalPrice.euro.price),
|
||||
currency: totalPrice.euro.currency,
|
||||
}
|
||||
)}
|
||||
</Caption>
|
||||
{totalPrice.euro && (
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}{" "}
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: intl.formatNumber(totalPrice.euro.price),
|
||||
currency: totalPrice.euro.currency,
|
||||
}
|
||||
)}
|
||||
</Caption>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Divider className={styles.bottomDivider} color="primaryLightSubtle" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
@@ -9,15 +10,14 @@ import styles from "../hotelPriceList.module.css"
|
||||
import type { PriceCardProps } from "@/types/components/hotelReservation/selectHotel/priceCardProps"
|
||||
|
||||
export default function HotelPriceCard({
|
||||
currency,
|
||||
memberAmount,
|
||||
regularAmount,
|
||||
productTypePrices,
|
||||
isMemberPrice = false,
|
||||
}: PriceCardProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<dl className={styles.priceCard}>
|
||||
{memberAmount && (
|
||||
{isMemberPrice && (
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="red">
|
||||
@@ -30,7 +30,7 @@ export default function HotelPriceCard({
|
||||
<dt>
|
||||
<Caption
|
||||
type="bold"
|
||||
color={memberAmount ? "red" : "uiTextHighContrast"}
|
||||
color={isMemberPrice ? "red" : "uiTextHighContrast"}
|
||||
>
|
||||
{intl.formatMessage({ id: "From" })}
|
||||
</Caption>
|
||||
@@ -39,15 +39,15 @@ export default function HotelPriceCard({
|
||||
<div className={styles.price}>
|
||||
<Subtitle
|
||||
type="two"
|
||||
color={memberAmount ? "red" : "uiTextHighContrast"}
|
||||
color={isMemberPrice ? "red" : "uiTextHighContrast"}
|
||||
>
|
||||
{memberAmount ? memberAmount : regularAmount}
|
||||
{productTypePrices.localPrice.pricePerNight}
|
||||
</Subtitle>
|
||||
<Body
|
||||
color={memberAmount ? "red" : "uiTextHighContrast"}
|
||||
color={isMemberPrice ? "red" : "uiTextHighContrast"}
|
||||
textTransform="bold"
|
||||
>
|
||||
{currency}
|
||||
{productTypePrices.localPrice.currency}
|
||||
<span className={styles.perNight}>
|
||||
/{intl.formatMessage({ id: "night" })}
|
||||
</span>
|
||||
@@ -55,17 +55,40 @@ export default function HotelPriceCard({
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
{/* TODO add correct local price when API change */}
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color={"disabled"}>
|
||||
{intl.formatMessage({ id: "Approx." })}
|
||||
</Caption>
|
||||
</dt>
|
||||
<dd>
|
||||
<Caption color="disabled"> - EUR</Caption>
|
||||
</dd>
|
||||
</div>
|
||||
{productTypePrices?.requestedPrice && (
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}
|
||||
</Caption>
|
||||
</dt>
|
||||
<dd>
|
||||
<Caption color={"uiTextMediumContrast"}>
|
||||
{productTypePrices.requestedPrice.pricePerNight}{" "}
|
||||
{productTypePrices.requestedPrice.currency}
|
||||
</Caption>
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{productTypePrices.localPrice.pricePerStay !==
|
||||
productTypePrices.localPrice.pricePerNight && (
|
||||
<>
|
||||
<Divider color="subtle" className={styles.divider} />
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Total" })}
|
||||
</Caption>
|
||||
</dt>
|
||||
<dd>
|
||||
<Caption color={"uiTextMediumContrast"}>
|
||||
{productTypePrices.localPrice.pricePerStay}{" "}
|
||||
{productTypePrices.localPrice.currency}
|
||||
</Caption>
|
||||
</dd>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</dl>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,17 @@
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.prices {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
max-width: 260px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: var(--Spacing-x-half) 0;
|
||||
}
|
||||
|
||||
.priceRow {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { useParams } from "next/dist/client/components/navigation"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { selectRate } from "@/constants/routes/hotelReservation"
|
||||
|
||||
import { ErrorCircleIcon } from "@/components/Icons"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import HotelPriceCard from "./HotelPriceCard"
|
||||
@@ -9,34 +15,52 @@ import styles from "./hotelPriceList.module.css"
|
||||
|
||||
import { HotelPriceListProps } from "@/types/components/hotelReservation/selectHotel/hotePriceListProps"
|
||||
|
||||
export default function HotelPriceList({ price }: HotelPriceListProps) {
|
||||
export default function HotelPriceList({
|
||||
price,
|
||||
hotelId,
|
||||
}: HotelPriceListProps) {
|
||||
const intl = useIntl()
|
||||
const params = useParams()
|
||||
const lang = params.lang as Lang
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.prices}>
|
||||
{price ? (
|
||||
<>
|
||||
<HotelPriceCard
|
||||
currency={price?.currency}
|
||||
regularAmount={price?.regularAmount}
|
||||
/>
|
||||
<HotelPriceCard
|
||||
currency={price?.currency}
|
||||
memberAmount={price?.memberAmount}
|
||||
/>
|
||||
{price.public && <HotelPriceCard productTypePrices={price.public} />}
|
||||
{price.member && (
|
||||
<HotelPriceCard productTypePrices={price.member} isMemberPrice />
|
||||
)}
|
||||
<Button
|
||||
asChild
|
||||
theme="base"
|
||||
intent="primary"
|
||||
size="small"
|
||||
className={styles.button}
|
||||
>
|
||||
<Link
|
||||
href={`${selectRate[lang]}?hotel=${hotelId}`}
|
||||
color="none"
|
||||
keepSearchParams
|
||||
>
|
||||
{intl.formatMessage({ id: "See rooms" })}
|
||||
</Link>
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<div className={styles.priceCard}>
|
||||
<div className={styles.noRooms}>
|
||||
<ErrorCircleIcon color="red" />
|
||||
<div>
|
||||
<ErrorCircleIcon color="red" />
|
||||
</div>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "There are no rooms available that match your request",
|
||||
id: "There are no rooms available that match your request.",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,13 +70,6 @@
|
||||
gap: var(--Spacing-x-half);
|
||||
}
|
||||
|
||||
.prices {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.detailsButton {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
@@ -141,25 +141,7 @@ export default function HotelCard({
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
<div className={styles.prices}>
|
||||
<HotelPriceList price={price} />
|
||||
<Button
|
||||
asChild
|
||||
theme="base"
|
||||
intent="primary"
|
||||
size="small"
|
||||
className={styles.button}
|
||||
>
|
||||
{/* TODO: use correct search params */}
|
||||
<Link
|
||||
href={`${selectRate[lang]}?hotel=${hotelData.operaId}`}
|
||||
color="none"
|
||||
keepSearchParams
|
||||
>
|
||||
{intl.formatMessage({ id: "See rooms" })}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<HotelPriceList price={price} hotelId={hotel.hotelData.operaId} />
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
|
||||
@@ -8,9 +8,9 @@ export function getHotelPins(hotels: HotelData[]): HotelPin[] {
|
||||
lng: hotel.hotelData.location.longitude,
|
||||
},
|
||||
name: hotel.hotelData.name,
|
||||
publicPrice: hotel.price?.regularAmount ?? null,
|
||||
memberPrice: hotel.price?.memberAmount ?? null,
|
||||
currency: hotel.price?.currency || null,
|
||||
publicPrice: hotel.price?.public?.localPrice.pricePerNight ?? null,
|
||||
memberPrice: hotel.price?.member?.localPrice.pricePerNight ?? null,
|
||||
currency: hotel.price?.public?.localPrice.currency || null,
|
||||
images: [
|
||||
hotel.hotelData.hotelContent.images,
|
||||
...(hotel.hotelData.gallery?.heroImages ?? []),
|
||||
|
||||
@@ -12,6 +12,7 @@ import styles from "./hotelCardListing.module.css"
|
||||
import {
|
||||
type HotelCardListingProps,
|
||||
HotelCardListingTypeEnum,
|
||||
type HotelData,
|
||||
} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import { SortOrder } from "@/types/components/hotelReservation/selectHotel/hotelSorter"
|
||||
|
||||
@@ -43,10 +44,15 @@ export default function HotelCardListing({
|
||||
(a.hotelData.ratings?.tripAdvisor.rating ?? 0)
|
||||
)
|
||||
case SortOrder.Price:
|
||||
const getPricePerNight = (hotel: HotelData): number => {
|
||||
return (
|
||||
hotel.price?.member?.localPrice?.pricePerNight ??
|
||||
hotel.price?.public?.localPrice?.pricePerNight ??
|
||||
0
|
||||
)
|
||||
}
|
||||
return [...hotelData].sort(
|
||||
(a, b) =>
|
||||
parseInt(a.price?.memberAmount ?? "0", 10) -
|
||||
parseInt(b.price?.memberAmount ?? "0", 10)
|
||||
(a, b) => getPricePerNight(a) - getPricePerNight(b)
|
||||
)
|
||||
case SortOrder.Distance:
|
||||
default:
|
||||
|
||||
@@ -49,7 +49,7 @@ export function filterDuplicateRoomTypesByLowestPrice(
|
||||
const previousLowest = roomMap.get(roomType)
|
||||
|
||||
const currentRequestedPrice = Math.min(
|
||||
Number(publicRequestedPrice.pricePerNight) ?? Infinity,
|
||||
Number(publicRequestedPrice?.pricePerNight) ?? Infinity,
|
||||
Number(memberRequestedPrice?.pricePerNight) ?? Infinity
|
||||
)
|
||||
const currentLocalPrice = Math.min(
|
||||
|
||||
@@ -348,7 +348,6 @@
|
||||
"Terms and conditions": "Geschäftsbedingungen",
|
||||
"Thank you": "Danke",
|
||||
"Theatre": "Theater",
|
||||
"There are no rooms available that match your request": "Es sind keine Zimmer verfügbar, die Ihrer Anfrage entsprechen",
|
||||
"There are no rooms available that match your request.": "Es sind keine Zimmer verfügbar, die Ihrer Anfrage entsprechen.",
|
||||
"There are no transactions to display": "Es sind keine Transaktionen zum Anzeigen vorhanden",
|
||||
"Things nearby HOTEL_NAME": "Dinge in der Nähe von {hotelName}",
|
||||
|
||||
@@ -378,7 +378,6 @@
|
||||
"Terms and conditions": "Terms and conditions",
|
||||
"Thank you": "Thank you",
|
||||
"Theatre": "Theatre",
|
||||
"There are no rooms available that match your request": "There are no rooms available that match your request",
|
||||
"There are no rooms available that match your request.": "There are no rooms available that match your request.",
|
||||
"There are no transactions to display": "There are no transactions to display",
|
||||
"Things nearby HOTEL_NAME": "Things nearby {hotelName}",
|
||||
|
||||
@@ -350,7 +350,6 @@
|
||||
"Terms and conditions": "Käyttöehdot",
|
||||
"Thank you": "Kiitos",
|
||||
"Theatre": "Teatteri",
|
||||
"There are no rooms available that match your request": "Pyyntöäsi vastaavia huoneita ei ole saatavilla",
|
||||
"There are no rooms available that match your request.": "Ei huoneita saatavilla, jotka vastaavat pyyntöäsi.",
|
||||
"There are no transactions to display": "Näytettäviä tapahtumia ei ole",
|
||||
"Things nearby HOTEL_NAME": "Lähellä olevia asioita {hotelName}",
|
||||
|
||||
@@ -347,7 +347,6 @@
|
||||
"Terms and conditions": "Vilkår og betingelser",
|
||||
"Thank you": "Takk",
|
||||
"Theatre": "Teater",
|
||||
"There are no rooms available that match your request": "Det er ingen tilgjengelige rom som samsvarer med forespørselen din",
|
||||
"There are no rooms available that match your request.": "Det er ingen rom tilgjengelige som matcher din forespørsel.",
|
||||
"There are no transactions to display": "Det er ingen transaksjoner å vise",
|
||||
"Things nearby HOTEL_NAME": "Ting i nærheten av {hotelName}",
|
||||
|
||||
@@ -347,7 +347,6 @@
|
||||
"Terms and conditions": "Allmänna villkor",
|
||||
"Thank you": "Tack",
|
||||
"Theatre": "Teater",
|
||||
"There are no rooms available that match your request": "Det finns inga tillgängliga rum som matchar din förfrågan",
|
||||
"There are no rooms available that match your request.": "Det finns inga rum tillgängliga som matchar din begäran.",
|
||||
"There are no transactions to display": "Det finns inga transaktioner att visa",
|
||||
"Things nearby HOTEL_NAME": "Saker i närheten av {hotelName}",
|
||||
|
||||
@@ -82,7 +82,7 @@ export const getRoomAvailability = cache(
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
children,
|
||||
promotionCode,
|
||||
bookingCode,
|
||||
rateCode,
|
||||
}: GetRoomsAvailabilityInput) {
|
||||
return serverClient().hotel.availability.rooms({
|
||||
@@ -91,7 +91,7 @@ export const getRoomAvailability = cache(
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
children,
|
||||
promotionCode,
|
||||
bookingCode,
|
||||
rateCode,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ export const getHotelsAvailabilityInputSchema = z.object({
|
||||
roomStayEndDate: z.string(),
|
||||
adults: z.number(),
|
||||
children: z.string().optional(),
|
||||
promotionCode: z.string().optional().default(""),
|
||||
reservationProfileType: z.string().optional().default(""),
|
||||
attachedProfileId: z.string().optional().default(""),
|
||||
bookingCode: z.string().optional().default(""),
|
||||
})
|
||||
|
||||
export const getRoomsAvailabilityInputSchema = z.object({
|
||||
@@ -19,9 +17,7 @@ export const getRoomsAvailabilityInputSchema = z.object({
|
||||
roomStayEndDate: z.string(),
|
||||
adults: z.number(),
|
||||
children: z.string().optional(),
|
||||
promotionCode: z.string().optional(),
|
||||
reservationProfileType: z.string().optional().default(""),
|
||||
attachedProfileId: z.string().optional().default(""),
|
||||
bookingCode: z.string().optional(),
|
||||
rateCode: z.string().optional(),
|
||||
})
|
||||
|
||||
@@ -31,9 +27,7 @@ export const getSelectedRoomAvailabilityInputSchema = z.object({
|
||||
roomStayEndDate: z.string(),
|
||||
adults: z.number(),
|
||||
children: z.string().optional(),
|
||||
promotionCode: z.string().optional(),
|
||||
reservationProfileType: z.string().optional().default(""),
|
||||
attachedProfileId: z.string().optional().default(""),
|
||||
bookingCode: z.string().optional(),
|
||||
rateCode: z.string(),
|
||||
roomTypeCode: z.string(),
|
||||
packageCodes: z.array(z.nativeEnum(RoomPackageCodeEnum)).optional(),
|
||||
|
||||
@@ -491,22 +491,6 @@ const occupancySchema = z.object({
|
||||
children: z.array(childrenSchema),
|
||||
})
|
||||
|
||||
const bestPricePerStaySchema = z.object({
|
||||
currency: z.string(),
|
||||
// TODO: remove optional when API is ready
|
||||
regularAmount: z.string().optional(),
|
||||
// TODO: remove optional when API is ready
|
||||
memberAmount: z.string().optional(),
|
||||
})
|
||||
|
||||
const bestPricePerNightSchema = z.object({
|
||||
currency: z.string(),
|
||||
// TODO: remove optional when API is ready
|
||||
regularAmount: z.string().optional(),
|
||||
// TODO: remove optional when API is ready
|
||||
memberAmount: z.string().optional(),
|
||||
})
|
||||
|
||||
const linksSchema = z.object({
|
||||
links: z.array(
|
||||
z.object({
|
||||
@@ -516,30 +500,6 @@ const linksSchema = z.object({
|
||||
),
|
||||
})
|
||||
|
||||
const hotelsAvailabilitySchema = z.object({
|
||||
data: z.array(
|
||||
z.object({
|
||||
attributes: z.object({
|
||||
checkInDate: z.string(),
|
||||
checkOutDate: z.string(),
|
||||
occupancy: occupancySchema.optional(),
|
||||
status: z.string(),
|
||||
hotelId: z.number(),
|
||||
ratePlanSet: z.string().optional(),
|
||||
bestPricePerStay: bestPricePerStaySchema.optional(),
|
||||
bestPricePerNight: bestPricePerNightSchema.optional(),
|
||||
}),
|
||||
relationships: linksSchema.optional(),
|
||||
type: z.string().optional(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const getHotelsAvailabilitySchema = hotelsAvailabilitySchema
|
||||
export type HotelsAvailability = z.infer<typeof hotelsAvailabilitySchema>
|
||||
export type HotelsAvailabilityPrices =
|
||||
HotelsAvailability["data"][number]["attributes"]["bestPricePerNight"]
|
||||
|
||||
export const priceSchema = z.object({
|
||||
pricePerNight: z.coerce.number(),
|
||||
pricePerStay: z.coerce.number(),
|
||||
@@ -550,7 +510,7 @@ export const productTypePriceSchema = z.object({
|
||||
rateCode: z.string(),
|
||||
rateType: z.string().optional(),
|
||||
localPrice: priceSchema,
|
||||
requestedPrice: priceSchema,
|
||||
requestedPrice: priceSchema.optional(),
|
||||
})
|
||||
|
||||
const productSchema = z.object({
|
||||
@@ -560,6 +520,34 @@ const productSchema = z.object({
|
||||
}),
|
||||
})
|
||||
|
||||
const hotelsAvailabilitySchema = z.object({
|
||||
data: z.array(
|
||||
z.object({
|
||||
attributes: z.object({
|
||||
checkInDate: z.string(),
|
||||
checkOutDate: z.string(),
|
||||
occupancy: occupancySchema,
|
||||
status: z.string(),
|
||||
hotelId: z.number(),
|
||||
productType: z
|
||||
.object({
|
||||
public: productTypePriceSchema.optional(),
|
||||
member: productTypePriceSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
relationships: linksSchema.optional(),
|
||||
type: z.string().optional(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const getHotelsAvailabilitySchema = hotelsAvailabilitySchema
|
||||
export type HotelsAvailability = z.infer<typeof hotelsAvailabilitySchema>
|
||||
export type ProductType =
|
||||
HotelsAvailability["data"][number]["attributes"]["productType"]
|
||||
export type ProductTypePrices = z.infer<typeof productTypePriceSchema>
|
||||
|
||||
const roomConfigurationSchema = z.object({
|
||||
status: z.string(),
|
||||
roomTypeCode: z.string(),
|
||||
|
||||
@@ -369,9 +369,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
attachedProfileId,
|
||||
bookingCode,
|
||||
} = input
|
||||
|
||||
const params: Record<string, string | number> = {
|
||||
@@ -379,9 +377,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
...(children && { children }),
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
attachedProfileId,
|
||||
bookingCode,
|
||||
language: apiLang,
|
||||
}
|
||||
hotelsAvailabilityCounter.add(1, {
|
||||
@@ -390,8 +386,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsAvailability start",
|
||||
@@ -414,8 +409,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
@@ -446,8 +440,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
@@ -466,8 +459,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsAvailability success",
|
||||
@@ -493,9 +485,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
attachedProfileId,
|
||||
bookingCode,
|
||||
rateCode,
|
||||
} = input
|
||||
|
||||
@@ -504,9 +494,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
...(children && { children }),
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
attachedProfileId,
|
||||
bookingCode,
|
||||
}
|
||||
|
||||
roomsAvailabilityCounter.add(1, {
|
||||
@@ -515,8 +503,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.roomsAvailability start",
|
||||
@@ -540,8 +527,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
@@ -572,8 +558,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
@@ -592,8 +577,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.roomsAvailability success",
|
||||
@@ -620,9 +604,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
attachedProfileId,
|
||||
bookingCode,
|
||||
rateCode,
|
||||
roomTypeCode,
|
||||
packageCodes,
|
||||
@@ -633,9 +615,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
...(children && { children }),
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
attachedProfileId,
|
||||
bookingCode,
|
||||
language: toApiLang(ctx.lang),
|
||||
}
|
||||
|
||||
@@ -645,8 +625,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.selectedRoomAvailability start",
|
||||
@@ -670,8 +649,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponseAvailability.status,
|
||||
@@ -702,8 +680,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
@@ -797,8 +774,7 @@ export const hotelQueryRouter = router({
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
promotionCode,
|
||||
reservationProfileType,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.selectedRoomAvailability success",
|
||||
|
||||
@@ -25,7 +25,7 @@ const SESSION_STORAGE_KEY = "enterDetails"
|
||||
|
||||
type TotalPrice = {
|
||||
local: { price: number; currency: string }
|
||||
euro: { price: number; currency: string }
|
||||
euro?: { price: number; currency: string }
|
||||
}
|
||||
|
||||
export interface EnterDetailsState {
|
||||
|
||||
@@ -25,7 +25,7 @@ type Price = {
|
||||
export type RoomsData = {
|
||||
roomType: string
|
||||
localPrice: Price
|
||||
euroPrice: Price
|
||||
euroPrice: Price | undefined
|
||||
adults: number
|
||||
children?: Child[]
|
||||
cancellationText: string
|
||||
|
||||
@@ -4,7 +4,5 @@ export type AvailabilityInput = {
|
||||
roomStayEndDate: string
|
||||
adults: number
|
||||
children?: string
|
||||
promotionCode?: string
|
||||
reservationProfileType?: string
|
||||
attachedProfileId?: string
|
||||
bookingCode?: string
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { HotelsAvailabilityPrices } from "@/server/routers/hotels/output"
|
||||
import type { ProductType } from "@/server/routers/hotels/output"
|
||||
|
||||
export type HotelPriceListProps = {
|
||||
price: HotelsAvailabilityPrices
|
||||
price: ProductType
|
||||
hotelId: string
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HotelsAvailabilityPrices } from "@/server/routers/hotels/output"
|
||||
import { ProductType } from "@/server/routers/hotels/output"
|
||||
|
||||
import { Hotel } from "@/types/hotel"
|
||||
|
||||
@@ -16,5 +16,5 @@ export type HotelCardListingProps = {
|
||||
|
||||
export type HotelData = {
|
||||
hotelData: Hotel
|
||||
price: HotelsAvailabilityPrices
|
||||
price: ProductType
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ type ImageMetaData = z.infer<typeof imageMetaDataSchema>
|
||||
export type HotelPin = {
|
||||
name: string
|
||||
coordinates: Coordinates
|
||||
publicPrice: string | null
|
||||
memberPrice: string | null
|
||||
publicPrice: number | null
|
||||
memberPrice: number | null
|
||||
currency: string | null
|
||||
images: {
|
||||
imageSizes: ImageSizes
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ProductTypePrices } from "@/server/routers/hotels/output"
|
||||
|
||||
export type PriceCardProps = {
|
||||
currency: string
|
||||
memberAmount?: string | undefined
|
||||
regularAmount?: string | undefined
|
||||
productTypePrices: ProductTypePrices
|
||||
isMemberPrice?: boolean
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user