From b75177ad98ab816615eb52a64522a0ad9129dc58 Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Fri, 25 Apr 2025 05:36:44 +0000 Subject: [PATCH] Fix/SW-2429 map view * feat(SW-2429): Removed [contentType]>[uid] and use app router based structure for content types * feat(SW-2429): Added breadcrumbs to follow contenttype folder structure * feat(SW-2429): Removed modal/dialog functionality from map views on hotel and destination pages * fix(SW-2429): Fixed issue with booking widget on meeting pages. Also used same structure for content types Approved-by: Arvid Norlin --- .../collection_page/[uid]/page.tsx | 19 +++ .../@breadcrumbs/content_page/[uid]/page.tsx | 3 + .../destination_city_page/[uid]/page.tsx | 3 + .../destination_country_page/[uid]/page.tsx | 3 + .../destination_overview_page/[uid]}/page.tsx | 0 .../@breadcrumbs/hotel_page/[uid]/page.tsx | 3 + .../@breadcrumbs/loyalty_page/[uid]/page.tsx | 12 ++ .../@breadcrumbs/start_page/[uid]/page.tsx | 3 + .../(contentTypes)/@preview/default.tsx | 1 + .../@preview/loading.tsx | 0 .../@preview/page.tsx | 0 .../collection_page/[uid]/page.tsx | 7 + .../content_page/[uid]/page.tsx | 32 ++++ .../destination_city_page/[uid]/page.tsx | 25 +++ .../destination_country_page/[uid]/page.tsx | 29 ++++ .../destination_overview_page/[uid]/error.tsx | 0 .../[uid]/loading.tsx | 0 .../destination_overview_page/[uid]/page.tsx | 0 .../(contentTypes)/hotel_page/[uid]/page.tsx | 38 +++++ .../layout.module.css | 0 .../(live)/(public)/(contentTypes)/layout.tsx | 24 +++ .../[uid] => (contentTypes)}/loading.tsx | 0 .../loyalty_page/[uid]/page.tsx | 7 + .../(contentTypes)/start_page/[uid]/page.tsx | 19 +++ .../[contentType]/[uid]/@breadcrumbs/page.tsx | 55 ------- .../(public)/[contentType]/[uid]/layout.tsx | 35 ----- .../(public)/[contentType]/[uid]/page.tsx | 111 -------------- .../[uid]/@preview/loading.tsx | 1 - .../[uid]/@preview/page.tsx | 1 - .../[uid]/layout.tsx | 1 - .../destination_city_page/[uid]/page.tsx | 24 +++ .../(contentTypes)/hotel_page/[uid]/page.tsx | 39 +++++ .../(contentTypes)/start_page/[uid]/page.tsx | 3 + .../[contentType]/[uid]/[...paths]/page.tsx | 1 - .../[contentType]/[uid]/page.tsx | 64 -------- .../CityMap/cityMap.module.css | 4 + .../DestinationCityPage/CityMap/index.tsx | 17 +-- .../DestinationCityPage/index.tsx | 87 ++++++----- .../CountryMap/countryMap.module.css | 4 + .../CountryMap/index.tsx | 17 +-- .../DestinationCountryPage/index.tsx | 81 ++++++---- .../DestinationPage/Map/DynamicMap/index.tsx | 2 +- .../ContentType/DestinationPage/Map/index.tsx | 115 +++++--------- .../DestinationPage/Map/map.module.css | 22 +-- .../ContentType/DestinationPage/Map/utils.ts | 2 +- .../ContentType/HotelMapPage/Client.tsx | 113 ++++++++++++++ .../Sidebar/index.tsx | 98 ++++++------ .../Sidebar/sidebar.module.css | 51 ++++--- .../hotelMapPage.module.css} | 20 +-- .../ContentType/HotelMapPage/index.tsx | 42 ++++++ .../HotelPage/Map/DynamicMap/index.tsx | 142 ------------------ .../ContentType/HotelPage/index.tsx | 30 +--- .../components/Maps/InteractiveMap/index.tsx | 4 +- .../Maps/Markers/Poi/poi.module.css | 6 +- apps/scandic-web/types/params.ts | 15 -- 55 files changed, 705 insertions(+), 730 deletions(-) create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/collection_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/content_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_city_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_country_page/[uid]/page.tsx rename apps/scandic-web/app/[lang]/(live)/(public)/{destination_overview_page/[uid]/@breadcrumbs => (contentTypes)/@breadcrumbs/destination_overview_page/[uid]}/page.tsx (100%) create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/hotel_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/loyalty_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/start_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/default.tsx rename apps/scandic-web/app/[lang]/(live)/(public)/{[contentType]/[uid] => (contentTypes)}/@preview/loading.tsx (100%) rename apps/scandic-web/app/[lang]/(live)/(public)/{[contentType]/[uid] => (contentTypes)}/@preview/page.tsx (100%) create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/collection_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/content_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_city_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx rename apps/scandic-web/app/[lang]/(live)/(public)/{ => (contentTypes)}/destination_overview_page/[uid]/error.tsx (100%) rename apps/scandic-web/app/[lang]/(live)/(public)/{ => (contentTypes)}/destination_overview_page/[uid]/loading.tsx (100%) rename apps/scandic-web/app/[lang]/(live)/(public)/{ => (contentTypes)}/destination_overview_page/[uid]/page.tsx (100%) create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/hotel_page/[uid]/page.tsx rename apps/scandic-web/app/[lang]/(live)/(public)/{[contentType]/[uid] => (contentTypes)}/layout.module.css (100%) create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/layout.tsx rename apps/scandic-web/app/[lang]/(live)/(public)/{[contentType]/[uid] => (contentTypes)}/loading.tsx (100%) create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/loyalty_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/start_page/[uid]/page.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/layout.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/loading.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/page.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/layout.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/destination_city_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/hotel_page/[uid]/page.tsx create mode 100644 apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/start_page/[uid]/page.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/[...paths]/page.tsx delete mode 100644 apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx create mode 100644 apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx rename apps/scandic-web/components/ContentType/{HotelPage/Map/DynamicMap => HotelMapPage}/Sidebar/index.tsx (68%) rename apps/scandic-web/components/ContentType/{HotelPage/Map/DynamicMap => HotelMapPage}/Sidebar/sidebar.module.css (72%) rename apps/scandic-web/components/ContentType/{HotelPage/Map/DynamicMap/dynamicMap.module.css => HotelMapPage/hotelMapPage.module.css} (56%) create mode 100644 apps/scandic-web/components/ContentType/HotelMapPage/index.tsx delete mode 100644 apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/index.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/collection_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/collection_page/[uid]/page.tsx new file mode 100644 index 000000000..ede2db8ae --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/collection_page/[uid]/page.tsx @@ -0,0 +1,19 @@ +import { Suspense } from "react" + +import Breadcrumbs from "@/components/Breadcrumbs" +import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" + +import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs" + +export default function CollectionPageBreadcrumbs() { + const variants: Pick = { + color: "Surface/Secondary/Default", + size: "contentWidth", + } + + return ( + }> + + + ) +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/content_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/content_page/[uid]/page.tsx new file mode 100644 index 000000000..717d151f7 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/content_page/[uid]/page.tsx @@ -0,0 +1,3 @@ +export default function ContentPageBreadcrumbs() { + return null +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_city_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_city_page/[uid]/page.tsx new file mode 100644 index 000000000..e2959f394 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_city_page/[uid]/page.tsx @@ -0,0 +1,3 @@ +export default function DestinationCityPageBreadcrumbs() { + return null +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_country_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_country_page/[uid]/page.tsx new file mode 100644 index 000000000..be0499721 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_country_page/[uid]/page.tsx @@ -0,0 +1,3 @@ +export default function DestinationCountryPageBreadcrumbs() { + return null +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@breadcrumbs/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_overview_page/[uid]/page.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@breadcrumbs/page.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/destination_overview_page/[uid]/page.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/hotel_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/hotel_page/[uid]/page.tsx new file mode 100644 index 000000000..6839c2dd0 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/hotel_page/[uid]/page.tsx @@ -0,0 +1,3 @@ +export default function HotelPageBreadcrumbs() { + return null +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/loyalty_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/loyalty_page/[uid]/page.tsx new file mode 100644 index 000000000..7d655fb07 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/loyalty_page/[uid]/page.tsx @@ -0,0 +1,12 @@ +import { Suspense } from "react" + +import Breadcrumbs from "@/components/Breadcrumbs" +import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" + +export default function LoyaltyPageBreadcrumbs() { + return ( + }> + + + ) +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/start_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/start_page/[uid]/page.tsx new file mode 100644 index 000000000..dc5f28de8 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@breadcrumbs/start_page/[uid]/page.tsx @@ -0,0 +1,3 @@ +export default function StartPageBreadcrumbs() { + return null +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/default.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/default.tsx new file mode 100644 index 000000000..83ec2818e --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/default.tsx @@ -0,0 +1 @@ +export { default } from "./page" diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@preview/loading.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/loading.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@preview/loading.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/loading.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@preview/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/page.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@preview/page.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/@preview/page.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/collection_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/collection_page/[uid]/page.tsx new file mode 100644 index 000000000..c552a4fb0 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/collection_page/[uid]/page.tsx @@ -0,0 +1,7 @@ +import CollectionPage from "@/components/ContentType/StaticPages/CollectionPage" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default function CollectionPagePage() { + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/content_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/content_page/[uid]/page.tsx new file mode 100644 index 000000000..48cda3ccd --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/content_page/[uid]/page.tsx @@ -0,0 +1,32 @@ +import { headers } from "next/headers" +import { notFound, redirect } from "next/navigation" + +import { overview } from "@/constants/routes/myPages" +import { isSignupPage } from "@/constants/routes/signup" +import { env } from "@/env/server" + +import { auth } from "@/auth" +import ContentPage from "@/components/ContentType/StaticPages/ContentPage" +import { getLang } from "@/i18n/serverContext" +import { isValidSession } from "@/utils/session" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default async function ContentPagePage() { + const lang = getLang() + const pathname = headers().get("x-pathname") || "" + const isSignupRoute = isSignupPage(pathname) + + if (isSignupRoute) { + if (!env.SHOW_SIGNUP_FLOW) { + notFound() + } + + const session = await auth() + if (isValidSession(session)) { + redirect(overview[lang]) + } + } + + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_city_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_city_page/[uid]/page.tsx new file mode 100644 index 000000000..fe71e94a9 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_city_page/[uid]/page.tsx @@ -0,0 +1,25 @@ +import { notFound } from "next/navigation" +import { Suspense } from "react" + +import { env } from "@/env/server" + +import DestinationCityPage from "@/components/ContentType/DestinationPage/DestinationCityPage" +import DestinationCityPageSkeleton from "@/components/ContentType/DestinationPage/DestinationCityPage/DestinationCityPageSkeleton" + +import type { PageArgs } from "@/types/params" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default function DestinationCityPagePage({ + searchParams, +}: PageArgs<{}, { view?: "map" }>) { + if (env.HIDE_FOR_NEXT_RELEASE) { + notFound() + } + + return ( + }> + + + ) +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx new file mode 100644 index 000000000..2520db568 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx @@ -0,0 +1,29 @@ +import { notFound } from "next/navigation" +import { Suspense } from "react" + +import { env } from "@/env/server" + +import DestinationCountryPage from "@/components/ContentType/DestinationPage/DestinationCountryPage" +import DestinationCountryPageSkeleton from "@/components/ContentType/DestinationPage/DestinationCountryPage/DestinationCountryPageSkeleton" + +import type { PageArgs } from "@/types/params" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default function DestinationCountryPagePage({}: PageArgs< + {}, + { view?: "map" } +>) { + if (env.HIDE_FOR_NEXT_RELEASE) { + notFound() + } + + return ( + }> + + + ) +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/error.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_overview_page/[uid]/error.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/error.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_overview_page/[uid]/error.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/loading.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_overview_page/[uid]/loading.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/loading.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_overview_page/[uid]/loading.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_overview_page/[uid]/page.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/page.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_overview_page/[uid]/page.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/hotel_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/hotel_page/[uid]/page.tsx new file mode 100644 index 000000000..92507e223 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/hotel_page/[uid]/page.tsx @@ -0,0 +1,38 @@ +import { notFound } from "next/navigation" + +import { env } from "@/env/server" +import { getHotelPage } from "@/lib/trpc/memoizedRequests" + +import HotelMapPage from "@/components/ContentType/HotelMapPage" +import HotelPage from "@/components/ContentType/HotelPage" +import HotelSubpage from "@/components/ContentType/HotelSubpage" + +import type { PageArgs } from "@/types/params" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default async function HotelPagePage({ + searchParams, +}: PageArgs<{}, { subpage?: string; view?: "map" }>) { + if (env.HIDE_FOR_NEXT_RELEASE) { + return notFound() + } + const hotelPageData = await getHotelPage() + + if (!hotelPageData) { + notFound() + } + + if (searchParams.subpage) { + return ( + + ) + } + if (searchParams.view === "map") { + return + } + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/layout.module.css b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/layout.module.css similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/layout.module.css rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/layout.module.css diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/layout.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/layout.tsx new file mode 100644 index 000000000..6ce21b759 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/layout.tsx @@ -0,0 +1,24 @@ +import styles from "./layout.module.css" + +import type { LangParams, LayoutArgs } from "@/types/params" + +export default function ContentTypeLayout({ + breadcrumbs, + preview, + children, +}: React.PropsWithChildren< + LayoutArgs & { + breadcrumbs: React.ReactNode + preview: React.ReactNode + } +>) { + return ( +
+
+ {preview} + {breadcrumbs} + {children} +
+
+ ) +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/loading.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/loading.tsx similarity index 100% rename from apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/loading.tsx rename to apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/loading.tsx diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/loyalty_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/loyalty_page/[uid]/page.tsx new file mode 100644 index 000000000..d169bad07 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/loyalty_page/[uid]/page.tsx @@ -0,0 +1,7 @@ +import LoyaltyPage from "@/components/ContentType/LoyaltyPage" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default function LoyaltyPagePage() { + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/start_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/start_page/[uid]/page.tsx new file mode 100644 index 000000000..927ceb3ab --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/start_page/[uid]/page.tsx @@ -0,0 +1,19 @@ +import { notFound } from "next/navigation" + +import { env } from "@/env/server" + +import StartPage from "@/components/ContentType/StartPage" + +import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" +import type { PageArgs } from "@/types/params" + +export { generateMetadata } from "@/utils/generateMetadata" + +export default function StartPagePage({ + searchParams, +}: PageArgs<{}, BookingWidgetSearchData>) { + if (env.HIDE_FOR_NEXT_RELEASE) { + notFound() + } + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx deleted file mode 100644 index bef11f03b..000000000 --- a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { Suspense } from "react" - -import Breadcrumbs from "@/components/Breadcrumbs" -import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" - -import type { ContentTypeParams, LangParams, PageArgs } from "@/types/params" -import { PageContentTypeEnum } from "@/types/requests/contentType" -import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs" - -// This is a temporary solution to avoid showing breadcrumbs on certain content types. -// This should be refactored in the future to handle content types differently, similar to `destination_overview_page`. -const IGNORED_CONTENT_TYPES = [ - PageContentTypeEnum.hotelPage, - PageContentTypeEnum.contentPage, - PageContentTypeEnum.destinationCityPage, - PageContentTypeEnum.destinationCountryPage, - PageContentTypeEnum.destinationOverviewPage, - PageContentTypeEnum.startPage, -] - -// This function is temporary until the content types are refactored and handled differently, similar to `destination_overview_page`. -function getBreadcrumbsVariantsByContentType( - contentType: PageContentTypeEnum -): Pick | null { - switch (contentType) { - case PageContentTypeEnum.collectionPage: - return { color: "Surface/Secondary/Default", size: "contentWidth" } - default: - return null - } -} - -// We need to return null for both ignored content types and non-existent content types -// In order to no having to maintain an explicit array of all content types besides the PageContentTypeEnum we convert it here. -const allowedContentTypes = Object.keys(PageContentTypeEnum) - .map((key) => { - return PageContentTypeEnum[key as keyof typeof PageContentTypeEnum] - }) - .filter((c) => !IGNORED_CONTENT_TYPES.includes(c)) - -export default function PageBreadcrumbs({ - params, -}: PageArgs) { - if (!allowedContentTypes.includes(params.contentType)) { - return null - } - - const variants = getBreadcrumbsVariantsByContentType(params.contentType) - - return ( - }> - - - ) -} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/layout.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/layout.tsx deleted file mode 100644 index 3c0681cc7..000000000 --- a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/layout.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import styles from "./layout.module.css" - -import type { - ContentTypeParams, - LangParams, - LayoutArgs, - UIDParams, -} from "@/types/params" - -export default function ContentTypeLayout({ - breadcrumbs, - preview, - children, - //params, -}: React.PropsWithChildren< - LayoutArgs & { - breadcrumbs: React.ReactNode - preview: React.ReactNode - } ->) { - // Would like a better way to check if the contentType is valid. - // Perhaps a case for using an `{} as const` object for PageContentTypes instead? - // if (!Object.values(PageContentTypeEnum).includes(params.contentType)) { - // notFound() - // } - return ( -
-
- {preview} - {breadcrumbs} - {children} -
-
- ) -} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx deleted file mode 100644 index 160b4360e..000000000 --- a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { headers } from "next/headers" -import { notFound, redirect } from "next/navigation" -import { Suspense } from "react" - -import { overview } from "@/constants/routes/myPages" -import { isSignupPage } from "@/constants/routes/signup" -import { env } from "@/env/server" -import { getHotelPage } from "@/lib/trpc/memoizedRequests" - -import { auth } from "@/auth" -import DestinationCityPage from "@/components/ContentType/DestinationPage/DestinationCityPage" -import DestinationCityPageSkeleton from "@/components/ContentType/DestinationPage/DestinationCityPage/DestinationCityPageSkeleton" -import DestinationCountryPage from "@/components/ContentType/DestinationPage/DestinationCountryPage" -import DestinationCountryPageSkeleton from "@/components/ContentType/DestinationPage/DestinationCountryPage/DestinationCountryPageSkeleton" -import HotelPage from "@/components/ContentType/HotelPage" -import HotelSubpage from "@/components/ContentType/HotelSubpage" -import LoyaltyPage from "@/components/ContentType/LoyaltyPage" -import StartPage from "@/components/ContentType/StartPage" -import CollectionPage from "@/components/ContentType/StaticPages/CollectionPage" -import ContentPage from "@/components/ContentType/StaticPages/ContentPage" -import { getLang } from "@/i18n/serverContext" -import { isValidSession } from "@/utils/session" - -import type { - LangParams, - NonAppRouterContentTypeParams, - PageArgs, - UIDParams, -} from "@/types/params" -import { PageContentTypeEnum } from "@/types/requests/contentType" - -export { generateMetadata } from "@/utils/generateMetadata" - -export default async function ContentTypePage({ - params, - searchParams, -}: PageArgs< - LangParams & NonAppRouterContentTypeParams & UIDParams, - { subpage?: string; filterFromUrl?: string } ->) { - const pathname = headers().get("x-pathname") || "" - - switch (params.contentType) { - case PageContentTypeEnum.collectionPage: - return - case PageContentTypeEnum.contentPage: { - const isSignupRoute = isSignupPage(pathname) - - if (isSignupRoute) { - if (!env.SHOW_SIGNUP_FLOW) { - return notFound() - } - - const session = await auth() - if (isValidSession(session)) { - redirect(overview[getLang()]) - } - } - - return - } - case PageContentTypeEnum.loyaltyPage: - return - case PageContentTypeEnum.destinationCountryPage: - if (env.HIDE_FOR_NEXT_RELEASE) { - return notFound() - } - return ( - }> - - - ) - case PageContentTypeEnum.destinationCityPage: - if (env.HIDE_FOR_NEXT_RELEASE) { - return notFound() - } - return ( - }> - - - ) - case PageContentTypeEnum.hotelPage: - if (env.HIDE_FOR_NEXT_RELEASE) { - return notFound() - } - const hotelPageData = await getHotelPage() - - if (hotelPageData) { - if (searchParams.subpage) { - return ( - - ) - } - return - } - - notFound() - case PageContentTypeEnum.startPage: - if (env.HIDE_FOR_NEXT_RELEASE) { - return notFound() - } - return - default: - const type: never = params.contentType - console.error(`Unsupported content type given: ${type}`) - notFound() - } -} diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/loading.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/loading.tsx deleted file mode 100644 index 114ae97b3..000000000 --- a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/loading.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "../../../[contentType]/[uid]/@preview/loading" diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/page.tsx deleted file mode 100644 index 81c9d5a28..000000000 --- a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/@preview/page.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "../../../[contentType]/[uid]/@preview/page" diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/layout.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/layout.tsx deleted file mode 100644 index 4faada2be..000000000 --- a/apps/scandic-web/app/[lang]/(live)/(public)/destination_overview_page/[uid]/layout.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "../../[contentType]/[uid]/layout" diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/destination_city_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/destination_city_page/[uid]/page.tsx new file mode 100644 index 000000000..81510ff13 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/destination_city_page/[uid]/page.tsx @@ -0,0 +1,24 @@ +import { env } from "@/env/server" +import { getDestinationCityPage } from "@/lib/trpc/memoizedRequests" + +import BookingWidget from "@/components/BookingWidget" + +import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" +import type { PageArgs } from "@/types/params" + +export default async function BookingWidgetDestinationCityPage({ + searchParams, +}: PageArgs<{}, BookingWidgetSearchData>) { + if (!env.ENABLE_BOOKING_WIDGET) { + return null + } + const { bookingCode } = searchParams + const pageData = await getDestinationCityPage() + + const bookingWidgetSearchParams = { + bookingCode: bookingCode ?? "", + city: pageData?.city.name ?? "", + } + + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/hotel_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/hotel_page/[uid]/page.tsx new file mode 100644 index 000000000..ea12be891 --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/hotel_page/[uid]/page.tsx @@ -0,0 +1,39 @@ +import { env } from "@/env/server" +import { getHotel, getHotelPage } from "@/lib/trpc/memoizedRequests" + +import BookingWidget from "@/components/BookingWidget" +import { getLang } from "@/i18n/serverContext" + +import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" +import type { PageArgs } from "@/types/params" + +export default async function BookingWidgetHotelPage({ + searchParams, +}: PageArgs<{}, BookingWidgetSearchData & { subpage?: string }>) { + if (!env.ENABLE_BOOKING_WIDGET) { + return null + } + const { bookingCode, subpage } = searchParams + + const hotelPageData = await getHotelPage() + const hotelData = await getHotel({ + hotelId: hotelPageData?.hotel_page_id || "", + language: getLang(), + isCardOnlyPayment: false, + }) + + const isMeetingSubpage = + subpage && hotelData?.additionalData.meetingRooms.nameInUrl === subpage + + if (isMeetingSubpage) { + return null + } + + const bookingWidgetSearchParams = { + bookingCode: bookingCode ?? "", + hotel: hotelData?.hotel.id ?? "", + city: hotelData?.hotel.cityName ?? "", + } + + return +} diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/start_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/start_page/[uid]/page.tsx new file mode 100644 index 000000000..58031bb8e --- /dev/null +++ b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/(contentTypes)/start_page/[uid]/page.tsx @@ -0,0 +1,3 @@ +export default async function BookingWidgetStartPage() { + return null +} diff --git a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/[...paths]/page.tsx b/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/[...paths]/page.tsx deleted file mode 100644 index 03a82e5f5..000000000 --- a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/[...paths]/page.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "../page" 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 deleted file mode 100644 index 446c8d5f2..000000000 --- a/apps/scandic-web/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { env } from "@/env/server" -import { getHotel, getHotelPage } from "@/lib/trpc/memoizedRequests" - -import BookingWidget from "@/components/BookingWidget" -import { getLang } from "@/i18n/serverContext" - -import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" -import type { ContentTypeParams, PageArgs } from "@/types/params" -import { PageContentTypeEnum } from "@/types/requests/contentType" - -export default async function BookingWidgetPage({ - params, - searchParams, -}: PageArgs) { - if (!env.ENABLE_BOOKING_WIDGET) { - return null - } - - if (params.contentType === PageContentTypeEnum.startPage) { - return null - } - - if (params.contentType === PageContentTypeEnum.hotelPage) { - return ( - - ) - } - - return -} - -async function BookingWidgetOnHotelPage({ - bookingCode, - subpage, -}: { - bookingCode?: string - subpage: string -}) { - const hotelPageData = await getHotelPage() - - const hotelData = await getHotel({ - hotelId: hotelPageData?.hotel_page_id || "", - language: getLang(), - isCardOnlyPayment: false, - }) - - const isMeetingSubpage = - hotelData?.additionalData.meetingRooms.nameInUrl === subpage - - if (isMeetingSubpage) { - return null - } - - const hotelPageParams = { - bookingCode: bookingCode ?? "", - hotel: hotelData?.hotel.id ?? "", - city: hotelData?.hotel.cityName ?? "", - } - - return -} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/cityMap.module.css b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/cityMap.module.css index 586806063..a1c3fcd88 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/cityMap.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/cityMap.module.css @@ -1,3 +1,7 @@ +.title { + color: var(--Text-Heading); +} + @media screen and (max-width: 949px) { .title { display: none; diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx index 6006f6cea..69090f273 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx @@ -1,9 +1,9 @@ "use client" import { useIntl } from "react-intl" -import { useDestinationDataStore } from "@/stores/destination-data" +import { Typography } from "@scandic-hotels/design-system/Typography" -import Title from "@/components/TempDesignSystem/Text/Title" +import { useDestinationDataStore } from "@/stores/destination-data" import Map from "../../Map" import { getHeadingText } from "../../utils" @@ -44,14 +44,11 @@ export default function CityMap({ pageType="city" defaultLocation={defaultLocation} > - - {getHeadingText(intl, city.name, allFilters, activeFilters[0])} - + +

