Skip to content

Commit

Permalink
feat(i18): replace useLanguage hook with server-side page data transl…
Browse files Browse the repository at this point in the history
…ations
  • Loading branch information
mathiazom committed Oct 16, 2024
1 parent ee5bd74 commit c9e00be
Show file tree
Hide file tree
Showing 15 changed files with 341 additions and 335 deletions.
115 changes: 62 additions & 53 deletions src/app/(main)/[lang]/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import CustomerCasesPreview from "src/components/customerCases/CustomerCasesPrev
import CustomErrorMessage from "src/components/customErrorMessage/CustomErrorMessage";
import Legal from "src/components/legal/Legal";
import LegalPreview from "src/components/legal/LegalPreview";
import PageHeader from "src/components/navigation/header/PageHeader";
import { homeLink } from "src/components/utils/linkTypes";
import { getDraftModeInfo } from "src/utils/draftmode";
import { fetchPageDataFromParams } from "src/utils/pageData";
Expand Down Expand Up @@ -77,60 +78,68 @@ async function Page({ params }: Props) {
return Page404;
}

const { queryResponse, docType } = pageData;
const { queryResponse, docType, pathTranslations } = pageData;

switch (docType) {
case "pageBuilder":
return (
<>
{queryResponse.data?.sections?.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={queryResponse}
isLandingPage={false}
sectionIndex={index}
/>
))}
</>
);
case "compensations":
return isDraftMode ? (
<CompensationsPreview
initialCompensations={queryResponse.compensationsPage}
initialLocations={queryResponse.companyLocations}
initialLocale={queryResponse.locale}
/>
) : (
<Compensations
compensations={queryResponse.compensationsPage.data}
locations={queryResponse.companyLocations.data}
locale={queryResponse.locale.data}
/>
);
case "customerCasesPage":
return isDraftMode ? (
<CustomerCasesPreview initialCustomerCases={queryResponse} />
) : (
<CustomerCases customerCasesPage={queryResponse.data} />
);
case "customerCase":
return (
// TODO: implement customer case detail page
<pre style={{ background: "hotpink", marginTop: "8rem" }}>
{JSON.stringify(pageData, null, 2)}
</pre>
);
case "legalDocument":
return isDraftMode ? (
<LegalPreview initialDocument={queryResponse} />
) : (
<Legal document={queryResponse.data} />
);
}

return Page404;
return (
<>
<PageHeader language={lang} pathTranslations={pathTranslations} />
<main id={"main"} tabIndex={-1}>
{(() => {
switch (docType) {
case "pageBuilder":
return (
<>
{queryResponse.data?.sections?.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={queryResponse}
isLandingPage={false}
sectionIndex={index}
/>
))}
</>
);
case "compensations":
return isDraftMode ? (
<CompensationsPreview
initialCompensations={queryResponse.compensationsPage}
initialLocations={queryResponse.companyLocations}
initialLocale={queryResponse.locale}
/>
) : (
<Compensations
compensations={queryResponse.compensationsPage.data}
locations={queryResponse.companyLocations.data}
locale={queryResponse.locale.data}
/>
);
case "customerCasesPage":
return isDraftMode ? (
<CustomerCasesPreview initialCustomerCases={queryResponse} />
) : (
<CustomerCases customerCasesPage={queryResponse.data} />
);
case "customerCase":
return (
// TODO: implement customer case detail page
<pre style={{ background: "hotpink", marginTop: "8rem" }}>
{JSON.stringify(pageData, null, 2)}
</pre>
);
case "legalDocument":
return isDraftMode ? (
<LegalPreview initialDocument={queryResponse} />
) : (
<Legal document={queryResponse.data} />
);
}
return Page404;
})()}
</main>
</>
);
}

export default Page;
37 changes: 1 addition & 36 deletions src/app/(main)/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { draftMode } from "next/headers";

import Footer from "src/components/navigation/footer/Footer";
import FooterPreview from "src/components/navigation/footer/FooterPreview";
import { Header } from "src/components/navigation/header/Header";
import HeaderPreview from "src/components/navigation/header/HeaderPreview";
import SkipToMain from "src/components/skipToMain/SkipToMain";
import { getDraftModeInfo } from "src/utils/draftmode";
import { BrandAssets } from "studio/lib/interfaces/brandAssets";
Expand All @@ -24,8 +22,6 @@ import {
} from "studio/lib/queries/siteSettings";
import { loadStudioQuery } from "studio/lib/store";

import styles from "./layout.module.css";

import "src/styles/global.css";

