feat(SW-2859): Create trpc package * Add isEdge, safeTry and dataCache to new common package * Add eslint and move prettier config * Clean up tests * Create trpc package and move initialization * Move errors and a few procedures * Move telemetry to common package * Move tokenManager to common package * Add Sentry to procedures * Clean up procedures * Fix self-referencing imports * Add exports to packages and lint rule to prevent relative imports * Add env to trpc package * Add eslint to trpc package * Apply lint rules * Use direct imports from trpc package * Add lint-staged config to trpc * Move lang enum to common * Restructure trpc package folder structure * Fix lang imports Approved-by: Linus Flood
112 lines
3.4 KiB
TypeScript
112 lines
3.4 KiB
TypeScript
/* eslint-disable formatjs/no-literal-string-in-jsx */
|
|
|
|
"use client"
|
|
import { useCallback, useEffect, useRef, useState } from "react"
|
|
|
|
import { languages } from "@/constants/languages"
|
|
import { env } from "@/env/client"
|
|
|
|
import Link from "@/components/TempDesignSystem/Link"
|
|
import useLang from "@/hooks/useLang"
|
|
|
|
import styles from "./desktop.module.css"
|
|
|
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
|
|
|
import type { LanguageSwitcherProps } from "@/types/components/current/languageSwitcher"
|
|
|
|
export default function Desktop({ urls }: LanguageSwitcherProps) {
|
|
const currentLanguage = useLang()
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
const divRef = useRef<HTMLDivElement>(null)
|
|
|
|
function toggleOpen() {
|
|
setIsOpen((prevIsOpen) => !prevIsOpen)
|
|
}
|
|
|
|
const close = useCallback(() => {
|
|
setIsOpen(false)
|
|
}, [setIsOpen])
|
|
|
|
useEffect(() => {
|
|
function handleClickOutside(evt: Event) {
|
|
const target = evt.target as HTMLElement
|
|
if (divRef.current && target && !divRef.current.contains(target)) {
|
|
close()
|
|
}
|
|
}
|
|
|
|
if (divRef.current) {
|
|
document.addEventListener("click", handleClickOutside, false)
|
|
}
|
|
return () => {
|
|
document.removeEventListener("click", handleClickOutside, false)
|
|
}
|
|
}, [close])
|
|
|
|
const urlKeys = Object.keys(urls)
|
|
|
|
if (urlKeys.length === 1 && urlKeys[0] === currentLanguage) {
|
|
return (
|
|
<div className={styles.container} ref={divRef}>
|
|
<section className={styles.languageSwitcher}>
|
|
<svg focusable="false" className={styles.icon} viewBox="0 0 32 32">
|
|
<use xlinkHref="/_static/img/icons/sprites.svg#icon-globe"></use>
|
|
</svg>
|
|
{languages[currentLanguage]}
|
|
</section>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<section className={styles.desktop}>
|
|
<div className={styles.container} ref={divRef}>
|
|
<button
|
|
aria-pressed="false"
|
|
className={styles.toggle}
|
|
onClick={toggleOpen}
|
|
>
|
|
<svg focusable="false" className={styles.icon} viewBox="0 0 32 32">
|
|
<use xlinkHref="/_static/img/icons/sprites.svg#icon-globe"></use>
|
|
</svg>
|
|
{languages[currentLanguage]}
|
|
<span className={styles.hiddenAccessible}>Choose language</span>
|
|
<span className={styles.caret}></span>
|
|
</button>
|
|
<ul className={`${styles.dropdown} ${isOpen ? styles.isOpen : ""}`}>
|
|
{urlKeys.map((key) => {
|
|
const url = urls[key as Lang]?.url
|
|
if (url) {
|
|
return (
|
|
<li
|
|
key={key}
|
|
className={`${styles.li} ${currentLanguage === key ? styles.active : ""}`}
|
|
>
|
|
{urls[key as Lang]?.isExternal ? (
|
|
<Link
|
|
className={styles.link}
|
|
href={url}
|
|
rel={env.isLangLive(key as Lang) ? undefined : "nofollow"}
|
|
>
|
|
{languages[key as Lang]}
|
|
</Link>
|
|
) : (
|
|
<a
|
|
className={styles.link}
|
|
href={url}
|
|
rel={env.isLangLive(key as Lang) ? undefined : "nofollow"}
|
|
>
|
|
{languages[key as Lang]}
|
|
</a>
|
|
)}
|
|
</li>
|
|
)
|
|
}
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|