fix(SW-705): Updated logic for language switcher

This commit is contained in:
Pontus Dreij
2024-11-29 17:03:20 +01:00
parent 9d4c6eb25d
commit 89c131e3eb
6 changed files with 33 additions and 41 deletions

View File

@@ -1,6 +1,5 @@
"use client" "use client"
import { usePathname } from "next/navigation" import { usePathname } from "next/navigation"
import { Suspense } from "react"
import { useIntl } from "react-intl" import { useIntl } from "react-intl"
import { logout } from "@/constants/routes/handleAuth" import { logout } from "@/constants/routes/handleAuth"
@@ -10,7 +9,6 @@ import useDropdownStore from "@/stores/main-menu"
import Image from "@/components/Image" import Image from "@/components/Image"
import LoginButton from "@/components/LoginButton" import LoginButton from "@/components/LoginButton"
import Avatar from "@/components/MyPages/Avatar" import Avatar from "@/components/MyPages/Avatar"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
import useLang from "@/hooks/useLang" import useLang from "@/hooks/useLang"
import { trackClick } from "@/utils/tracking" import { trackClick } from "@/utils/tracking"
@@ -190,13 +188,7 @@ export function MainMenu({
))} ))}
</ul> </ul>
{languageSwitcher ? ( {languageSwitcher ? (
<li className={styles.mobileLi}> <li className={styles.mobileLi}>{languageSwitcher}</li>
<Suspense
fallback={<SkeletonShimmer height="20px" width="10ch" />}
>
{languageSwitcher}
</Suspense>
</li>
) : null} ) : null}
{!!user ? ( {!!user ? (
<li className={`${styles.mobileLi} ${styles.logout}`}> <li className={`${styles.mobileLi} ${styles.logout}`}>

View File

@@ -1,11 +1,8 @@
import { Suspense } from "react"
import { logout } from "@/constants/routes/handleAuth" import { logout } from "@/constants/routes/handleAuth"
import { overview } from "@/constants/routes/myPages" import { overview } from "@/constants/routes/myPages"
import { getName } from "@/lib/trpc/memoizedRequests" import { getName } from "@/lib/trpc/memoizedRequests"
import LoginButton from "@/components/LoginButton" import LoginButton from "@/components/LoginButton"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext" import { getLang } from "@/i18n/serverContext"
@@ -35,13 +32,7 @@ export default async function TopMenu({
<ul className={styles.list}> <ul className={styles.list}>
{languageSwitcher ? ( {languageSwitcher ? (
<li className={styles.langSwitcher}> <li className={styles.langSwitcher}>{languageSwitcher}</li>
<Suspense
fallback={<SkeletonShimmer height="20px" width="10ch" />}
>
{languageSwitcher}
</Suspense>
</li>
) : null} ) : null}
{links.map(({ link }, i) => ( {links.map(({ link }, i) => (

View File

@@ -1,5 +1,3 @@
import { Suspense } from "react"
import { getFooter, getLanguageSwitcher } from "@/lib/trpc/memoizedRequests" import { getFooter, getLanguageSwitcher } from "@/lib/trpc/memoizedRequests"
import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name" import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name"
@@ -88,9 +86,7 @@ export default async function FooterDetails() {
)} )}
</nav> </nav>
{languages?.urls ? ( {languages?.urls ? (
<Suspense fallback={<SkeletonShimmer height="20px" width="10ch" />}> <LanguageSwitcher type="footer" urls={languages.urls} />
<LanguageSwitcher type="footer" urls={languages.urls} />
</Suspense>
) : null} ) : null}
</div> </div>
</div> </div>

View File

@@ -1,5 +1,6 @@
"use client" "use client"
import { usePathname, useSearchParams } from "next/navigation"
import { useIntl } from "react-intl" import { useIntl } from "react-intl"
import { Lang, languages } from "@/constants/languages" import { Lang, languages } from "@/constants/languages"
@@ -10,6 +11,8 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import useLang from "@/hooks/useLang" import useLang from "@/hooks/useLang"
import { useTrapFocus } from "@/hooks/useTrapFocus" import { useTrapFocus } from "@/hooks/useTrapFocus"
import { replaceUrlPart } from "./utils"
import styles from "./languageSwitcherContent.module.css" import styles from "./languageSwitcherContent.module.css"
import type { LanguageSwitcherContentProps } from "@/types/components/languageSwitcher/languageSwitcher" import type { LanguageSwitcherContentProps } from "@/types/components/languageSwitcher/languageSwitcher"
@@ -18,12 +21,15 @@ export default function LanguageSwitcherContent({
urls, urls,
onLanguageSwitch, onLanguageSwitch,
}: LanguageSwitcherContentProps) { }: LanguageSwitcherContentProps) {
console.log(urls)
const intl = useIntl() const intl = useIntl()
const currentLanguage = useLang() const currentLanguage = useLang()
const languageSwitcherRef = useTrapFocus() const languageSwitcherRef = useTrapFocus()
const urlKeys = Object.keys(urls) as Lang[] const urlKeys = Object.keys(urls) as Lang[]
const pathname = usePathname()
return ( return (
<div className={styles.languageSwitcherContent} ref={languageSwitcherRef}> <div className={styles.languageSwitcherContent} ref={languageSwitcherRef}>
<div className={styles.languageWrapper}> <div className={styles.languageWrapper}>
@@ -39,8 +45,9 @@ export default function LanguageSwitcherContent({
<li key={key}> <li key={key}>
<Link <Link
className={`${styles.link} ${isActive ? styles.active : ""}`} className={`${styles.link} ${isActive ? styles.active : ""}`}
href={url} href={replaceUrlPart(pathname, url)}
onClick={onLanguageSwitch} onClick={onLanguageSwitch}
keepSearchParams
> >
{languages[key]} {languages[key]}
{isActive ? <CheckIcon color="burgundy" /> : null} {isActive ? <CheckIcon color="burgundy" /> : null}

View File

@@ -0,0 +1,19 @@
export function replaceUrlPart(currentPath: string, newPart: string): string {
const pathSegments = currentPath.split("/").filter((segment) => segment)
const newPathSegments = newPart
.replace(/\/$/, "")
.split("/")
.filter((segment) => segment)
const isFullPathReplacement = newPathSegments.length > 1
if (isFullPathReplacement) {
return `/${newPathSegments.join("/")}`
}
const updatedPathSegments = pathSegments.slice(1)
const updatedPath = `/${newPathSegments.concat(updatedPathSegments).join("/")}`
return updatedPath
}

View File

@@ -1,10 +1,9 @@
"use client" "use client"
import { usePathname, useSearchParams } from "next/navigation" import { Suspense, useRef } from "react"
import { useRef } from "react"
import { useIntl } from "react-intl" import { useIntl } from "react-intl"
import { Lang, languages } from "@/constants/languages" import { languages } from "@/constants/languages"
import useDropdownStore from "@/stores/main-menu" import useDropdownStore from "@/stores/main-menu"
import { ChevronDownSmallIcon, GlobeIcon } from "@/components/Icons" import { ChevronDownSmallIcon, GlobeIcon } from "@/components/Icons"
@@ -24,7 +23,6 @@ import {
type LanguageSwitcherProps, type LanguageSwitcherProps,
LanguageSwitcherTypesEnum, LanguageSwitcherTypesEnum,
} from "@/types/components/languageSwitcher/languageSwitcher" } from "@/types/components/languageSwitcher/languageSwitcher"
import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
export default function LanguageSwitcher({ export default function LanguageSwitcher({
urls, urls,
@@ -38,23 +36,12 @@ export default function LanguageSwitcher({
isHeaderLanguageSwitcherMobileOpen, isHeaderLanguageSwitcherMobileOpen,
isHeaderLanguageSwitcherOpen, isHeaderLanguageSwitcherOpen,
} = useDropdownStore() } = useDropdownStore()
const searchParams = useSearchParams()
const pathname = usePathname()
const queryParams = new URLSearchParams(searchParams.toString())
const languageSwitcherRef = useRef<HTMLDivElement>(null) const languageSwitcherRef = useRef<HTMLDivElement>(null)
const isFooter = type === LanguageSwitcherTypesEnum.Footer const isFooter = type === LanguageSwitcherTypesEnum.Footer
const isHeader = !isFooter const isHeader = !isFooter
const globeIconSize = type === "desktopHeader" ? 16 : 20 const globeIconSize = type === "desktopHeader" ? 16 : 20
const currentUrl = `${pathname}?${queryParams.toString()}`
const fullUrls = Object.entries(urls).reduce((acc, [lang, { url }]) => {
const newUrl = currentUrl.replace(/^\/[a-z]{2}\//, url)
acc[lang as Lang] = { url: newUrl }
return acc
}, {} as LanguageSwitcherData)
const position = isFooter ? "footer" : "header" const position = isFooter ? "footer" : "header"
const dropdownType = { const dropdownType = {
@@ -119,7 +106,7 @@ export default function LanguageSwitcher({
{isLanguageSwitcherOpen ? ( {isLanguageSwitcherOpen ? (
<LanguageSwitcherContainer type={type}> <LanguageSwitcherContainer type={type}>
<LanguageSwitcherContent <LanguageSwitcherContent
urls={fullUrls} urls={urls}
onLanguageSwitch={() => toggleDropdown(dropdownType)} onLanguageSwitch={() => toggleDropdown(dropdownType)}
/> />
</LanguageSwitcherContainer> </LanguageSwitcherContainer>