Merged in feature/refactor-lang (pull request #387)

feat: SW-238 Avoid prop drilling of lang

Approved-by: Michael Zetterberg
This commit is contained in:
Niclas Edenvin
2024-08-14 11:00:20 +00:00
parent 35128dbf44
commit e67212bd94
94 changed files with 378 additions and 322 deletions

View File

@@ -5,13 +5,11 @@ import { overview } from "@/constants/routes/myPages"
import { serverClient } from "@/lib/trpc/server"
import { auth } from "@/auth"
import type { LangParams, LayoutArgs } from "@/types/params"
import { getLang } from "@/i18n/serverContext"
export default async function ProtectedLayout({
children,
params,
}: React.PropsWithChildren<LayoutArgs<LangParams>>) {
}: React.PropsWithChildren) {
const session = await auth()
/**
* Fallback to make sure every route nested in the
@@ -19,16 +17,16 @@ export default async function ProtectedLayout({
*/
const h = headers()
const redirectTo = encodeURIComponent(
h.get("x-url") ?? h.get("x-pathname") ?? overview[params.lang]
h.get("x-url") ?? h.get("x-pathname") ?? overview[getLang()]
)
if (!session) {
redirect(`/${params.lang}/login?redirectTo=${redirectTo}`)
redirect(`/${getLang()}/login?redirectTo=${redirectTo}`)
}
const user = await serverClient().user.get()
if (!user || "error" in user) {
redirect(`/${params.lang}/login?redirectTo=${redirectTo}`)
redirect(`/${getLang()}/login?redirectTo=${redirectTo}`)
}
return children

View File

@@ -1,5 +1,10 @@
import Breadcrumbs from "@/components/MyPages/Breadcrumbs"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default function AllBreadcrumbs({ params }: PageArgs<LangParams>) {
setLang(params.lang)
export default function AllBreadcrumbs() {
return <Breadcrumbs />
}

View File

@@ -4,6 +4,7 @@ import Content from "@/components/MyPages/AccountPage/Content"
import Title from "@/components/TempDesignSystem/Text/Title"
import TrackingSDK from "@/components/TrackingSDK"
import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
@@ -12,6 +13,8 @@ import type { LangParams, PageArgs } from "@/types/params"
export default async function MyPages({
params,
}: PageArgs<LangParams & { path: string[] }>) {
setLang(params.lang)
const accountPageRes = await serverClient().contentstack.accountPage.get()
const { formatMessage } = await getIntl()
@@ -26,7 +29,7 @@ export default async function MyPages({
<main className={styles.blocks}>
<Title>{accountPage.heading}</Title>
{accountPage.content.length ? (
<Content lang={params.lang} content={accountPage.content} />
<Content content={accountPage.content} />
) : (
<p>{formatMessage({ id: "No content published" })}</p>
)}

View File

@@ -2,20 +2,17 @@ import Sidebar from "@/components/MyPages/Sidebar"
import styles from "./layout.module.css"
import { LangParams, LayoutArgs } from "@/types/params"
export default async function MyPagesLayout({
breadcrumbs,
children,
params,
}: React.PropsWithChildren<LayoutArgs<LangParams>> & {
}: React.PropsWithChildren & {
breadcrumbs: React.ReactNode
}) {
return (
<section className={styles.layout}>
{breadcrumbs}
<section className={styles.content}>
<Sidebar lang={params.lang} />
<Sidebar />
{children}
</section>
</section>

View File

@@ -3,10 +3,17 @@ import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
export default async function CommunicationSlot() {
import { LangParams, PageArgs } from "@/types/params"
export default async function CommunicationSlot({
params,
}: PageArgs<LangParams>) {
setLang(params.lang)
const { formatMessage } = await getIntl()
return (
<section className={styles.container}>

View File

@@ -7,10 +7,14 @@ import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
export default async function CreditCardSlot() {
import { LangParams, PageArgs } from "@/types/params"
export default async function CreditCardSlot({ params }: PageArgs<LangParams>) {
setLang(params.lang)
const { formatMessage } = await getIntl()
const creditCards = await serverClient().user.creditCards()

View File

@@ -5,10 +5,16 @@ import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
export default async function MembershipCardSlot() {
import { LangParams, PageArgs } from "@/types/params"
export default async function MembershipCardSlot({
params,
}: PageArgs<LangParams>) {
setLang(params.lang)
const { formatMessage } = await getIntl()
const membershipCards = await serverClient().user.membershipCards()

View File

@@ -1,8 +1,15 @@
import { serverClient } from "@/lib/trpc/server"
import Form from "@/components/Forms/Edit/Profile"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default async function EditProfileSlot({
params,
}: PageArgs<LangParams>) {
setLang(params.lang)
export default async function EditProfileSlot() {
const user = await serverClient().user.get({ mask: false })
if (!user || "error" in user) {
return null

View File

@@ -16,12 +16,14 @@ import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import { getLang, setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
import type { LangParams, PageArgs } from "@/types/params"
import { LangParams, PageArgs } from "@/types/params"
export default async function Profile({ params }: PageArgs<LangParams>) {
setLang(params.lang)
const { formatMessage } = await getIntl()
const user = await serverClient().user.get()
if (!user || "error" in user) {
@@ -40,7 +42,7 @@ export default async function Profile({ params }: PageArgs<LangParams>) {
</Title>
</hgroup>
<Button asChild intent="primary" size="small" theme="base">
<Link color="none" href={profileEdit[params.lang]}>
<Link color="none" href={profileEdit[getLang()]}>
{formatMessage({ id: "Edit profile" })}
</Link>
</Button>

View File

@@ -3,8 +3,12 @@ import "./profileLayout.css"
import { serverClient } from "@/lib/trpc/server"
import TrackingSDK from "@/components/TrackingSDK"
import { setLang } from "@/i18n/serverContext"
export default async function ProfilePage() {
import { LangParams, PageArgs } from "@/types/params"
export default async function ProfilePage({ params }: PageArgs<LangParams>) {
setLang(params.lang)
const accountPage = await serverClient().contentstack.accountPage.get()
if (!accountPage) {

View File

@@ -1,5 +1,10 @@
import Breadcrumbs from "@/components/MyPages/Breadcrumbs"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default function PageBreadcrumbs({ params }: PageArgs<LangParams>) {
setLang(params.lang)
export default function PageBreadcrumbs() {
return <Breadcrumbs />
}

View File

@@ -3,6 +3,7 @@ import { notFound } from "next/navigation"
import ContentPage from "@/components/ContentType/ContentPage"
import HotelPage from "@/components/ContentType/HotelPage/HotelPage"
import LoyaltyPage from "@/components/ContentType/LoyaltyPage/LoyaltyPage"
import { setLang } from "@/i18n/serverContext"
import {
ContentTypeParams,
@@ -14,13 +15,15 @@ import {
export default async function ContentTypePage({
params,
}: PageArgs<LangParams & ContentTypeParams & UIDParams, {}>) {
setLang(params.lang)
switch (params.contentType) {
case "content-page":
return <ContentPage />
case "loyalty-page":
return <LoyaltyPage lang={params.lang} />
return <LoyaltyPage />
case "hotel-page":
return <HotelPage lang={params.lang} />
return <HotelPage />
default:
const type: never = params.contentType
console.error(`Unsupported content type given: ${type}`)

View File

@@ -1,5 +1,9 @@
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default function HotelReservationPage({ params }: PageArgs<LangParams>) {
setLang(params.lang)
return null
}

View File

@@ -6,6 +6,7 @@ import { ChevronRightIcon } from "@/components/Icons"
import StaticMap from "@/components/Maps/StaticMap"
import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n"
import { getLang, setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
@@ -15,10 +16,11 @@ export default async function SelectHotelPage({
params,
}: PageArgs<LangParams>) {
const intl = await getIntl()
setLang(params.lang)
const { attributes } = await serverClient().hotel.getHotel({
hotelId: "d98c7ab1-ebaa-4102-b351-758daf1ddf55",
language: params.lang,
language: getLang(),
})
const hotels = [attributes]

View File

@@ -5,16 +5,19 @@ import BedSelection from "@/components/HotelReservation/SelectRate/BedSelection"
import BreakfastSelection from "@/components/HotelReservation/SelectRate/BreakfastSelection"
import FlexibilitySelection from "@/components/HotelReservation/SelectRate/FlexibilitySelection"
import RoomSelection from "@/components/HotelReservation/SelectRate/RoomSelection"
import { getLang, setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
import { LangParams, PageArgs } from "@/types/params"
export default async function SelectRate({ params }: PageArgs<LangParams>) {
setLang(params.lang)
// TODO: pass the correct hotel ID
const { attributes: hotel } = await serverClient().hotel.getHotel({
hotelId: "d98c7ab1-ebaa-4102-b351-758daf1ddf55",
language: params.lang,
language: getLang(),
})
const rooms = await serverClient().hotel.getRates({
// TODO: pass the correct hotel ID and all other parameters that should be included in the search

View File

@@ -1,14 +1,9 @@
"use client"
import { useParams } from "next/navigation"
import { baseUrls } from "@/constants/routes/baseUrls"
import LanguageSwitcher from "@/components/Current/Header/LanguageSwitcher"
import { LangParams } from "@/types/params"
export default function Error() {
const params = useParams<LangParams>()
return <LanguageSwitcher urls={baseUrls} lang={params.lang} />
return <LanguageSwitcher urls={baseUrls} />
}

View File

@@ -1,11 +1,18 @@
import { serverClient } from "@/lib/trpc/server"
import LanguageSwitcher from "@/components/Current/Header/LanguageSwitcher"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default async function LanguageSwitcherRoute({
params,
}: PageArgs<LangParams>) {
setLang(params.lang)
export default async function LanguageSwitcherRoute() {
const data = await serverClient().contentstack.languageSwitcher.get()
if (!data) {
return null
}
return <LanguageSwitcher urls={data.urls} lang={data.lang} />
return <LanguageSwitcher urls={data.urls} />
}

View File

@@ -1,13 +1,15 @@
import { serverClient } from "@/lib/trpc/server"
import MyPagesMobileDropdown from "@/components/Current/Header/MyPagesMobileDropdown"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default async function MyPagesMobileDropdownPage({
params,
}: PageArgs<LangParams>) {
setLang(params.lang)
const navigation = await serverClient().contentstack.myPages.navigation.get()
if (!navigation) return null
return <MyPagesMobileDropdown navigation={navigation} lang={params.lang} />
return <MyPagesMobileDropdown navigation={navigation} />
}

View File

@@ -1,17 +1,13 @@
import Header from "@/components/Current/Header"
import { LangParams, PageArgs } from "@/types/params"
export default function HeaderLayout({
params,
languageSwitcher,
myPagesMobileDropdown,
}: PageArgs<LangParams> & {
}: {
languageSwitcher: React.ReactNode
} & { myPagesMobileDropdown: React.ReactNode }) {
return (
<Header
lang={params.lang}
myPagesMobileDropdown={myPagesMobileDropdown}
languageSwitcher={languageSwitcher}
/>

View File

@@ -4,18 +4,18 @@ import { serverClient } from "@/lib/trpc/server"
import Header from "@/components/Current/Header"
import LanguageSwitcher from "@/components/Current/Header/LanguageSwitcher"
import MyPagesMobileDropdown from "@/components/Current/Header/MyPagesMobileDropdown"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default async function HeaderPage({ params }: PageArgs<LangParams>) {
setLang(params.lang)
const navigation = await serverClient().contentstack.myPages.navigation.get()
return (
<Header
lang={params.lang}
myPagesMobileDropdown={
<MyPagesMobileDropdown navigation={navigation} lang={params.lang} />
}
languageSwitcher={<LanguageSwitcher urls={baseUrls} lang={params.lang} />}
myPagesMobileDropdown={<MyPagesMobileDropdown navigation={navigation} />}
languageSwitcher={<LanguageSwitcher urls={baseUrls} />}
/>
)
}

View File

@@ -11,6 +11,7 @@ import VwoScript from "@/components/Current/VwoScript"
import { preloadUserTracking } from "@/components/TrackingSDK"
import { getIntl } from "@/i18n"
import ServerIntlProvider from "@/i18n/Provider"
import { getLang, setLang } from "@/i18n/serverContext"
import type { Metadata } from "next"
@@ -30,11 +31,12 @@ export default async function RootLayout({
header: React.ReactNode
}
>) {
setLang(params.lang)
preloadUserTracking()
const { defaultLocale, locale, messages } = await getIntl()
return (
<html lang={params.lang}>
<html lang={getLang()}>
<head>
<AdobeSDKScript />
<Script data-cookieconsent="ignore" src="/_static/js/cookie-bot.js" />
@@ -53,10 +55,10 @@ export default async function RootLayout({
</head>
<body>
<ServerIntlProvider intl={{ defaultLocale, locale, messages }}>
<TrpcProvider lang={params.lang}>
<TrpcProvider>
{header}
{children}
<Footer lang={params.lang} />
<Footer />
</TrpcProvider>
</ServerIntlProvider>
</body>

View File

@@ -1,11 +1,10 @@
import { Lang } from "@/constants/languages"
import NotFound from "@/components/Current/NotFound"
import { setLang } from "@/i18n/serverContext"
import { LangParams, PageArgs } from "@/types/params"
export default function NotFoundPage({ params }: PageArgs<LangParams>) {
const lang = params.lang || Lang.en
setLang(params.lang)
return <NotFound lang={lang} />
return <NotFound />
}

View File

@@ -1,3 +1,5 @@
import { getLang, setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
import { LangParams, LayoutArgs, StatusParams } from "@/types/params"
@@ -5,9 +7,11 @@ import { LangParams, LayoutArgs, StatusParams } from "@/types/params"
export default function MiddlewareError({
params,
}: LayoutArgs<LangParams & StatusParams>) {
setLang(params.lang)
return (
<div className={styles.layout}>
Middleware Error {params.lang}: {params.status}
Middleware Error {getLang()}: {params.status}
</div>
)
}

View File

@@ -1,6 +1,10 @@
import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
export default async function NotFound() {
import { LangParams, PageArgs } from "@/types/params"
export default async function NotFound({ params }: PageArgs<LangParams>) {
setLang(params.lang)
const { formatMessage } = await getIntl()
return (
<main>