const fontBrittiSans = localFont({
Expand Down Expand Up @@ -73,45 +69,14 @@ export default async function Layout({
]);

const hasNavData = hasValidData(initialNav.data);
const hasCompanyInfoData = hasValidData(initialCompanyInfo.data);

const hasHeaderData =
hasNavData && (initialNav.data.main || initialNav.data.sidebar);

const hasFooterData = hasNavData && initialNav.data.footer;
const hasMenuData = hasCompanyInfoData && (hasHeaderData || hasFooterData);

if (!hasMenuData) {
return (
<html lang={params.lang}>
<body className={fontBrittiSans.variable}>
<main
id="main"
tabIndex={-1}
className={styles.offsetForStickyHeader}
>
{children}
</main>
</body>
</html>
);
}

return (
<html lang={params.lang}>
<body className={fontBrittiSans.variable}>
<SkipToMain />
{hasHeaderData && isDraftMode ? (
<HeaderPreview
initialNav={initialNav}
initialBrandAssets={initialBrandAssets}
/>
) : (
<Header data={initialNav.data} assets={initialBrandAssets.data} />
)}
<main id="main" tabIndex={-1}>
{children}
</main>
{children}
{hasFooterData && isDraftMode ? (
<FooterPreview
initialNav={initialNav}
Expand Down
45 changes: 34 additions & 11 deletions src/app/(main)/[lang]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { Metadata } from "next";

import InformationSection from "src/components/informationSection/InformationSection";
import PageHeader from "src/components/navigation/header/PageHeader";
import { getDraftModeInfo } from "src/utils/draftmode";
import SectionRenderer from "src/utils/renderSection";
import { generateMetadataFromSeo } from "src/utils/seo";
import { InternationalizedString } from "studio/lib/interfaces/global";
import { LinkType } from "studio/lib/interfaces/navigation";
import { PageBuilder } from "studio/lib/interfaces/pages";
import { LANDING_PAGE_QUERY } from "studio/lib/queries/siteSettings";
import { LanguageObject } from "studio/lib/interfaces/supportedLanguages";
import {
LANDING_PAGE_QUERY,
LANGUAGES_QUERY,
} from "studio/lib/queries/siteSettings";
import { loadStudioQuery } from "studio/lib/store";

export async function generateMetadata({ params }: Props): Promise<Metadata> {
Expand Down Expand Up @@ -57,16 +63,33 @@ const Home = async ({ params }: Props) => {
data: initialLandingPage.data,
};

return initialLandingPage.data.sections.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={initialData}
isLandingPage={true}
sectionIndex={index}
/>
));
const languages = await loadStudioQuery<LanguageObject[] | null>(
LANGUAGES_QUERY,
);

const pathTranslations: InternationalizedString =
languages?.data?.map((language) => ({
_key: language.id,
value: "",
})) ?? [];

return (
<>
<PageHeader language={params.lang} pathTranslations={pathTranslations} />
<main id={"main"} tabIndex={-1}>
{initialLandingPage.data.sections.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={initialData}
isLandingPage={true}
sectionIndex={index}
/>
))}
</main>
</>
);
};

export default Home;
44 changes: 20 additions & 24 deletions src/components/languageSwitcher/LanguageSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,42 @@ import Link from "next/link";
import { Fragment } from "react";

import Text from "src/components/text/Text";
import useLanguage from "src/utils/hooks/useLanguage";
import { InternationalizedString } from "studio/lib/interfaces/global";

import styles from "./languageSwitcher.module.css";

export default function LanguageSwitcher() {
const { slugTranslations, language, defaultLanguage } = useLanguage();

const currentLanguage = language ?? defaultLanguage;

// make sure the current language is the first item in the languages list
const sortedTranslations = slugTranslations?.toSorted((a, b) =>
a?.language?.id === currentLanguage?.id
? -1
: b?.language?.id === currentLanguage?.id
? 1
: 0,
);
export interface LanguageSwitcherProps {
currentLanguage: string;
pathTranslations: InternationalizedString;
}

export default function LanguageSwitcher({
currentLanguage,
pathTranslations,
}: LanguageSwitcherProps) {
return (
<ul className={styles.list}>
{sortedTranslations?.map((slugTranslation, index) => {
if (slugTranslation?.language === undefined) {
{pathTranslations?.map((pathTranslation, index) => {
if (pathTranslation._key === undefined) {
return null;
}
const linkText = (
<Text type={"small"}>
{slugTranslation.language.id.toUpperCase()}
</Text>
<Text type={"small"}>{pathTranslation._key.toUpperCase()}</Text>
);
return (
<Fragment key={slugTranslation.language.id}>
<Fragment key={pathTranslation._key}>
<li>
{currentLanguage === undefined ||
slugTranslation.language.id !== currentLanguage.id ? (
<Link href={slugTranslation.slug}>{linkText}</Link>
{pathTranslation._key !== currentLanguage ? (
<Link
href={`/${pathTranslation._key}/${pathTranslation.value}`}
>
{linkText}
</Link>
) : (
linkText
)}
</li>
{index < sortedTranslations.length - 1 && (
{index < pathTranslations.length - 1 && (
<span className={styles.divider}></span>
)}
</Fragment>
Expand Down
11 changes: 9 additions & 2 deletions src/components/navigation/header/Header.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Meta, StoryObj } from "@storybook/react";

import { mockLogo, mockNavigation } from "src/components/navigation/mockData";
import { defaultLanguage } from "i18n/supportedLanguages";
import {
mockLogo,
mockNavigation,
mockPathTranslations,
} from "src/components/navigation/mockData";

import { Header } from "./Header";

Expand All @@ -23,7 +28,9 @@ type Story = StoryObj<typeof Header>;

export const Default: Story = {
args: {
data: mockNavigation,
navigation: mockNavigation,
assets: mockLogo,
currentLanguage: defaultLanguage?.id ?? "en",
pathTranslations: mockPathTranslations,
},
};
Loading

0 comments on commit c9e00be

Please sign in to comment.