diff --git a/apps/partner-sas/app/[lang]/book-hotel/[city]/route.ts b/apps/partner-sas/app/[lang]/book-hotel/[city]/route.ts new file mode 100644 index 000000000..d142f41e7 --- /dev/null +++ b/apps/partner-sas/app/[lang]/book-hotel/[city]/route.ts @@ -0,0 +1,102 @@ +import { type NextRequest, NextResponse } from "next/server" +import { z } from "zod" + +import { serializeBookingSearchParams } from "@scandic-hotels/booking-flow/utils/url" +import { Lang } from "@scandic-hotels/common/constants/language" +import { selectHotel } from "@scandic-hotels/common/constants/routes/hotelReservation" +import { dt } from "@scandic-hotels/common/dt" +import { languageSchema } from "@scandic-hotels/common/utils/languages" +import { equalsIgnoreCaseAndAccents } from "@scandic-hotels/common/utils/stringEquals" + +import { env } from "@/env/server" +import { serverClient } from "@/lib/trpc" + +const schema = z.object({ + city: z.string().catch(() => ""), + lang: languageSchema, + adults: z + .number() + .default(1) + .transform((val) => Math.max(1, Math.min(6, val))) + .catch(() => 1), + fromDate: z + .string() + .date() + .transform((val) => { + const dtVal = dt.utc(val) + if (dtVal.isBefore(dt.utc().startOf("day"))) { + return dt.utc().startOf("day") + } + + return dtVal + }) + .catch(() => dt.utc().startOf("day")), + toDate: z + .string() + .date() + .transform((val) => dt.utc(val)) + .optional() + .catch(() => undefined), +}) + +export async function GET( + request: NextRequest, + { + params, + }: { + params: Promise<{ city: string; lang: string }> + } +) { + const p = await params + + const { data: lang } = languageSchema.safeParse(p.lang) // Validate lang param + + const { searchParams } = request.nextUrl + const result = schema.safeParse({ + city: p.city, + lang: lang ?? Lang.en, + adults: searchParams.get("adults") + ? Number(searchParams.get("adults")) + : undefined, + fromDate: searchParams.get("fromDate") || "", + toDate: searchParams.get("toDate") || undefined, + }) + + if (result.success === false) { + return NextResponse.redirect(new URL(`/${lang || Lang.en}`, env.PUBLIC_URL)) + } + + if ( + !result.data.toDate || + !result.data.toDate.isAfter(result.data.fromDate) + ) { + result.data.toDate = result.data.fromDate.add(1, "day") + } + + const client = await serverClient() + + const locations = await client.hotel.locations.get({ lang: Lang.en }) + const cityData = locations + .filter((loc) => loc.type === "cities") + .find((loc) => equalsIgnoreCaseAndAccents(loc.name, result.data.city)) + + if (!cityData?.cityIdentifier) { + return NextResponse.redirect(new URL(`/${lang || Lang.en}`, env.PUBLIC_URL)) + } + + const url = new URL( + `${selectHotel(lang || Lang.en)}?${serializeBookingSearchParams({ + city: cityData.cityIdentifier, + fromDate: result.data.fromDate.format("YYYY-MM-DD"), + toDate: result.data.toDate.format("YYYY-MM-DD"), + rooms: [ + { + adults: result.data.adults, + }, + ], + })}`, + env.PUBLIC_URL + ) + + return NextResponse.redirect(url) +}