feat: SW-2028 Updated validations at trpc query level

This commit is contained in:
Hrishikesh Vaipurkar
2025-03-25 14:28:52 +01:00
parent eda475d64e
commit 4f4e077859
8 changed files with 36 additions and 34 deletions

View File

@@ -44,7 +44,6 @@ function HotelCard({
state = "default",
type = HotelCardListingTypeEnum.PageListing,
bookingCode = "",
userPoints,
}: HotelCardProps) {
const params = useParams()
const lang = params.lang as Lang
@@ -74,13 +73,7 @@ function HotelCard({
availability.productType?.member?.rateType === RateTypeEnum.Regular
const price = availability.productType
const userHasEnoughPoints =
userPoints !== undefined
? !!price?.redemptions?.some(
(r) => r.localPrice.pointsPerStay < userPoints
)
: false
const userHasEnoughPoints = price?.redemptions?.some((r) => r.hasEnoughPoints)
const notEnoughPointsLabel = intl.formatMessage({ id: "Not enough points" })
return (
@@ -218,7 +211,7 @@ function HotelCard({
))}
</div>
) : null}
{userPoints !== undefined && !userHasEnoughPoints ? (
{price?.redemptions?.length && !userHasEnoughPoints ? (
<Tooltip
arrow="left"
position="bottom"

View File

@@ -30,7 +30,6 @@ import { RateTypeEnum } from "@/types/enums/rateType"
export default function HotelCardListing({
hotelData,
type = HotelCardListingTypeEnum.PageListing,
userPoints,
}: HotelCardListingProps) {
const { data: session } = useSession()
const isUserLoggedIn = isValidClientSession(session)
@@ -122,7 +121,6 @@ export default function HotelCardListing({
}
type={type}
bookingCode={bookingCode}
userPoints={userPoints}
/>
</div>
))

View File

@@ -246,14 +246,6 @@ export async function getHotels(
return hotels
}
export async function getUserPoints() {
const membershipCard = await serverClient().user.safeMembershipLevel()
if (!membershipCard) {
return undefined
}
return membershipCard.currentPoints
}
const hotelSurroundingsFilterNames = [
"Hotel surroundings",
"Hotel omgivelser",

View File

@@ -23,7 +23,7 @@ import { convertObjToSearchParams } from "@/utils/url"
import HotelCardListing from "../HotelCardListing"
import BookingCodeFilter from "./BookingCodeFilter"
import { getFiltersFromHotels, getHotels, getUserPoints } from "./helpers"
import { getFiltersFromHotels, getHotels } from "./helpers"
import HotelCount from "./HotelCount"
import HotelFilter from "./HotelFilter"
import HotelSorter from "./HotelSorter"
@@ -76,11 +76,6 @@ export default async function SelectHotel({
!!redemption
)
let userPoints
if (redemption) {
userPoints = await getUserPoints()
}
const arrivalDate = new Date(selectHotelParams.fromDate)
const departureDate = new Date(selectHotelParams.toDate)
@@ -252,10 +247,7 @@ export default async function SelectHotel({
isAllUnavailable={isAllUnavailable}
operaId={hotels?.[0]?.hotel.operaId}
/>
<HotelCardListing
hotelData={hotels}
userPoints={userPoints ? userPoints : undefined}
/>
<HotelCardListing hotelData={hotels} />
</div>
</main>
<Suspense key={`${suspenseKey}-tracking`} fallback={null}>

View File

@@ -67,6 +67,8 @@ import {
getSelectedRoomAvailability,
} from "./utils"
import type { Session } from "next-auth"
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
import { HotelTypeEnum } from "@/types/enums/hotelType"
@@ -209,7 +211,8 @@ export const getHotel = cache(
export const getHotelsAvailabilityByCity = async (
input: HotelsAvailabilityInputSchema,
apiLang: string,
token: string // Either service token or user access token in case of redemption search
token: string, // Either service token or user access token in case of redemption search
session?: Session
) => {
const {
cityId,
@@ -222,7 +225,7 @@ export const getHotelsAvailabilityByCity = async (
} = input
const cacheClient = await getCacheClient()
return await cacheClient.cacheOrGet(
`${cityId}:${roomStayStartDate}:${roomStayEndDate}:${adults}:${children}:${bookingCode}`,
`${cityId}:${roomStayStartDate}:${roomStayEndDate}:${adults}:${children}:${bookingCode}:${redemption ? "isRedemption" : ""}`,
async () => {
const params: Record<string, string | number> = {
roomStayStartDate,
@@ -325,6 +328,18 @@ export const getHotelsAvailabilityByCity = async (
query: { cityId, params: params },
})
)
if (redemption && session) {
const verifiedUser = await getVerifiedUser({ session })
if (!verifiedUser?.error) {
const userPoints = verifiedUser?.data.membership?.currentPoints ?? 0
validateAvailabilityData.data.data.forEach((data) => {
data.attributes.productType?.redemptions?.forEach((r) => {
r.hasEnoughPoints = userPoints >= r.localPrice.pointsPerStay
})
})
}
}
return {
availability: validateAvailabilityData.data.data.flatMap(
(hotels) => hotels.attributes
@@ -487,7 +502,8 @@ export const hotelQueryRouter = router({
return getHotelsAvailabilityByCity(
input,
apiLang,
ctx.session.token.access_token
ctx.session.token.access_token,
ctx.session,
)
}),
hotelsByHotelIds: serviceProcedure
@@ -606,6 +622,18 @@ export const hotelQueryRouter = router({
)?.mustBeGuaranteed
}
if (redemption && ctx.session) {
const verifiedUser = await getVerifiedUser({ session: ctx.session })
if (!verifiedUser?.error) {
const userPoints = verifiedUser?.data.membership?.currentPoints ?? 0
validateAvailabilityData.data.roomConfigurations.forEach((data) => {
data.redemptions?.forEach(r => {
r.redemption.hasEnoughPoints = userPoints >= r.redemption.localPrice.pointsPerStay
})
})
}
}
return validateAvailabilityData.data
})
)

View File

@@ -66,6 +66,7 @@ export const productTypePointsSchema = z
.object({
localPrice: redemptionSchema,
requestedPrice: redemptionSchema.nullish(),
hasEnoughPoints: z.boolean().optional().default(false),
})
.merge(partialPriceSchema)

View File

@@ -15,7 +15,6 @@ export type HotelData = {
export type HotelCardListingProps = {
hotelData: HotelResponse[]
type?: HotelCardListingTypeEnum
userPoints?: number
}
export interface NullableHotelData extends Omit<HotelData, "hotelData"> {

View File

@@ -7,5 +7,4 @@ export type HotelCardProps = {
type?: HotelCardListingTypeEnum
state?: "default" | "active"
bookingCode?: string | null
userPoints?: number
}