import { cache } from "react" import { type MembershipLevel, MembershipLevelEnum, } from "@scandic-hotels/common/constants/membershipLevels" import { createCounter } from "@scandic-hotels/common/telemetry" import { router } from "../../.." import { notFoundError } from "../../../errors" import { GetAllLoyaltyLevels, GetLoyaltyLevel, } from "../../../graphql/Query/LoyaltyLevels.graphql" import { request } from "../../../graphql/request" import { contentstackBaseProcedure } from "../../../procedures" import { generateLoyaltyConfigTag } from "../../../utils/generateTag" import { loyaltyLevelInput } from "./input" import { type LoyaltyLevel, type LoyaltyLevelsResponse, validateLoyaltyLevelsSchema, } from "./output" import type { Lang } from "@scandic-hotels/common/constants/language" export const getAllLoyaltyLevels = cache(async (lang: Lang) => { const getLoyaltyLevelAllCounter = createCounter( "trpc.contentstack.loyaltyLevel.all" ) const metricsGetLoyaltyLevelAll = getLoyaltyLevelAllCounter.init() metricsGetLoyaltyLevelAll.start() // Ideally we should fetch all available tiers from API, but since they // are static, we can just use the enum values. We want to know which // levels we are fetching so that we can use tags to cache them const allLevelIds = Object.values(MembershipLevelEnum) const tags = allLevelIds.map((levelId) => generateLoyaltyConfigTag(lang, "loyalty_level", levelId) ) const loyaltyLevelsConfigResponse = await request( GetAllLoyaltyLevels, { lang, level_ids: allLevelIds }, { key: tags, ttl: "max" } ) if (!loyaltyLevelsConfigResponse.data) { metricsGetLoyaltyLevelAll.noDataError() throw notFoundError({ message: "GetAllLoyaltyLevels returned no data", errorDetails: { lang, level_ids: allLevelIds }, }) } const validatedLoyaltyLevels = validateLoyaltyLevelsSchema.safeParse( loyaltyLevelsConfigResponse.data ) if (!validatedLoyaltyLevels.success) { metricsGetLoyaltyLevelAll.validationError(validatedLoyaltyLevels.error) return [] } metricsGetLoyaltyLevelAll.success() return validatedLoyaltyLevels.data }) export const getLoyaltyLevel = cache( async (lang: Lang, level_id: MembershipLevel) => { const getLoyaltyLevelCounter = createCounter( "trpc.contentstack.loyaltyLevel.get" ) const metricsGetLoyaltyLevel = getLoyaltyLevelCounter.init({ lang, level_id, }) metricsGetLoyaltyLevel.start() const loyaltyLevelsConfigResponse = await request( GetLoyaltyLevel, { lang, level_id }, { key: generateLoyaltyConfigTag(lang, "loyalty_level", level_id), ttl: "max", } ) if ( !loyaltyLevelsConfigResponse.data || !loyaltyLevelsConfigResponse.data.all_loyalty_level.items.length ) { metricsGetLoyaltyLevel.noDataError() throw notFoundError({ message: "GetLoyaltyLevel returned no data", errorDetails: { lang, level_id }, }) } const validatedLoyaltyLevels = validateLoyaltyLevelsSchema.safeParse( loyaltyLevelsConfigResponse.data ) if (!validatedLoyaltyLevels.success) { metricsGetLoyaltyLevel.validationError(validatedLoyaltyLevels.error) return null } metricsGetLoyaltyLevel.success() const result: LoyaltyLevel = validatedLoyaltyLevels.data[0] return result } ) export const loyaltyLevelQueryRouter = router({ byLevel: contentstackBaseProcedure .input(loyaltyLevelInput) .query(async function ({ ctx, input }) { return getLoyaltyLevel(ctx.lang, input.level) }), all: contentstackBaseProcedure.query(async function ({ ctx }) { return getAllLoyaltyLevels(ctx.lang) }), })