Merge branch 'master' of bitbucket.org:scandic-swap/web into fix/loading-rooms-separately
This commit is contained in:
@@ -18,6 +18,9 @@ export const rewardsCurrentInput = z.object({
|
||||
lang: z.nativeEnum(Lang).optional(),
|
||||
})
|
||||
|
||||
export const rewardsUpdateInput = z.object({
|
||||
id: z.string(),
|
||||
})
|
||||
export const rewardsUpdateInput = z.array(
|
||||
z.object({
|
||||
rewardId: z.string(),
|
||||
couponCode: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import { notFound } from "@/server/errors/trpc"
|
||||
import {
|
||||
contentStackBaseWithProtectedProcedure,
|
||||
contentStackBaseWithServiceProcedure,
|
||||
protectedProcedure,
|
||||
router,
|
||||
} from "@/server/trpc"
|
||||
|
||||
@@ -16,7 +17,6 @@ import {
|
||||
} from "./input"
|
||||
import {
|
||||
Reward,
|
||||
SurpriseReward,
|
||||
validateApiRewardSchema,
|
||||
validateCategorizedRewardsSchema,
|
||||
} from "./output"
|
||||
@@ -34,10 +34,11 @@ import {
|
||||
getCurrentRewardFailCounter,
|
||||
getCurrentRewardSuccessCounter,
|
||||
getUniqueRewardIds,
|
||||
getUnwrapSurpriseCounter,
|
||||
getUnwrapSurpriseFailCounter,
|
||||
getUnwrapSurpriseSuccessCounter,
|
||||
} from "./utils"
|
||||
|
||||
import { Surprise } from "@/types/components/blocks/surprises"
|
||||
|
||||
const ONE_HOUR = 60 * 60
|
||||
|
||||
export const rewardQueryRouter = router({
|
||||
@@ -327,44 +328,100 @@ export const rewardQueryRouter = router({
|
||||
|
||||
getCurrentRewardSuccessCounter.add(1)
|
||||
|
||||
const surprises =
|
||||
validatedApiRewards.data
|
||||
.filter(
|
||||
(reward): reward is SurpriseReward =>
|
||||
reward?.type === "coupon" && reward?.rewardType === "Surprise"
|
||||
const surprises = validatedApiRewards.data
|
||||
// TODO: Add predicates once legacy endpoints are removed
|
||||
.filter((reward) => {
|
||||
if (reward?.rewardType !== "Surprise") {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!("coupon" in reward)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const unwrappedCoupons =
|
||||
reward.coupon?.filter((coupon) => !coupon.unwrapped) || []
|
||||
if (unwrappedCoupons.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
.map((surprise) => {
|
||||
const reward = cmsRewards.find(
|
||||
({ reward_id }) => surprise.rewardId === reward_id
|
||||
)
|
||||
.map((surprise) => {
|
||||
const reward = cmsRewards.find(
|
||||
({ reward_id }) => surprise.rewardId === reward_id
|
||||
)
|
||||
|
||||
if (!reward) {
|
||||
return null
|
||||
}
|
||||
if (!reward) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
...reward,
|
||||
id: surprise.id,
|
||||
endsAt: surprise.endsAt,
|
||||
}
|
||||
})
|
||||
.filter((surprise): surprise is Surprise => !!surprise) ?? []
|
||||
return {
|
||||
...reward,
|
||||
id: surprise.id,
|
||||
coupons: "coupon" in surprise ? surprise.coupon || [] : [],
|
||||
}
|
||||
})
|
||||
.flatMap((surprises) => (surprises ? [surprises] : []))
|
||||
|
||||
return surprises
|
||||
}),
|
||||
update: contentStackBaseWithProtectedProcedure
|
||||
unwrap: protectedProcedure
|
||||
.input(rewardsUpdateInput)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const response = await Promise.resolve({ ok: true })
|
||||
// const response = await api.post(api.endpoints.v1.rewards, {
|
||||
// body: {
|
||||
// ids: [input.id],
|
||||
// },
|
||||
// })
|
||||
if (!response.ok) {
|
||||
return false
|
||||
getUnwrapSurpriseCounter.add(1)
|
||||
|
||||
const promises = input.map(({ rewardId, couponCode }) => {
|
||||
return api.post(api.endpoints.v1.Profile.Reward.unwrap, {
|
||||
body: {
|
||||
rewardId,
|
||||
couponCode,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const responses = await Promise.all(promises)
|
||||
|
||||
const errors = await Promise.all(
|
||||
responses.map(async (apiResponse) => {
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
|
||||
getUnwrapSurpriseFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
|
||||
console.error(
|
||||
"contentstack.unwrap API error",
|
||||
JSON.stringify({
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
query: {},
|
||||
})
|
||||
)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
)
|
||||
|
||||
if (errors.filter((ok) => !ok).length > 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
getUnwrapSurpriseSuccessCounter.add(1)
|
||||
|
||||
return true
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -44,6 +44,15 @@ export const getByLevelRewardFailCounter = meter.createCounter(
|
||||
export const getByLevelRewardSuccessCounter = meter.createCounter(
|
||||
"trpc.contentstack.reward.byLevel-success"
|
||||
)
|
||||
export const getUnwrapSurpriseCounter = meter.createCounter(
|
||||
"trpc.contentstack.reward.unwrap"
|
||||
)
|
||||
export const getUnwrapSurpriseFailCounter = meter.createCounter(
|
||||
"trpc.contentstack.reward.unwrap-fail"
|
||||
)
|
||||
export const getUnwrapSurpriseSuccessCounter = meter.createCounter(
|
||||
"trpc.contentstack.reward.unwrap-success"
|
||||
)
|
||||
|
||||
const ONE_HOUR = 60 * 60
|
||||
|
||||
|
||||
@@ -74,3 +74,6 @@ export const getRoomPackagesInputSchema = z.object({
|
||||
children: z.number().optional().default(0),
|
||||
packageCodes: z.array(z.string()).optional().default([]),
|
||||
})
|
||||
export const getCityCoordinatesInputSchema = z.object({
|
||||
city: z.string(),
|
||||
})
|
||||
|
||||
@@ -200,14 +200,14 @@ const rewardNightSchema = z.object({
|
||||
|
||||
export const pointOfInterestSchema = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
distance: z.number(),
|
||||
name: z.string().optional(),
|
||||
distance: z.number().optional(),
|
||||
category: z.object({
|
||||
name: z.string(),
|
||||
group: z.string(),
|
||||
name: z.string().optional(),
|
||||
group: z.string().optional(),
|
||||
}),
|
||||
location: locationSchema,
|
||||
isHighlighted: z.boolean(),
|
||||
location: locationSchema.optional(),
|
||||
isHighlighted: z.boolean().optional(),
|
||||
})
|
||||
.transform((poi) => ({
|
||||
name: poi.name,
|
||||
@@ -215,8 +215,8 @@ export const pointOfInterestSchema = z
|
||||
categoryName: poi.category.name,
|
||||
group: getPoiGroupByCategoryName(poi.category.name),
|
||||
coordinates: {
|
||||
lat: poi.location.latitude,
|
||||
lng: poi.location.longitude,
|
||||
lat: poi.location?.latitude ?? 0,
|
||||
lng: poi.location?.longitude ?? 0,
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -463,7 +463,9 @@ export const getHotelDataSchema = z.object({
|
||||
parking: z.array(parkingSchema),
|
||||
pointsOfInterest: z
|
||||
.array(pointOfInterestSchema)
|
||||
.transform((pois) => pois.sort((a, b) => a.distance - b.distance)),
|
||||
.transform((pois) =>
|
||||
pois.sort((a, b) => (a.distance ?? 0) - (b.distance ?? 0))
|
||||
),
|
||||
ratings: ratingsSchema,
|
||||
rewardNight: rewardNightSchema,
|
||||
restaurantImages: facilitySchema.optional(),
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
import { getVerifiedUser, parsedUser } from "../user/query"
|
||||
import {
|
||||
getBreakfastPackageInputSchema,
|
||||
getCityCoordinatesInputSchema,
|
||||
getHotelDataInputSchema,
|
||||
getHotelsAvailabilityInputSchema,
|
||||
getRatesInputSchema,
|
||||
@@ -342,7 +343,7 @@ export const hotelQueryRouter = router({
|
||||
return {
|
||||
hotelId,
|
||||
hotelName: hotelAttributes.name,
|
||||
hotelDescription: hotelAttributes.hotelContent.texts.descriptions.short,
|
||||
hotelDescriptions: hotelAttributes.hotelContent.texts,
|
||||
hotelLocation: hotelAttributes.location,
|
||||
hotelAddress: hotelAttributes.address,
|
||||
hotelRatings: hotelAttributes.ratings,
|
||||
@@ -355,6 +356,9 @@ export const hotelQueryRouter = router({
|
||||
alerts: hotelAlerts,
|
||||
faq: contentstackData?.faq,
|
||||
healthFacilities: hotelAttributes.healthFacilities,
|
||||
contact: hotelAttributes.contactInformation,
|
||||
socials: hotelAttributes.socialMedia,
|
||||
ecoLabels: hotelAttributes.hotelFacts.ecoLabels,
|
||||
}
|
||||
}),
|
||||
availability: router({
|
||||
@@ -1078,4 +1082,19 @@ export const hotelQueryRouter = router({
|
||||
)
|
||||
}),
|
||||
}),
|
||||
map: router({
|
||||
city: serviceProcedure
|
||||
.input(getCityCoordinatesInputSchema)
|
||||
.query(async function ({ input }) {
|
||||
const apiKey = process.env.GOOGLE_STATIC_MAP_KEY
|
||||
const { city } = input
|
||||
const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(city)}&key=${apiKey}`
|
||||
|
||||
const response = await fetch(url)
|
||||
const data = await response.json()
|
||||
const { lat, lng } = data.results[0].geometry.location
|
||||
|
||||
return { lat, lng }
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -12,13 +12,14 @@ import {
|
||||
type Countries,
|
||||
} from "./output"
|
||||
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { Endpoint } from "@/lib/api/endpoints"
|
||||
import type { RequestOptionsWithOutBody } from "@/types/fetch"
|
||||
import { PointOfInterestGroupEnum } from "@/types/hotel"
|
||||
import { HotelLocation } from "@/types/trpc/routers/hotel/locations"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { Endpoint } from "@/lib/api/endpoints"
|
||||
|
||||
export function getPoiGroupByCategoryName(category: string) {
|
||||
export function getPoiGroupByCategoryName(category: string | undefined) {
|
||||
if (!category) return PointOfInterestGroupEnum.LOCATION
|
||||
switch (category) {
|
||||
case "Airport":
|
||||
case "Bus terminal":
|
||||
|
||||
Reference in New Issue
Block a user