mirror of
https://github.com/vercel/commerce.git
synced 2025-05-15 14:06:59 +00:00
Locale switcher updates
This commit is contained in:
parent
4327a10dc9
commit
5c2f3d5e3e
@ -15,6 +15,9 @@ import ProductPage from './product-page';
|
|||||||
import ProductPagePreview from './product-page-preview';
|
import ProductPagePreview from './product-page-preview';
|
||||||
import SinglePage from './single-page';
|
import SinglePage from './single-page';
|
||||||
import SinglePagePreview from './single-page-preview';
|
import SinglePagePreview from './single-page-preview';
|
||||||
|
// Chrome
|
||||||
|
import Footer from 'components/layout/footer';
|
||||||
|
import Header from 'components/layout/header';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render pages depending on type.
|
* Render pages depending on type.
|
||||||
@ -30,24 +33,40 @@ export default async function Page({ params }: { params: { slug: string[]; local
|
|||||||
|
|
||||||
const data = filterDataToSingleItem(pageData, isEnabled);
|
const data = filterDataToSingleItem(pageData, isEnabled);
|
||||||
|
|
||||||
if (isEnabled) {
|
const localeData = {
|
||||||
|
type: data._type,
|
||||||
|
locale: data.locale,
|
||||||
|
translations: data.translations
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Header localeData={localeData} />
|
||||||
|
<main className="flex-1">
|
||||||
|
<article>
|
||||||
|
{isEnabled ? (
|
||||||
<PreviewSuspense fallback="Loading...">
|
<PreviewSuspense fallback="Loading...">
|
||||||
{docType === 'home' && <HomePagePreview query={query} queryParams={queryParams} />}
|
{docType === 'home' && <HomePagePreview query={query} queryParams={queryParams} />}
|
||||||
{docType === 'page' && <SinglePagePreview query={query} queryParams={queryParams} />}
|
{docType === 'page' && <SinglePagePreview query={query} queryParams={queryParams} />}
|
||||||
{docType === 'product' && <ProductPagePreview query={query} queryParams={queryParams} />}
|
{docType === 'product' && (
|
||||||
{docType === 'category' && <CategoryPagePreview query={query} queryParams={queryParams} />}
|
<ProductPagePreview query={query} queryParams={queryParams} />
|
||||||
|
)}
|
||||||
|
{docType === 'category' && (
|
||||||
|
<CategoryPagePreview query={query} queryParams={queryParams} />
|
||||||
|
)}
|
||||||
</PreviewSuspense>
|
</PreviewSuspense>
|
||||||
);
|
) : (
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
<>
|
||||||
{docType === 'home' && <HomePage data={data} />}
|
{docType === 'home' && <HomePage data={data} />}
|
||||||
{docType === 'product' && <ProductPage data={data} />}
|
{docType === 'product' && <ProductPage data={data} />}
|
||||||
{docType === 'category' && <CategoryPage data={data} />}
|
{docType === 'category' && <CategoryPage data={data} />}
|
||||||
{docType === 'page' && <SinglePage data={data} />}
|
{docType === 'page' && <SinglePage data={data} />}
|
||||||
</>
|
</>
|
||||||
|
)}
|
||||||
|
</article>
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import Footer from 'components/layout/footer';
|
|
||||||
import Header from 'components/layout/header';
|
|
||||||
import { NextIntlClientProvider } from 'next-intl';
|
import { NextIntlClientProvider } from 'next-intl';
|
||||||
import { Inter } from 'next/font/google';
|
import { Inter } from 'next/font/google';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
@ -10,8 +8,6 @@ const SITE_NAME = 'KM Storefront';
|
|||||||
const SITE_DESCRIPTION = 'Webb och digitalbyrå från Göteborg';
|
const SITE_DESCRIPTION = 'Webb och digitalbyrå från Göteborg';
|
||||||
const TWITTER_CREATOR = '@kodamera.se';
|
const TWITTER_CREATOR = '@kodamera.se';
|
||||||
const TWITTER_SITE = 'https://kodamera.se';
|
const TWITTER_SITE = 'https://kodamera.se';
|
||||||
const OG_IMAGE_URL = '/og-image.jpg';
|
|
||||||
const OG_IMAGE_ALT = 'Kodamera';
|
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: {
|
title: {
|
||||||
@ -19,16 +15,6 @@ export const metadata = {
|
|||||||
template: `%s | ${SITE_NAME}`
|
template: `%s | ${SITE_NAME}`
|
||||||
},
|
},
|
||||||
description: SITE_DESCRIPTION,
|
description: SITE_DESCRIPTION,
|
||||||
openGraph: {
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url: OG_IMAGE_URL,
|
|
||||||
width: 1200,
|
|
||||||
height: 630,
|
|
||||||
alt: OG_IMAGE_ALT
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
robots: {
|
robots: {
|
||||||
follow: true,
|
follow: true,
|
||||||
index: true
|
index: true
|
||||||
@ -73,9 +59,7 @@ export default async function LocaleLayout({ children, params: { locale } }: Loc
|
|||||||
<html lang={locale} className={inter.variable}>
|
<html lang={locale} className={inter.variable}>
|
||||||
<body className="flex min-h-screen flex-col">
|
<body className="flex min-h-screen flex-col">
|
||||||
<NextIntlClientProvider locale={locale} messages={messages}>
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
||||||
<Header />
|
{children}
|
||||||
<main className="flex-1">{children}</main>
|
|
||||||
<Footer />
|
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,63 +1,64 @@
|
|||||||
'use client'
|
'use client';
|
||||||
|
|
||||||
import LocaleSwitcher from 'components/ui/locale-switcher/locale-switcher'
|
import LocaleSwitcher from 'components/ui/locale-switcher/locale-switcher';
|
||||||
import Logo from 'components/ui/logo/logo'
|
import Logo from 'components/ui/logo/logo';
|
||||||
import {
|
import {
|
||||||
NavigationMenu,
|
NavigationMenu,
|
||||||
NavigationMenuItem,
|
NavigationMenuItem,
|
||||||
NavigationMenuLink,
|
NavigationMenuLink,
|
||||||
NavigationMenuList,
|
NavigationMenuList,
|
||||||
navigationMenuTriggerStyle,
|
navigationMenuTriggerStyle
|
||||||
} from 'components/ui/navigation-menu'
|
} from 'components/ui/navigation-menu';
|
||||||
import Link from 'next/link'
|
import { useLocale } from 'next-intl';
|
||||||
import { FC } from 'react'
|
import Link from 'next/link';
|
||||||
import HeaderRoot from './header-root'
|
import { FC } from 'react';
|
||||||
|
import HeaderRoot from './header-root';
|
||||||
|
|
||||||
interface HeaderProps {}
|
interface HeaderProps {
|
||||||
|
localeData: {
|
||||||
|
type: string;
|
||||||
|
locale: string;
|
||||||
|
translations: [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const Header: FC<HeaderProps> = () => {
|
const Header: FC<HeaderProps> = ({ localeData }: HeaderProps) => {
|
||||||
|
const locale = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HeaderRoot>
|
<HeaderRoot>
|
||||||
<div className="relative flex flex-col">
|
<div className="relative flex flex-col">
|
||||||
<div className="relative flex items-center w-full justify-between py-2 px-4 h-14 lg:h-16 lg:py-3 lg:px-8 2xl:px-16">
|
<div className="relative flex h-14 w-full items-center justify-between px-4 py-2 lg:h-16 lg:px-8 lg:py-3 2xl:px-16">
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href={`/${locale}`}
|
||||||
className="cursor-pointer duration-100 ease-in-out absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 lg:relative lg:left-0 lg:top-0 lg:translate-x-0 lg:translate-y-0"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform cursor-pointer duration-100 ease-in-out lg:relative lg:left-0 lg:top-0 lg:translate-x-0 lg:translate-y-0"
|
||||||
aria-label="Logo"
|
aria-label="Logo"
|
||||||
>
|
>
|
||||||
<Logo />
|
<Logo />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="absolute transform left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
|
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform">
|
||||||
<NavigationMenu delayDuration={0} className="hidden lg:block">
|
<NavigationMenu delayDuration={0} className="hidden lg:block">
|
||||||
<NavigationMenuList>
|
<NavigationMenuList>
|
||||||
<NavigationMenuItem>
|
<NavigationMenuItem>
|
||||||
<Link href={'/kategori/junior'} legacyBehavior passHref>
|
<Link href={'/kategori/junior'} legacyBehavior passHref>
|
||||||
<NavigationMenuLink
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
|
||||||
className={navigationMenuTriggerStyle()}
|
|
||||||
>
|
|
||||||
Junior
|
Junior
|
||||||
</NavigationMenuLink>
|
</NavigationMenuLink>
|
||||||
</Link>
|
</Link>
|
||||||
</NavigationMenuItem>
|
</NavigationMenuItem>
|
||||||
<NavigationMenuItem>
|
<NavigationMenuItem>
|
||||||
<Link href={'/kategori/trojor'} legacyBehavior passHref>
|
<Link href={'/kategori/trojor'} legacyBehavior passHref>
|
||||||
<NavigationMenuLink
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
|
||||||
className={navigationMenuTriggerStyle()}
|
|
||||||
>
|
|
||||||
Tröjor
|
Tröjor
|
||||||
</NavigationMenuLink>
|
</NavigationMenuLink>
|
||||||
</Link>
|
</Link>
|
||||||
</NavigationMenuItem>
|
</NavigationMenuItem>
|
||||||
<NavigationMenuItem>
|
<NavigationMenuItem>
|
||||||
<Link href={'/kategori/byxor'} legacyBehavior passHref>
|
<Link href={'/kategori/byxor'} legacyBehavior passHref>
|
||||||
<NavigationMenuLink
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
|
||||||
className={navigationMenuTriggerStyle()}
|
|
||||||
>
|
|
||||||
Byxor
|
Byxor
|
||||||
</NavigationMenuLink>
|
</NavigationMenuLink>
|
||||||
</Link>
|
</Link>
|
||||||
@ -66,12 +67,12 @@ const Header: FC<HeaderProps> = () => {
|
|||||||
</NavigationMenu>
|
</NavigationMenu>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<LocaleSwitcher />
|
<LocaleSwitcher localeData={localeData} currentLocale={locale} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</HeaderRoot>
|
</HeaderRoot>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Header
|
export default Header;
|
||||||
|
@ -10,20 +10,34 @@ import { useState } from 'react';
|
|||||||
import { i18n } from '../../../i18n-config';
|
import { i18n } from '../../../i18n-config';
|
||||||
|
|
||||||
interface LocaleSwitcherProps {
|
interface LocaleSwitcherProps {
|
||||||
current: string;
|
currentLocale: string;
|
||||||
pageData: object;
|
localeData: {
|
||||||
|
type: string;
|
||||||
|
locale: string;
|
||||||
|
translations: [];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LocaleSwitcher({ current, pageData }: LocaleSwitcherProps) {
|
export default function LocaleSwitcher({ currentLocale, localeData }: LocaleSwitcherProps) {
|
||||||
const pathName = usePathname();
|
const pathName = usePathname();
|
||||||
|
const translations = localeData.translations;
|
||||||
console.log(pageData);
|
|
||||||
|
|
||||||
const redirectedPathName = (locale: string) => {
|
const redirectedPathName = (locale: string) => {
|
||||||
if (!pathName) return '/';
|
if (!pathName || translations.length === 0) return '/';
|
||||||
const segments = pathName.split('/');
|
|
||||||
segments[1] = locale;
|
if (translations.length > 0) {
|
||||||
return segments.join('/');
|
const translation = translations.find((obj) => {
|
||||||
|
return obj['locale'] === locale;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (translation) {
|
||||||
|
const url = `/${translation['locale']}${translation['slug']}`;
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
@ -34,18 +48,18 @@ export default function LocaleSwitcher({ current, pageData }: LocaleSwitcherProp
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button
|
<button
|
||||||
className={
|
className={
|
||||||
'flex shrink-0 items-center justify-center space-x-1 rounded bg-app p-2 text-sm font-bold uppercase outline-none ring-2 ring-transparent transition duration-200 hover:ring-ui-border focus:ring-ui-border'
|
'flex shrink-0 items-center justify-center space-x-1 rounded bg-app p-2 text-xs font-bold uppercase outline-none ring-2 ring-transparent transition duration-200 hover:ring-ui-border focus:ring-ui-border'
|
||||||
}
|
}
|
||||||
aria-label="Language selector"
|
aria-label="Language selector"
|
||||||
>
|
>
|
||||||
<LanguageIcon className="h-6 w-6" />
|
<LanguageIcon className="h-6 w-6" />
|
||||||
<span>{current}</span>
|
<span>{currentLocale}</span>
|
||||||
</button>
|
</button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end" className="drop-shadow-xl">
|
<DropdownMenuContent align="end" className="drop-shadow-xl">
|
||||||
<ul className="">
|
<ul className="">
|
||||||
{i18n.locales.map((locale) => {
|
{i18n.locales.map((locale) => {
|
||||||
if (current === locale.id) {
|
if (currentLocale === locale.id) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
@ -160,7 +160,7 @@ export const reusableSection = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
// Homepage query
|
// Homepage query
|
||||||
export const homePageQuery = `*[_type == "home" && slug.current == "/" && language == $locale][0] {
|
export const homePageQuery = `*[_type == "home" && language == $locale][0] {
|
||||||
_type,
|
_type,
|
||||||
title,
|
title,
|
||||||
"slug": slug.current,
|
"slug": slug.current,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user