Merge branch 'master' into feature/tracking

This commit is contained in:
Linus Flood
2024-11-18 12:20:13 +01:00
240 changed files with 5429 additions and 2717 deletions

View File

@@ -3,25 +3,27 @@
import { Suspense, useEffect } from "react"
import { Dialog, Modal } from "react-aria-components"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"
import useDropdownStore from "@/stores/main-menu"
import { GiftIcon, SearchIcon, ServiceIcon } from "@/components/Icons"
import LanguageSwitcher from "@/components/LanguageSwitcher"
import { useHandleKeyUp } from "@/hooks/useHandleKeyUp"
import useMediaQuery from "@/hooks/useMediaQuery"
import HeaderLink from "../../HeaderLink"
import TopLink from "../../TopLink"
import styles from "./mobileMenu.module.css"
import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown"
import type { MobileMenuProps } from "@/types/components/header/mobileMenu"
import { IconName } from "@/types/components/icon"
export default function MobileMenu({
children,
languageUrls,
topLink,
isLoggedIn,
}: React.PropsWithChildren<MobileMenuProps>) {
const intl = useIntl()
const {
@@ -75,20 +77,13 @@ export default function MobileMenu({
className={styles.dialog}
aria-label={intl.formatMessage({ id: "Menu" })}
>
<Suspense fallback={"Loading nav"}>{children}</Suspense>
{children}
<footer className={styles.footer}>
<HeaderLink href="#">
<SearchIcon width={20} height={20} color="burgundy" />
<HeaderLink href="#" iconName={IconName.Search}>
{intl.formatMessage({ id: "Find booking" })}
</HeaderLink>
{topLink.link ? (
<HeaderLink href={topLink.link.url}>
<GiftIcon width={20} height={20} color="burgundy" />
{topLink.title}
</HeaderLink>
) : null}
<HeaderLink href="#">
<ServiceIcon width={20} height={20} color="burgundy" />
<TopLink isLoggedIn={isLoggedIn} topLink={topLink} iconSize={20} />
<HeaderLink href="#" iconName={IconName.Service}>
{intl.formatMessage({ id: "Customer service" })}
</HeaderLink>
<LanguageSwitcher type="mobileHeader" urls={languageUrls} />
@@ -98,3 +93,20 @@ export default function MobileMenu({
</>
)
}
export function MobileMenuSkeleton() {
const intl = useIntl()
return (
<button
type="button"
disabled
className={styles.hamburger}
aria-label={intl.formatMessage({
id: "Open menu",
})}
>
<span className={styles.bar} />
</button>
)
}

View File

@@ -1,4 +1,8 @@
import { getHeader, getLanguageSwitcher } from "@/lib/trpc/memoizedRequests"
import {
getHeader,
getLanguageSwitcher,
getName,
} from "@/lib/trpc/memoizedRequests"
import MobileMenu from "../MobileMenu"
@@ -8,13 +12,18 @@ export default async function MobileMenuWrapper({
// preloaded
const languages = await getLanguageSwitcher()
const header = await getHeader()
const user = await getName()
if (!languages || !header) {
return null
}
return (
<MobileMenu languageUrls={languages.urls} topLink={header.data.topLink}>
<MobileMenu
languageUrls={languages.urls}
topLink={header.data.topLink}
isLoggedIn={!!user}
>
{children}
</MobileMenu>
)

View File

@@ -6,6 +6,7 @@ import { useIntl } from "react-intl"
import useDropdownStore from "@/stores/main-menu"
import { ChevronDownSmallIcon } from "@/components/Icons"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import Body from "@/components/TempDesignSystem/Text/Body"
import useClickOutside from "@/hooks/useClickOutside"
import { useHandleKeyUp } from "@/hooks/useHandleKeyUp"
@@ -47,7 +48,7 @@ export default function MyPagesMenu({
onClick={() => toggleDropdown(DropdownTypeEnum.MyPagesMenu)}
>
<Avatar initials={getInitials(user.firstName, user.lastName)} />
<Body textTransform="bold" color="textHighContrast" asChild>
<Body textTransform="bold" color="baseTextHighContrast" asChild>
<span>
{intl.formatMessage({ id: "Hi" })} {user.firstName}!
</span>
@@ -73,3 +74,15 @@ export default function MyPagesMenu({
</div>
)
}
export function MyPagesMenuSkeleton() {
return (
<div className={styles.myPagesMenu}>
<MainMenuButton>
<Avatar />
<SkeletonShimmer width="10ch" />
<ChevronDownSmallIcon className={`${styles.chevron}`} color="red" />
</MainMenuButton>
</div>
)
}

View File

@@ -10,8 +10,10 @@ import LoginButton from "@/components/LoginButton"
import { getIntl } from "@/i18n"
import Avatar from "../Avatar"
import MyPagesMenu from "../MyPagesMenu"
import MyPagesMobileMenu from "../MyPagesMobileMenu"
import MyPagesMenu, { MyPagesMenuSkeleton } from "../MyPagesMenu"
import MyPagesMobileMenu, {
MyPagesMobileMenuSkeleton,
} from "../MyPagesMobileMenu"
import styles from "./myPagesMenuWrapper.module.css"
@@ -62,3 +64,12 @@ export default async function MyPagesMenuWrapper() {
</>
)
}
export function MyPagesMenuWrapperSkeleton() {
return (
<div>
<MyPagesMenuSkeleton />
<MyPagesMobileMenuSkeleton />
</div>
)
}

View File

@@ -3,11 +3,11 @@
import { useEffect } from "react"
import { Dialog, Modal } from "react-aria-components"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"
import useDropdownStore from "@/stores/main-menu"
import { useHandleKeyUp } from "@/hooks/useHandleKeyUp"
import useMediaQuery from "@/hooks/useMediaQuery"
import { getInitials } from "@/utils/user"
import Avatar from "../Avatar"
@@ -76,3 +76,13 @@ export default function MyPagesMobileMenu({
</div>
)
}
export function MyPagesMobileMenuSkeleton() {
return (
<div className={styles.myPagesMobileMenu}>
<MainMenuButton className={styles.button}>
<Avatar />
</MainMenuButton>
</div>
)
}

View File

@@ -1,3 +1,7 @@
import { cx } from "class-variance-authority"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import NavigationMenuItem from "../NavigationMenuItem"
import styles from "./navigationMenuList.module.css"
@@ -20,3 +24,13 @@ export default function NavigationMenuList({
</ul>
)
}
export function NavigationMenuListSkeleton() {
return (
<ul className={cx(styles.navigationMenu, styles.desktop)}>
<li className={styles.item}>
<SkeletonShimmer width="30ch" />
</li>
</ul>
)
}

View File

@@ -5,37 +5,31 @@ import Image from "@/components/Image"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import { NavigationMenuListSkeleton } from "./NavigationMenu/NavigationMenuList"
import { MobileMenuSkeleton } from "./MobileMenu"
import MobileMenuWrapper from "./MobileMenuWrapper"
import MyPagesMenuWrapper from "./MyPagesMenuWrapper"
import MyPagesMenuWrapper, {
MyPagesMenuWrapperSkeleton,
} from "./MyPagesMenuWrapper"
import NavigationMenu from "./NavigationMenu"
import styles from "./mainMenu.module.css"
export default async function MainMenu() {
const lang = getLang()
const intl = await getIntl()
export default function MainMenu() {
return (
<div className={styles.mainMenu}>
<nav className={styles.nav}>
<NextLink className={styles.logoLink} href={`/${lang}`}>
<Image
alt={intl.formatMessage({ id: "Back to scandichotels.com" })}
className={styles.logo}
height={22}
src="/_static/img/scandic-logotype.svg"
width={103}
/>
</NextLink>
<Suspense fallback={<Logo alt="..." />}>
<MainMenuLogo />
</Suspense>
<div className={styles.menus}>
<Suspense fallback={"Loading nav"}>
<Suspense fallback={<NavigationMenuListSkeleton />}>
<NavigationMenu isMobile={false} />
</Suspense>
<Suspense fallback={"Loading profile"}>
<Suspense fallback={<MyPagesMenuWrapperSkeleton />}>
<MyPagesMenuWrapper />
</Suspense>
<Suspense fallback={"Loading menu"}>
<Suspense fallback={<MobileMenuSkeleton />}>
<MobileMenuWrapper>
<NavigationMenu isMobile={true} />
</MobileMenuWrapper>
@@ -45,3 +39,25 @@ export default async function MainMenu() {
</div>
)
}
async function MainMenuLogo() {
const intl = await getIntl()
return <Logo alt={intl.formatMessage({ id: "Back to scandichotels.com" })} />
}
function Logo({ alt }: { alt: string }) {
const lang = getLang()
return (
<NextLink className={styles.logoLink} href={`/${lang}`}>
<Image
alt={alt}
className={styles.logo}
height={22}
src="/_static/img/scandic-logotype.svg"
width={103}
/>
</NextLink>
)
}

View File

@@ -1,7 +1,7 @@
.mainMenu {
background-color: var(--Base-Surface-Primary-light-Normal);
padding: var(--Spacing-x2);
border-bottom: 1px solid var(--Base-Border-Subtle);
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
}
.nav {