+ {getHeadingText(intl, city.name, allFilters, activeFilters[0])} +

+
) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx index 633decbe3..5035fb5d6 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx @@ -21,7 +21,13 @@ import DestinationCityPageSkeleton from "./DestinationCityPageSkeleton" import styles from "./destinationCityPage.module.css" -export default async function DestinationCityPage() { +interface DestinationCityPageProps { + isMapView: boolean +} + +export default async function DestinationCityPage({ + isMapView, +}: DestinationCityPageProps) { const pageData = await getDestinationCityPage() if (!pageData) { @@ -46,45 +52,48 @@ export default async function DestinationCityPage() { <> }> -
-
- }> - - - {images?.length ? ( - - ) : null} -
-
- - {blocks && } -
- +
+ )}
diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/countryMap.module.css b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/countryMap.module.css index 586806063..a1c3fcd88 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/countryMap.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/countryMap.module.css @@ -1,3 +1,7 @@ +.title { + color: var(--Text-Heading); +} + @media screen and (max-width: 949px) { .title { display: none; diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/index.tsx index c552e5856..a5d0084c7 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/CountryMap/index.tsx @@ -2,9 +2,9 @@ import { useIntl } from "react-intl" -import { useDestinationDataStore } from "@/stores/destination-data" +import { Typography } from "@scandic-hotels/design-system/Typography" -import Title from "@/components/TempDesignSystem/Text/Title" +import { useDestinationDataStore } from "@/stores/destination-data" import Map from "../../Map" import { getHeadingText } from "../../utils" @@ -44,14 +44,11 @@ export default function CountryMap({ pageType="country" defaultLocation={defaultLocation} > - - {getHeadingText(intl, country, allFilters, activeFilters[0])} - + +

+ {getHeadingText(intl, country, allFilters, activeFilters[0])} +

+
) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/index.tsx index f3027261c..ff81c5ee1 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCountryPage/index.tsx @@ -1,6 +1,7 @@ import { notFound } from "next/navigation" import { Suspense } from "react" +import { env } from "@/env/server" import { getDestinationCountryPage } from "@/lib/trpc/memoizedRequests" import Breadcrumbs from "@/components/Breadcrumbs" @@ -14,11 +15,18 @@ import SidebarContentWrapper from "../SidebarContentWrapper" import DestinationPageSidePeek from "../Sidepeek" import TopImages from "../TopImages" import DestinationTracking from "../Tracking" +import CountryMap from "./CountryMap" import DestinationCountryPageSkeleton from "./DestinationCountryPageSkeleton" import styles from "./destinationCountryPage.module.css" -export default async function DestinationCountryPage() { +interface DestinationCountryPageProps { + isMapView: boolean +} + +export default async function DestinationCountryPage({ + isMapView, +}: DestinationCountryPageProps) { const pageData = await getDestinationCountryPage() if (!pageData) { @@ -43,38 +51,47 @@ export default async function DestinationCountryPage() { <> }> -
-
- }> - - - {images?.length ? ( - - ) : null} -
-
- - {blocks && } -
- -
+ ) : null} + +
+ + {blocks && } +
+ + + )}
diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx index b3ec2fb17..598e9ad97 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx @@ -51,7 +51,7 @@ export default function DynamicMap({ const pageType = usePageType() const { activeMarker } = useDestinationPageHotelsMapStore() const ref = useRef(null) - const [hasFittedBounds, setHasFittedBounds] = useState(false) + const [hasFittedBounds, setHasFittedBounds] = useState(!!activeMarker) useEffect(() => { if (ref.current && activeMarker && pageType === "overview") { diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx index 409600c9a..c57fa635a 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx @@ -1,15 +1,13 @@ "use client" -import { useRouter, useSearchParams } from "next/navigation" +import { useRouter } from "next/navigation" import { type PropsWithChildren, useCallback, useEffect, - useMemo, useRef, useState, } from "react" -import { Dialog, Modal } from "react-aria-components" import { useIntl } from "react-intl" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" @@ -48,17 +46,11 @@ export default function Map({ children, }: PropsWithChildren) { const router = useRouter() - const searchParams = useSearchParams() const { activeMarker: activeHotelId, setActiveMarker } = useDestinationPageHotelsMapStore() - const isMapView = useMemo( - () => searchParams.get("view") === "map", - [searchParams] - ) const activeHotel = hotels.find(({ hotel }) => hotel.id === activeHotelId) const rootDiv = useRef(null) - const [mapHeight, setMapHeight] = useState("0px") - const [scrollHeightWhenOpened, setScrollHeightWhenOpened] = useState(0) + const [mapHeight, setMapHeight] = useState("100dvh") const intl = useIntl() @@ -92,25 +84,6 @@ export default function Map({ setMapHeight(`calc(100dvh - ${topPosition + scrollY}px)`) }, []) - // Making sure the map is always opened at the top of the page, - // just below the header and booking widget as these should stay visible. - // When closing, the page should scroll back to the position it was before opening the map. - useEffect(() => { - // Skip the first render - if (!rootDiv.current) { - return - } - - if (isMapView && scrollHeightWhenOpened === 0) { - const scrollY = window.scrollY - setScrollHeightWhenOpened(scrollY) - window.scrollTo({ top: 0, behavior: "instant" }) - } else if (!isMapView && scrollHeightWhenOpened !== 0) { - window.scrollTo({ top: scrollHeightWhenOpened, behavior: "instant" }) - setScrollHeightWhenOpened(0) - } - }, [isMapView, scrollHeightWhenOpened, rootDiv]) - useEffect(() => { const debouncedResizeHandler = debounce(function () { handleMapHeight() @@ -125,7 +98,7 @@ export default function Map({ observer.unobserve(document.documentElement) } } - }, [rootDiv, isMapView, handleMapHeight]) + }, [rootDiv, handleMapHeight]) function handleClose() { const url = new URL(window.location.href) @@ -136,57 +109,39 @@ export default function Map({ return ( -
- - +
+ - -
- - - - -
-
+ + {intl.formatMessage({ + defaultMessage: "Back", + })} + + +
+ + + +
) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css b/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css index 78e26a3c2..dd85031f6 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css @@ -1,14 +1,10 @@ -.dialog { - --destination-map-height: 100dvh; - - position: absolute; - top: 0; - left: 0; - height: var(--destination-map-height); - width: 100dvw; - z-index: var(--hotel-dynamic-map-z-index); +.mapWrapper { + position: fixed; display: flex; + height: 100dvh; + width: 100dvw; background-color: var(--Base-Surface-Primary-light-Normal); + z-index: 1; } .sidebar { @@ -22,12 +18,6 @@ gap: var(--Spacing-x4); } -.wrapper { - position: absolute; - top: 0; - left: 0; -} - .closeButton { pointer-events: initial; box-shadow: var(--button-box-shadow); @@ -39,7 +29,7 @@ } @media screen and (max-width: 949px) { - .dialog { + .mapWrapper { flex-direction: column; } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts b/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts index dcdd1ecb7..06cdbd931 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts @@ -42,7 +42,7 @@ export function getHotelMapMarkers(hotels: DestinationPagesHotelData[]) { : null, url: url, tripadvisor: hotel.tripadvisor, - amenities: hotel.detailedFacilities, + amenities: hotel.detailedFacilities.slice(0, 3), image: getImage({ hotel, url }), })) diff --git a/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx b/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx new file mode 100644 index 000000000..49db525b8 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelMapPage/Client.tsx @@ -0,0 +1,113 @@ +"use client" +import { APIProvider } from "@vis.gl/react-google-maps" +import { useRouter } from "next/navigation" +import { useCallback, useEffect, useRef, useState } from "react" +import { useIntl } from "react-intl" + +import { Button } from "@scandic-hotels/design-system/Button" +import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" + +import InteractiveMap from "@/components/Maps/InteractiveMap" +import { debounce } from "@/utils/debounce" + +import Sidebar from "./Sidebar" + +import styles from "./hotelMapPage.module.css" + +import type { Coordinates } from "@/types/components/maps/coordinates" +import type { PointOfInterest } from "@/types/hotel" + +interface HotelMapPageClientProps { + apiKey: string + hotelName: string + coordinates: Coordinates + pointsOfInterest: PointOfInterest[] + mapId: string +} + +export default function HotelMapPageClient({ + apiKey, + hotelName, + coordinates, + pointsOfInterest, + mapId, +}: HotelMapPageClientProps) { + const intl = useIntl() + const router = useRouter() + const rootDiv = useRef(null) + const [mapHeight, setMapHeight] = useState("100dvh") + const [activePoi, setActivePoi] = useState(null) + + // Calculate the height of the map based on the viewport height from the start-point (below the header and booking widget) + const handleMapHeight = useCallback(() => { + const topPosition = rootDiv.current?.getBoundingClientRect().top ?? 0 + const scrollY = window.scrollY + setMapHeight(`calc(100dvh - ${topPosition + scrollY}px)`) + }, []) + + function handleClose() { + const url = new URL(window.location.href) + url.searchParams.delete("view") + router.push(url.toString()) + } + + useEffect(() => { + const debouncedResizeHandler = debounce(function () { + handleMapHeight() + }) + + const observer = new ResizeObserver(debouncedResizeHandler) + + observer.observe(document.documentElement) + + return () => { + if (observer) { + observer.unobserve(document.documentElement) + } + } + }, [rootDiv, handleMapHeight]) + + const closeButton = ( + + ) + + return ( + +
+ setActivePoi(poi ?? null)} + coordinates={coordinates} + /> + setActivePoi(poi ?? null)} + mapId={mapId} + /> +
+
+ ) +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx b/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx similarity index 68% rename from apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx rename to apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx index 0524f8f55..be4029cc9 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/index.tsx @@ -1,13 +1,14 @@ "use client" import { useMap } from "@vis.gl/react-google-maps" +import { cx } from "class-variance-authority" import { useState } from "react" +import { Button as AriaButton } from "react-aria-components" import { useIntl } from "react-intl" +import { Typography } from "@scandic-hotels/design-system/Typography" + import PoiMarker from "@/components/Maps/Markers/Poi" -import Button from "@/components/TempDesignSystem/Button" -import Body from "@/components/TempDesignSystem/Text/Body" -import Title from "@/components/TempDesignSystem/Text/Title" import styles from "./sidebar.module.css" @@ -134,64 +135,61 @@ export default function Sidebar({ isFullScreenSidebar ? styles.fullscreen : "" }`} > - + + + {isFullScreenSidebar ? viewAsMapMsg : viewAsListMsg} + +
- - {intl.formatMessage( - { - defaultMessage: "Things nearby {hotelName}", - }, - { hotelName } - )} - + +

+ {intl.formatMessage( + { + defaultMessage: "Things nearby {hotelName}", + }, + { hotelName } + )} +

+
{poisInGroups.map(({ group, pois }) => pois.length ? (
- -

+ +

{translatePOIGroup(group)}

- +
    {pois.map((poi) => (
  • - + + handleMouseEnter(poi.name)} + onPress={() => + handlePoiClick(poi.name, poi.coordinates) + } + > + {poi.name} + + {intl.formatMessage( + { + defaultMessage: "{distanceInKm} km", + }, + { + distanceInKm: poi.distance, + } + )} + + +
  • ))}
diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/sidebar.module.css b/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/sidebar.module.css similarity index 72% rename from apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/sidebar.module.css rename to apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/sidebar.module.css index 838cabfbe..4662acd3b 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/sidebar.module.css +++ b/apps/scandic-web/components/ContentType/HotelMapPage/Sidebar/sidebar.module.css @@ -5,20 +5,21 @@ .sidebarContent { display: grid; - gap: var(--Spacing-x5); + gap: var(--Space-x5); align-content: start; overflow-y: auto; } .poiGroup { display: grid; - gap: var(--Spacing-x2); + gap: var(--Space-x2); } .poiHeading { display: flex; align-items: center; - gap: var(--Spacing-x1); + gap: var(--Space-x1); + color: var(--Text-Default); } .poiList { @@ -26,23 +27,20 @@ } .poiItem { - padding: var(--Spacing-x1) 0; - border-bottom: 1px solid var(--Base-Border-Subtle); + padding: var(--Space-x1) 0; + border-bottom: 1px solid var(--Border-Default); } .poiButton { - background-color: var(--Base-Surface-Primary-light-Normal); - border-width: 0; - font-family: var(--typography-Body-Regular-fontFamily); - font-size: var(--typography-Body-Regular-fontSize); - font-weight: var(--typography-Body-Regular-fontWeight); - color: var(--UI-Text-High-contrast); - width: 100%; display: grid; grid-template-columns: 1fr max-content; - gap: var(--Spacing-x2); align-items: center; - padding: var(--Spacing-x-half) var(--Spacing-x1); + gap: var(--Space-x2); + background-color: var(--Base-Surface-Primary-light-Normal); + border-width: 0; + color: var(--Text-Default); + width: 100%; + padding: var(--Space-x05) var(--Space-x1); border-radius: var(--Corner-radius-Medium); cursor: pointer; text-align: left; @@ -52,6 +50,10 @@ background-color: var(--Base-Surface-Primary-light-Hover); } +.title { + color: var(--Text-Heading); +} + @media screen and (max-width: 767px) { .sidebar { --sidebar-mobile-toggle-height: 84px; @@ -84,24 +86,27 @@ bottom: 0; } - button.sidebarToggle { + .sidebarToggle { position: relative; - margin-top: var(--Spacing-x4); - padding: var(--Spacing-x2) !important; + color: var(--Text-Secondary); + background-color: var(--Base-Surface-Primary-light-Normal); + border-width: 0; + margin-top: var(--Space-x4); + padding: var(--Space-x2); } - button.sidebarToggle::before { + .sidebarToggle::before { content: ""; position: absolute; display: block; top: -0.5rem; - width: 100px; + width: 46px; height: 3px; - background-color: var(--UI-Text-High-contrast); + background-color: var(--Icon-Interactive-Disabled); } .sidebarContent { - padding: var(--Spacing-x3) var(--Spacing-x2); + padding: var(--Space-x3) var(--Space-x2); height: var(--sidebar-mobile-content-height); } } @@ -115,12 +120,12 @@ background-color: var(--Base-Surface-Primary-light-Normal); } - button.sidebarToggle { + .sidebarToggle { display: none; } .sidebarContent { - padding: var(--Spacing-x4) var(--Spacing-x5) var(--Spacing-x9); + padding: var(--Space-x4) var(--Space-x5) var(--Space-x8); height: 100%; position: relative; } diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/dynamicMap.module.css b/apps/scandic-web/components/ContentType/HotelMapPage/hotelMapPage.module.css similarity index 56% rename from apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/dynamicMap.module.css rename to apps/scandic-web/components/ContentType/HotelMapPage/hotelMapPage.module.css index 7cdd02371..55f498af8 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/dynamicMap.module.css +++ b/apps/scandic-web/components/ContentType/HotelMapPage/hotelMapPage.module.css @@ -1,23 +1,17 @@ -.dynamicMap { +.mapWrapper { --hotel-map-height: 100dvh; - position: absolute; - top: 0; - left: 0; + position: fixed; + display: flex; height: var(--hotel-map-height); width: 100dvw; - z-index: var(--hotel-dynamic-map-z-index); - display: flex; background-color: var(--Base-Surface-Primary-light-Normal); -} -.wrapper { - position: absolute; - top: 0; - left: 0; + z-index: 1; } .closeButton { - pointer-events: initial; box-shadow: var(--button-box-shadow); - gap: var(--Spacing-x-half); + color: var(--Component-Button-Inverted-On-fill-Default); + pointer-events: initial; + gap: var(--Space-x05); } diff --git a/apps/scandic-web/components/ContentType/HotelMapPage/index.tsx b/apps/scandic-web/components/ContentType/HotelMapPage/index.tsx new file mode 100644 index 000000000..cdf549d28 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelMapPage/index.tsx @@ -0,0 +1,42 @@ +import { notFound } from "next/navigation" + +import { env } from "@/env/server" +import { getHotel, getHotelPage } from "@/lib/trpc/memoizedRequests" + +import { getLang } from "@/i18n/serverContext" + +import HotelMapPageClient from "./Client" + +interface HotelMapPageProps { + hotelId: string +} + +export default async function HotelMapPage({ hotelId }: HotelMapPageProps) { + const lang = getLang() + const hotelPageData = await getHotelPage() + const hotelData = await getHotel({ + hotelId, + isCardOnlyPayment: false, + language: lang, + }) + + if (!hotelPageData || !hotelData) { + notFound() + } + + const { name, location, pointsOfInterest } = hotelData.hotel + + const coordinates = { + lat: location.latitude, + lng: location.longitude, + } + return ( + + ) +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/index.tsx deleted file mode 100644 index c2455b3bc..000000000 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/DynamicMap/index.tsx +++ /dev/null @@ -1,142 +0,0 @@ -"use client" -import { APIProvider } from "@vis.gl/react-google-maps" -import { useRouter, useSearchParams } from "next/navigation" -import { useCallback, useEffect, useMemo, useRef, useState } from "react" -import { Dialog, Modal } from "react-aria-components" -import { useIntl } from "react-intl" - -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" - -import InteractiveMap from "@/components/Maps/InteractiveMap" -import Button from "@/components/TempDesignSystem/Button" -import { debounce } from "@/utils/debounce" - -import Sidebar from "./Sidebar" - -import styles from "./dynamicMap.module.css" - -import type { DynamicMapProps } from "@/types/components/hotelPage/map/dynamicMap" - -export default function DynamicMap({ - apiKey, - hotelName, - coordinates, - pointsOfInterest, - mapId, -}: DynamicMapProps) { - const intl = useIntl() - const router = useRouter() - const searchParams = useSearchParams() - const isMapView = useMemo( - () => searchParams.get("view") === "map", - [searchParams] - ) - const rootDiv = useRef(null) - const [mapHeight, setMapHeight] = useState("0px") - const [scrollHeightWhenOpened, setScrollHeightWhenOpened] = useState(0) - const [activePoi, setActivePoi] = useState(null) - - // Calculate the height of the map based on the viewport height from the start-point (below the header and booking widget) - const handleMapHeight = useCallback(() => { - const topPosition = rootDiv.current?.getBoundingClientRect().top ?? 0 - const scrollY = window.scrollY - setMapHeight(`calc(100dvh - ${topPosition + scrollY}px)`) - }, []) - - function handleClose() { - const url = new URL(window.location.href) - url.searchParams.delete("view") - router.push(url.toString()) - } - - // Making sure the map is always opened at the top of the page, - // just below the header and booking widget as these should stay visible. - // When closing, the page should scroll back to the position it was before opening the map. - useEffect(() => { - // Skip the first render - if (!rootDiv.current) { - return - } - - if (isMapView && scrollHeightWhenOpened === 0) { - const scrollY = window.scrollY - setScrollHeightWhenOpened(scrollY) - window.scrollTo({ top: 0, behavior: "instant" }) - } else if (!isMapView && scrollHeightWhenOpened !== 0) { - window.scrollTo({ top: scrollHeightWhenOpened, behavior: "instant" }) - setScrollHeightWhenOpened(0) - } - }, [isMapView, scrollHeightWhenOpened, rootDiv]) - - useEffect(() => { - const debouncedResizeHandler = debounce(function () { - handleMapHeight() - }) - - const observer = new ResizeObserver(debouncedResizeHandler) - - observer.observe(document.documentElement) - - return () => { - if (observer) { - observer.unobserve(document.documentElement) - } - } - }, [rootDiv, isMapView, handleMapHeight]) - - const closeButton = ( - - ) - - return ( - -
- - - setActivePoi(poi ?? null)} - coordinates={coordinates} - /> - setActivePoi(poi ?? null)} - mapId={mapId} - /> - - -
-
- ) -} diff --git a/apps/scandic-web/components/ContentType/HotelPage/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/index.tsx index 3468b1701..700884a75 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/index.tsx @@ -1,7 +1,6 @@ import { notFound } from "next/navigation" import { Suspense } from "react" -import { env } from "@/env/server" import { getHotel, getHotelPage, @@ -18,7 +17,6 @@ import { setFacilityCards } from "@/utils/facilityCards" import { generateHotelSchema } from "@/utils/jsonSchemas" import { safeTry } from "@/utils/safeTry" -import DynamicMap from "./Map/DynamicMap" import MapCard from "./Map/MapCard" import MapWithCardWrapper from "./Map/MapWithCard" import MobileMapToggle from "./Map/MobileMapToggle" @@ -65,9 +63,6 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { getMeetingRooms({ hotelId, language: lang }) ) - const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY - const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID - if (!hotelData?.hotel || !hotelPageData) { return notFound() } @@ -203,24 +198,13 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { )} - {googleMapsApiKey ? ( - <> - - - - - ) : null} + + - +

diff --git a/apps/scandic-web/components/Maps/Markers/Poi/poi.module.css b/apps/scandic-web/components/Maps/Markers/Poi/poi.module.css index 0a08151ef..c50de444e 100644 --- a/apps/scandic-web/components/Maps/Markers/Poi/poi.module.css +++ b/apps/scandic-web/components/Maps/Markers/Poi/poi.module.css @@ -1,11 +1,9 @@ -/* 2024-09-18: At the moment, the background-colors for the poi marker is unknown. -This will be handled later. */ - .icon { + width: 24px; + height: 24px; display: flex; justify-content: center; align-items: center; - padding: var(--Spacing-x-half); border-radius: var(--Corner-radius-Rounded); background-color: var(--UI-Text-Placeholder); } diff --git a/apps/scandic-web/types/params.ts b/apps/scandic-web/types/params.ts index cf35f41bf..ae2a69fcc 100644 --- a/apps/scandic-web/types/params.ts +++ b/apps/scandic-web/types/params.ts @@ -29,21 +29,6 @@ export type ContentTypeParams = { | PageContentTypeEnum.startPage } -// This is purely for use in `apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx` -// It is meant as an interim solution while we move away from the switch-case -// approach into routing these based on App router. -// Folders in `apps/scandic-web/app/[lang]/(live)/(public)` should not be in this type. -export type NonAppRouterContentTypeParams = { - contentType: - | PageContentTypeEnum.loyaltyPage - | PageContentTypeEnum.contentPage - | PageContentTypeEnum.hotelPage - | PageContentTypeEnum.collectionPage - | PageContentTypeEnum.destinationCountryPage - | PageContentTypeEnum.destinationCityPage - | PageContentTypeEnum.startPage -} - export type ContentTypeWebviewParams = { contentType: "loyalty-page" | "account-page" }