import { z } from "zod" import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast" import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter" import { bookingSearchTypes } from "@/constants/booking" import { parseSearchParams, serializeSearchParams } from "./searchParams" import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" import type { DetailsBooking } from "@/types/components/hotelReservation/enterDetails/details" import type { SelectHotelBooking } from "@/types/components/hotelReservation/selectHotel/selectHotel" import type { Room, SelectRateBooking, } from "@/types/components/hotelReservation/selectRate/selectRate" import type { NextSearchParams } from "@/types/params" type PartialRoom = { rooms?: Partial[] } export type SelectHotelParams = Omit & { hotelId: string } & PartialRoom export function searchParamsToRecord(searchParams: URLSearchParams) { return Object.fromEntries(searchParams.entries()) } const keyRenameMap = { room: "rooms", ratecode: "rateCode", counterratecode: "counterRateCode", roomtype: "roomTypeCode", fromdate: "fromDate", todate: "toDate", hotel: "hotelId", child: "childrenInRoom", searchtype: "searchType", } const typeHints = { filters: "COMMA_SEPARATED_ARRAY", packages: "COMMA_SEPARATED_ARRAY", } as const const adultsSchema = z.coerce.number().min(1).max(6).catch(0) const childAgeSchema = z.coerce.number().catch(-1) const childBedSchema = z.coerce.number().catch(-1) const searchTypeSchema = z.enum(bookingSearchTypes).optional().catch(undefined) export function parseBookingWidgetSearchParams( searchParams: NextSearchParams ): BookingWidgetSearchData { try { const result = parseSearchParams(searchParams, { keyRenameMap, typeHints, schema: z.object({ city: z.string().optional(), hotelId: z.string().optional(), fromDate: z.string().optional(), toDate: z.string().optional(), bookingCode: z.string().optional(), searchType: searchTypeSchema, rooms: z .array( z.object({ adults: adultsSchema, childrenInRoom: z .array( z.object({ bed: childBedSchema, age: childAgeSchema, }) ) .optional() .default([]), }) ) .optional(), }), }) return result } catch (error) { console.log("[URL] Error parsing search params for booking widget:", error) return {} } } export function parseSelectHotelSearchParams( searchParams: NextSearchParams ): SelectHotelBooking | null { try { const result = parseSearchParams(searchParams, { keyRenameMap, typeHints, schema: z.object({ city: z.string().optional(), hotelId: z.string().optional(), fromDate: z.string(), toDate: z.string(), bookingCode: z.string().optional(), searchType: searchTypeSchema, rooms: z.array( z.object({ adults: adultsSchema, childrenInRoom: z .array( z.object({ bed: childBedSchema, age: childAgeSchema, }) ) .optional(), }) ), }), }) return result } catch (error) { console.log("[URL] Error parsing search params for select hotel:", error) return null } } export function parseSelectRateSearchParams( searchParams: NextSearchParams ): SelectRateBooking | null { try { const result = parseSearchParams(searchParams, { keyRenameMap, typeHints, schema: z.object({ city: z.string().optional(), hotelId: z.string(), fromDate: z.string(), toDate: z.string(), searchType: searchTypeSchema, bookingCode: z.string().optional(), rooms: z.array( z.object({ adults: adultsSchema, bookingCode: z.string().optional(), counterRateCode: z.string().optional(), rateCode: z.string().optional(), roomTypeCode: z.string().optional(), packages: z .array( z.nativeEnum({ ...BreakfastPackageEnum, ...RoomPackageCodeEnum, }) ) .optional(), childrenInRoom: z .array( z.object({ bed: childBedSchema, age: childAgeSchema, }) ) .optional(), }) ), }), }) return result } catch (error) { console.log("[URL] Error parsing search params for select rate:", error) return null } } export function parseDetailsSearchParams( searchParams: NextSearchParams ): DetailsBooking | null { const packageEnum = { ...BreakfastPackageEnum, ...RoomPackageCodeEnum, } as const try { const result = parseSearchParams(searchParams, { keyRenameMap, typeHints, schema: z.object({ city: z.string().optional(), hotelId: z.string(), fromDate: z.string(), toDate: z.string(), searchType: searchTypeSchema, bookingCode: z.string().optional(), rooms: z.array( z.object({ adults: adultsSchema, bookingCode: z.string().optional(), counterRateCode: z.string().optional(), rateCode: z.string(), roomTypeCode: z.string(), packages: z.array(z.nativeEnum(packageEnum)).optional(), childrenInRoom: z .array( z.object({ bed: childBedSchema, age: childAgeSchema, }) ) .optional(), }) ), }), }) return result } catch (error) { console.log("[URL] Error parsing search params for details:", error) return null } } const reversedKeyRenameMap = Object.fromEntries( Object.entries(keyRenameMap).map(([key, value]) => [value, key]) ) export function serializeBookingSearchParams( obj: | BookingWidgetSearchData | SelectHotelBooking | SelectRateBooking | DetailsBooking, { initialSearchParams }: { initialSearchParams?: URLSearchParams } = {} ) { return serializeSearchParams(obj, { keyRenameMap: reversedKeyRenameMap, initialSearchParams, typeHints, }) }