import { myStay } from "@scandic-hotels/common/constants/routes/myStay" import { dt } from "@scandic-hotels/common/dt" import { createCounter } from "@scandic-hotels/common/telemetry" import { safeTry } from "@scandic-hotels/common/utils/safeTry" import { env } from "../../../env/server" import * as api from "../../api" import { cache } from "../../DUPLICATED/cache" import { creditCardsSchema } from "../../routers/user/output" import { toApiLang } from "../../utils" import { encrypt } from "../../utils/encryption" import { getBasicUser } from "./utils/getBasicUser" import { type FriendTransaction, getStaysSchema, type Stay } from "./output" import type { Lang } from "@scandic-hotels/common/constants/language" import type { LangRoute } from "@scandic-hotels/common/constants/routes/langRoute" import type { Session } from "next-auth" export async function getPreviousStays( accessToken: string, limit: number = 10, language: Lang, cursor?: string ) { const getPreviousStaysCounter = createCounter("user", "getPreviousStays") const metricsGetPreviousStays = getPreviousStaysCounter.init({ limit, cursor, language, }) metricsGetPreviousStays.start() const params: Record = { limit: String(limit), language: toApiLang(language), } if (cursor) { params.offset = cursor } const apiResponse = await api.get( api.endpoints.v1.Booking.Stays.past, { headers: { Authorization: `Bearer ${accessToken}`, }, }, params ) if (!apiResponse.ok) { await metricsGetPreviousStays.httpError(apiResponse) return null } const apiJson = await apiResponse.json() const verifiedData = getStaysSchema.safeParse(apiJson) if (!verifiedData.success) { metricsGetPreviousStays.validationError(verifiedData.error) return null } metricsGetPreviousStays.success() return verifiedData.data } export async function getUpcomingStays( accessToken: string, limit: number = 10, language: Lang, cursor?: string ) { const getUpcomingStaysCounter = createCounter("user", "getUpcomingStays") const metricsGetUpcomingStays = getUpcomingStaysCounter.init({ limit, cursor, language, }) metricsGetUpcomingStays.start() const params: Record = { limit: String(limit), language: toApiLang(language), } if (cursor) { params.offset = cursor } const apiResponse = await api.get( api.endpoints.v1.Booking.Stays.future, { headers: { Authorization: `Bearer ${accessToken}`, }, }, params ) if (!apiResponse.ok) { await metricsGetUpcomingStays.httpError(apiResponse) return null } const apiJson = await apiResponse.json() const verifiedData = getStaysSchema.safeParse(apiJson) if (!verifiedData.success) { metricsGetUpcomingStays.validationError(verifiedData.error) return null } metricsGetUpcomingStays.success() return verifiedData.data } export const getCreditCards = cache( async ({ session, onlyNonExpired, }: { session: Session onlyNonExpired?: boolean }) => { const getCreditCardsCounter = createCounter("user", "getCreditCards") const metricsGetCreditCards = getCreditCardsCounter.init({ onlyNonExpired, }) metricsGetCreditCards.start() const apiResponse = await api.get(api.endpoints.v1.Profile.creditCards, { headers: { Authorization: `Bearer ${session.token.access_token}`, }, }) if (!apiResponse.ok) { await metricsGetCreditCards.httpError(apiResponse) return null } const apiJson = await apiResponse.json() const verifiedData = creditCardsSchema.safeParse(apiJson) if (!verifiedData.success) { metricsGetCreditCards.validationError(verifiedData.error) return null } const result = verifiedData.data.data.filter((card) => { if (onlyNonExpired) { try { const expirationDate = dt(card.expirationDate).startOf("day") const currentDate = dt().startOf("day") return expirationDate > currentDate } catch (_) { return false } } return true }) metricsGetCreditCards.success() return result } ) export async function updateStaysBookingUrl( data: Stay[], session: Session, lang: Lang ): Promise export async function updateStaysBookingUrl( data: FriendTransaction[], session: Session, lang: Lang ): Promise export async function updateStaysBookingUrl( data: Stay[] | FriendTransaction[], session: Session, lang: Lang ) { const [user, error] = await safeTry( getBasicUser({ token: session.token, }) ) if (!user || error) { return data } return data.map((d) => { const originalString = d.attributes.confirmationNumber.toString() + "," + user.lastName const encryptedBookingValue = encrypt(originalString) // Get base URL with fallback for ephemeral environments (like deploy previews). const baseUrl = env.PUBLIC_URL || "https://www.scandichotels.com" // Construct Booking URL. const bookingUrl = new URL(myStay[lang], baseUrl) // Add search parameters. if (encryptedBookingValue) { bookingUrl.searchParams.set("RefId", encryptedBookingValue) } else { bookingUrl.searchParams.set("lastName", user.lastName) bookingUrl.searchParams.set( "bookingId", d.attributes.confirmationNumber.toString() ) } return { ...d, attributes: { ...d.attributes, bookingUrl: bookingUrl.toString(), }, } }) } export const myBookingPath: LangRoute = { da: "/hotelreservation/min-booking", de: "/hotelreservation/my-booking", en: "/hotelreservation/my-booking", fi: "/varaa-hotelli/varauksesi", no: "/hotelreservation/my-booking", sv: "/hotelreservation/din-bokning", }