From f36b90e47469d6b285495b17ce12429e5fe69666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20J=C3=A4derberg?= Date: Wed, 5 Mar 2025 13:37:33 +0000 Subject: [PATCH] Merged in feature/bookingwidget-client-side (pull request #1481) Move more of BookingWidget to client SW-1639 * feat: move getLocations in booking widget to client side so that it's also cached on the client reducing the blinking when switching urls (and reducing duplicate calls) Approved-by: Linus Flood --- .../hotelreservation/(standard)/utils.ts | 12 +++--- .../[contentType]/[uid]/page.tsx | 4 +- .../@bookingwidget/hotelreservation/page.tsx | 4 +- .../app/[lang]/(live)/@bookingwidget/page.tsx | 4 +- .../components/BookingWidget/Client.tsx | 43 ++++++++++--------- .../components/BookingWidget/index.tsx | 16 +------ .../lib/trpc/memoizedRequests/index.ts | 3 +- .../server/routers/hotels/input.ts | 4 ++ .../server/routers/hotels/query.ts | 24 ++++++----- .../types/components/bookingWidget/index.ts | 2 - 10 files changed, 54 insertions(+), 62 deletions(-) diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts index 755275dcb..6fa32bdfb 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts +++ b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts @@ -3,6 +3,7 @@ import { notFound } from "next/navigation" import { getLocations } from "@/lib/trpc/memoizedRequests" import { generateChildrenString } from "@/components/HotelReservation/utils" +import { safeTry } from "@/utils/safeTry" import { convertSearchParamsToObj, type SelectHotelParams } from "@/utils/url" import type { @@ -46,13 +47,14 @@ export async function getHotelSearchDetails< ): Promise | null> { const selectHotelParams = convertSearchParamsToObj(searchParams) - const locations = await getLocations() - - if (!locations || "error" in locations) return null + const [locations, error] = await safeTry(getLocations()) + if (!locations || error) { + return null + } const hotel = ("hotelId" in selectHotelParams && - (locations.data.find( + (locations.find( (location) => isHotelLocation(location) && "operaId" in location && @@ -72,7 +74,7 @@ export async function getHotelSearchDetails< const city = (typeof cityName === "string" && - locations.data.find( + locations.find( (location) => location.name.toLowerCase() === cityName.toLowerCase() )) || null diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx index 34ab97386..1b750bc4b 100644 --- a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx @@ -1,7 +1,7 @@ import { env } from "@/env/server" import { getHotel, getHotelPage } from "@/lib/trpc/memoizedRequests" -import BookingWidget, { preload } from "@/components/BookingWidget" +import BookingWidget from "@/components/BookingWidget" import { getLang } from "@/i18n/serverContext" import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" @@ -16,8 +16,6 @@ export default async function BookingWidgetPage({ return null } - preload() - if (params.contentType === PageContentTypeEnum.hotelPage) { const hotelPageData = await getHotelPage() diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx index 4e4b9d496..b5507583e 100644 --- a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx @@ -1,6 +1,6 @@ import { env } from "@/env/server" -import BookingWidget, { preload } from "@/components/BookingWidget" +import BookingWidget from "@/components/BookingWidget" import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" import type { LangParams, PageArgs } from "@/types/params" @@ -12,7 +12,5 @@ export default async function BookingWidgetPage({ return null } - preload() - return } diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/page.tsx index b2e10734a..c78c5be9e 100644 --- a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/page.tsx @@ -1,6 +1,6 @@ import { env } from "@/env/server" -import BookingWidget, { preload } from "@/components/BookingWidget" +import BookingWidget from "@/components/BookingWidget" import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" import type { PageArgs } from "@/types/params" @@ -12,7 +12,5 @@ export default async function BookingWidgetPage({ return null } - preload() - return } diff --git a/apps/scandic-web/components/BookingWidget/Client.tsx b/apps/scandic-web/components/BookingWidget/Client.tsx index 50a2ad8b2..c22ddd03e 100644 --- a/apps/scandic-web/components/BookingWidget/Client.tsx +++ b/apps/scandic-web/components/BookingWidget/Client.tsx @@ -5,6 +5,7 @@ import { useEffect, useRef, useState } from "react" import { FormProvider, useForm } from "react-hook-form" import { dt } from "@/lib/dt" +import { trpc } from "@/lib/trpc/client" import { StickyElementNameEnum } from "@/stores/sticky-position" import Form, { @@ -12,6 +13,7 @@ import Form, { } from "@/components/Forms/BookingWidget" import { bookingWidgetSchema } from "@/components/Forms/BookingWidget/schema" import { CloseLargeIcon } from "@/components/Icons" +import useLang from "@/hooks/useLang" import useStickyPosition from "@/hooks/useStickyPosition" import { debounce } from "@/utils/debounce" import isValidJson from "@/utils/isValidJson" @@ -31,32 +33,14 @@ import type { } from "@/types/components/bookingWidget" import type { Location } from "@/types/trpc/routers/hotel/locations" -function getLocationObj(locations: Location[], destination: string) { - try { - const location = locations.find((location) => { - if (location.type === "hotels") { - return location.operaId === destination - } else if (location.type === "cities") { - return location.name.toLowerCase() === destination.toLowerCase() - } - }) - - if (location) { - return location - } - } catch (_) { - // ignore any errors - } - return null -} - export default function BookingWidgetClient({ - locations, type, bookingWidgetSearchParams, }: BookingWidgetClientProps) { const [isOpen, setIsOpen] = useState(false) const bookingWidgetRef = useRef(null) + const lang = useLang() + const [locations] = trpc.hotel.locations.get.useSuspenseQuery({ lang }) useStickyPosition({ ref: bookingWidgetRef, @@ -225,3 +209,22 @@ export function BookingWidgetSkeleton() { ) } + +function getLocationObj(locations: Location[], destination: string) { + try { + const location = locations.find((location) => { + if (location.type === "hotels") { + return location.operaId === destination + } else if (location.type === "cities") { + return location.name.toLowerCase() === destination.toLowerCase() + } + }) + + if (location) { + return location + } + } catch (_) { + // ignore any errors + } + return null +} diff --git a/apps/scandic-web/components/BookingWidget/index.tsx b/apps/scandic-web/components/BookingWidget/index.tsx index 70616bd50..e6e7aa415 100644 --- a/apps/scandic-web/components/BookingWidget/index.tsx +++ b/apps/scandic-web/components/BookingWidget/index.tsx @@ -1,16 +1,9 @@ -import { - getLocations, - isBookingWidgetHidden, -} from "@/lib/trpc/memoizedRequests" +import { isBookingWidgetHidden } from "@/lib/trpc/memoizedRequests" import BookingWidgetClient from "./Client" import type { BookingWidgetProps } from "@/types/components/bookingWidget" -export function preload() { - void getLocations() -} - export default async function BookingWidget({ type, bookingWidgetSearchParams, @@ -21,15 +14,8 @@ export default async function BookingWidget({ return null } - const locations = await getLocations() - - if (!locations || "error" in locations) { - return null - } - return ( diff --git a/apps/scandic-web/lib/trpc/memoizedRequests/index.ts b/apps/scandic-web/lib/trpc/memoizedRequests/index.ts index c724e9cd2..f7ba0eac5 100644 --- a/apps/scandic-web/lib/trpc/memoizedRequests/index.ts +++ b/apps/scandic-web/lib/trpc/memoizedRequests/index.ts @@ -21,7 +21,8 @@ import type { import type { GetSavedPaymentCardsInput } from "@/server/routers/user/input" export const getLocations = cache(async function getMemoizedLocations() { - return serverClient().hotel.locations.get() + const lang = getLang() + return serverClient().hotel.locations.get({ lang }) }) export const getProfile = cache(async function getMemoizedProfile() { diff --git a/apps/scandic-web/server/routers/hotels/input.ts b/apps/scandic-web/server/routers/hotels/input.ts index 481d04a18..9a913735c 100644 --- a/apps/scandic-web/server/routers/hotels/input.ts +++ b/apps/scandic-web/server/routers/hotels/input.ts @@ -140,3 +140,7 @@ export const getHotelsByCountryInput = z.object({ export const getHotelsByCityIdentifierInput = z.object({ cityIdentifier: z.string(), }) + +export const getLocationsInput = z.object({ + lang: z.nativeEnum(Lang), +}) diff --git a/apps/scandic-web/server/routers/hotels/query.ts b/apps/scandic-web/server/routers/hotels/query.ts index 8f0dfc57a..319e04a45 100644 --- a/apps/scandic-web/server/routers/hotels/query.ts +++ b/apps/scandic-web/server/routers/hotels/query.ts @@ -30,6 +30,7 @@ import { getHotelsByCountryInput, getHotelsByCSFilterInput, getHotelsByHotelIdsAvailabilityInputSchema, + getLocationsInput, getMeetingRoomsInputSchema, hotelInputSchema, hotelsAvailabilityInputSchema, @@ -1272,9 +1273,14 @@ export const hotelQueryRouter = router({ return validateHotelData.data.map((id: string) => parseInt(id, 10)) }), locations: router({ - get: serviceProcedure.query(async function ({ ctx }) { + get: serviceProcedure.input(getLocationsInput).query(async function ({ + input, + ctx, + }) { + const lang = input.lang ?? ctx.lang + const searchParams = new URLSearchParams() - searchParams.set("language", toApiLang(ctx.lang)) + searchParams.set("language", toApiLang(lang)) const options: RequestOptionsWithOutBody = { // needs to clear default option as only @@ -1288,29 +1294,27 @@ export const hotelQueryRouter = router({ }, } - const countries = await getCountries(options, searchParams, ctx.lang) + const countries = await getCountries(options, searchParams, lang) if (!countries) { - return null + throw new Error("Unable to fetch countries") } const countryNames = countries.data.map((country) => country.name) const citiesByCountry = await getCitiesByCountry( countryNames, options, searchParams, - ctx.lang + lang ) const locations = await getLocations( - ctx.lang, + lang, options, searchParams, citiesByCountry ) - if (Array.isArray(locations)) { - return { - data: locations, - } + if (!locations || "error" in locations) { + throw new Error("Unable to fetch locations") } return locations diff --git a/apps/scandic-web/types/components/bookingWidget/index.ts b/apps/scandic-web/types/components/bookingWidget/index.ts index b03151023..7a172f9f7 100644 --- a/apps/scandic-web/types/components/bookingWidget/index.ts +++ b/apps/scandic-web/types/components/bookingWidget/index.ts @@ -2,7 +2,6 @@ import type { VariantProps } from "class-variance-authority" import type { z } from "zod" import type { SearchParams } from "@/types/params" -import type { Locations } from "@/types/trpc/routers/hotel/locations" import type { bookingCodeSchema, bookingWidgetSchema, @@ -32,7 +31,6 @@ export interface BookingWidgetProps { } export interface BookingWidgetClientProps { - locations: Locations type?: BookingWidgetType bookingWidgetSearchParams: SearchParams["searchParams"] }