From 2791f07f67a4c8b5bf061684ff25f8254333fb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20J=C3=A4derberg?= Date: Mon, 17 Feb 2025 07:47:33 +0000 Subject: [PATCH] Merged in fix/mypages-clientside-menu (pull request #1344) Fix/mypages clientside menu * feat: move mypages menu to client side * Merge branch 'master' of bitbucket.org:scandic-swap/web into fix/mypages-clientside-menu * wip * wip * wip * refactor: reorganize MyPages navigation logic and improve type definitions * refactor: enhance MyPagesMobileDropdown with loading states and skeletons * refactor: clean up header component and improve myPagesNavigation query structure * Merge branch 'master' of bitbucket.org:scandic-swap/web into fix/mypages-clientside-menu Approved-by: Linus Flood --- app/[lang]/(live)/layout.tsx | 2 + components/Current/Header/MainMenu/index.tsx | 8 +- .../Header/MyPagesMobileDropdown/index.tsx | 135 ++++++++++-------- .../my-pages-mobile-dropdown.module.css | 4 + components/Current/Header/index.tsx | 24 +--- .../Header/MainMenu/MyPagesMenu/index.tsx | 13 +- .../MainMenu/MyPagesMenuContent/index.tsx | 42 ++++-- .../MainMenu/MyPagesMenuWrapper/index.tsx | 58 ++++---- .../MainMenu/MyPagesMobileMenu/index.tsx | 4 - components/MyPages/Sidebar/index.tsx | 15 +- components/MyPages/menuItems.ts | 101 ------------- server/index.ts | 2 + .../contentstack/loyaltyLevel/input.ts | 2 + server/routers/navigation/index.ts | 5 + .../routers/navigation/mypages/MyPagesLink.ts | 10 ++ .../navigation/mypages/getPrimaryLinks.ts | 83 +++++++++++ .../navigation/mypages/getSecondaryLinks.ts | 28 ++++ server/routers/navigation/mypages/index.ts | 49 +++++++ 18 files changed, 334 insertions(+), 251 deletions(-) delete mode 100644 components/MyPages/menuItems.ts create mode 100644 server/routers/navigation/index.ts create mode 100644 server/routers/navigation/mypages/MyPagesLink.ts create mode 100644 server/routers/navigation/mypages/getPrimaryLinks.ts create mode 100644 server/routers/navigation/mypages/getSecondaryLinks.ts create mode 100644 server/routers/navigation/mypages/index.ts diff --git a/app/[lang]/(live)/layout.tsx b/app/[lang]/(live)/layout.tsx index 335cacabb..e81803125 100644 --- a/app/[lang]/(live)/layout.tsx +++ b/app/[lang]/(live)/layout.tsx @@ -1,6 +1,7 @@ import "@/app/globals.css" import "@scandic-hotels/design-system/style.css" +import { ReactQueryDevtools } from "@tanstack/react-query-devtools" import Script from "next/script" import { SessionProvider } from "next-auth/react" @@ -70,6 +71,7 @@ export default async function RootLayout({ + diff --git a/components/Current/Header/MainMenu/index.tsx b/components/Current/Header/MainMenu/index.tsx index 5fcdf188b..f8dd3001e 100644 --- a/components/Current/Header/MainMenu/index.tsx +++ b/components/Current/Header/MainMenu/index.tsx @@ -71,10 +71,11 @@ export function MainMenu({ if (!isMyPagesMobileMenuOpen) { trackClick("profile picture icon") } - toggleDropdown(DropdownTypeEnum.MyPagesMobileMenu) } + console.log("isMyPagesMobileMenuOpen", isMyPagesMobileMenuOpen) + return (
    - {links.map((link, i) => ( + {Array.from({ length: 5 }, () => "").map((_, i) => (
  • diff --git a/components/Current/Header/MyPagesMobileDropdown/index.tsx b/components/Current/Header/MyPagesMobileDropdown/index.tsx index 12c49ef49..339014038 100644 --- a/components/Current/Header/MyPagesMobileDropdown/index.tsx +++ b/components/Current/Header/MyPagesMobileDropdown/index.tsx @@ -1,9 +1,12 @@ "use client" + import { useIntl } from "react-intl" import { logout } from "@/constants/routes/handleAuth" +import { trpc } from "@/lib/trpc/client" import useDropdownStore from "@/stores/main-menu" +import SkeletonShimmer from "@/components/SkeletonShimmer" import Divider from "@/components/TempDesignSystem/Divider" import Link from "@/components/TempDesignSystem/Link" import Title from "@/components/TempDesignSystem/Text/Title" @@ -14,22 +17,13 @@ import styles from "./my-pages-mobile-dropdown.module.css" import type { ReactNode } from "react" import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown" -import type { MyPagesLink } from "@/components/MyPages/menuItems" -export default function MyPagesMobileDropdown({ - primaryLinks, - secondaryLinks, -}: { - primaryLinks: MyPagesLink[] - secondaryLinks: MyPagesLink[] -}) { +export default function MyPagesMobileDropdown() { + const { data: myPagesNavigation } = useMyPagesNavigation() + const intl = useIntl() const { toggleDropdown, isMyPagesMobileMenuOpen } = useDropdownStore() - if (primaryLinks.length === 0 && secondaryLinks.length === 0) { - return null - } - const handleOnClick = () => toggleDropdown(DropdownTypeEnum.MyPagesMobileMenu) return ( @@ -43,16 +37,10 @@ export default function MyPagesMobileDropdown({ - + - + ) @@ -71,58 +59,64 @@ function List({ children }: { children: ReactNode }) { ) } -function PrimaryLinks({ - primaryLinks, - handleOnClick, -}: { - primaryLinks: MyPagesLink[] - handleOnClick: () => void -}) { +function PrimaryLinks({ handleOnClick }: { handleOnClick: () => void }) { + const { + data: myPagesNavigation, + isLoading, + isSuccess, + } = useMyPagesNavigation() + + const primaryLinks = myPagesNavigation?.primaryLinks ?? [] return ( <> - {primaryLinks.map((link, i) => ( -
  • - - {link.text} - -
  • - ))} + {isLoading && } + {isSuccess && + primaryLinks.map((link, i) => ( +
  • + + {link.text} + +
  • + ))} ) } -function SecondaryLinks({ - secondaryLinks, - handleOnClick, -}: { - secondaryLinks: MyPagesLink[] - handleOnClick: () => void -}) { +function SecondaryLinks({ handleOnClick }: { handleOnClick: () => void }) { + const { + data: myPagesNavigation, + isLoading, + isSuccess, + } = useMyPagesNavigation() + + const secondaryLinks = myPagesNavigation?.secondaryLinks ?? [] const intl = useIntl() const lang = useLang() return ( <> - {secondaryLinks.map((link, i) => ( -
  • - - {link.text} - -
  • - ))} + {isLoading && } + {isSuccess && + secondaryLinks.map((link, i) => ( +
  • + + {link.text} + +
  • + ))}
  • ) } + +function Skeletons({ count }: { count: number }) { + return ( + <> + {Array.from({ length: count }).map((_, i) => ( +
  • + +
  • + ))} + + ) +} + +function useMyPagesNavigation() { + const lang = useLang() + return trpc.navigation.myPages.useQuery({ lang }) +} diff --git a/components/Current/Header/MyPagesMobileDropdown/my-pages-mobile-dropdown.module.css b/components/Current/Header/MyPagesMobileDropdown/my-pages-mobile-dropdown.module.css index f42c1dfad..137585c41 100644 --- a/components/Current/Header/MyPagesMobileDropdown/my-pages-mobile-dropdown.module.css +++ b/components/Current/Header/MyPagesMobileDropdown/my-pages-mobile-dropdown.module.css @@ -61,3 +61,7 @@ display: none; } } + +.skeletonItem { + padding: var(--Spacing-x1); +} diff --git a/components/Current/Header/index.tsx b/components/Current/Header/index.tsx index 7c294520e..1126aaecf 100644 --- a/components/Current/Header/index.tsx +++ b/components/Current/Header/index.tsx @@ -6,10 +6,6 @@ import { getName, } from "@/lib/trpc/memoizedRequests" -import { - getPrimaryLinks, - getSecondaryLinks, -} from "@/components/MyPages/menuItems" import { getLang } from "@/i18n/serverContext" import LanguageSwitcher from "./LanguageSwitcher" @@ -22,14 +18,11 @@ import styles from "./header.module.css" export default async function Header() { const lang = getLang() - const [data, user, languages, primaryLinks, secondaryLinks] = - await Promise.all([ - getCurrentHeader(lang), - getName(), - getLanguageSwitcher(), - getPrimaryLinks({ lang }), - getSecondaryLinks({ lang }), - ]) + const [data, user, languages] = await Promise.all([ + getCurrentHeader(lang), + getName(), + getLanguageSwitcher(), + ]) if (!languages || !data?.header) { return null @@ -58,12 +51,7 @@ export default async function Header() { logo={logo} topMenuMobileLinks={topMenuMobileLinks} languageSwitcher={} - myPagesMobileDropdown={ - - } + myPagesMobileDropdown={} bookingHref={homeHref} user={user} /> diff --git a/components/Header/MainMenu/MyPagesMenu/index.tsx b/components/Header/MainMenu/MyPagesMenu/index.tsx index 1d3830c45..8406ca724 100644 --- a/components/Header/MainMenu/MyPagesMenu/index.tsx +++ b/components/Header/MainMenu/MyPagesMenu/index.tsx @@ -3,6 +3,8 @@ import { useRef } from "react" import { useIntl } from "react-intl" +import { MembershipLevelEnum } from "@/constants/membershipLevels" +import { trpc } from "@/lib/trpc/client" import useDropdownStore from "@/stores/main-menu" import { ChevronDownSmallIcon } from "@/components/Icons" @@ -10,7 +12,7 @@ import SkeletonShimmer from "@/components/SkeletonShimmer" import Body from "@/components/TempDesignSystem/Text/Body" import useClickOutside from "@/hooks/useClickOutside" import { useHandleKeyUp } from "@/hooks/useHandleKeyUp" -import {type FriendsMembership,getInitials } from "@/utils/user" +import { type FriendsMembership, getInitials } from "@/utils/user" import Avatar from "../Avatar" import MainMenuButton from "../MainMenuButton" @@ -20,22 +22,17 @@ import styles from "./myPagesMenu.module.css" import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown" import type { User } from "@/types/user" -import type { MyPagesLink } from "@/components/MyPages/menuItems" import type { LoyaltyLevel } from "@/server/routers/contentstack/loyaltyLevel/output" export type MyPagesMenuProps = { - primaryLinks: MyPagesLink[] - secondaryLinks: MyPagesLink[] user: Pick membership?: FriendsMembership | null membershipLevel: LoyaltyLevel | null } export default function MyPagesMenu({ - membership, - primaryLinks, - secondaryLinks, user, + membership, membershipLevel, }: MyPagesMenuProps) { const intl = useIntl() @@ -76,8 +73,6 @@ export default function MyPagesMenu({
    diff --git a/components/Header/MainMenu/MyPagesMenuContent/index.tsx b/components/Header/MainMenu/MyPagesMenuContent/index.tsx index 6f155075c..52e28baa6 100644 --- a/components/Header/MainMenu/MyPagesMenuContent/index.tsx +++ b/components/Header/MainMenu/MyPagesMenuContent/index.tsx @@ -3,6 +3,7 @@ import { useIntl } from "react-intl" import { logout } from "@/constants/routes/handleAuth" +import { trpc } from "@/lib/trpc/client" import { ArrowRightIcon } from "@/components/Icons" import Divider from "@/components/TempDesignSystem/Divider" @@ -20,14 +21,17 @@ type Props = MyPagesMenuProps & { toggleOpenStateFn: () => void } export default function MyPagesMenuContent({ membership, - primaryLinks, - secondaryLinks, toggleOpenStateFn, user, membershipLevel, }: Props) { + const lang = useLang() const intl = useIntl() const myPagesMenuContentRef = useTrapFocus() + const { data: myPagesNavigation } = useMyPagesNavigation() + + const primaryLinks = myPagesNavigation?.primaryLinks ?? [] + const secondaryLinks = myPagesNavigation?.secondaryLinks ?? [] const membershipPoints = membership?.currentPoints const introClassName = @@ -65,16 +69,10 @@ export default function MyPagesMenuContent({
  • - + - +
@@ -82,9 +80,14 @@ export default function MyPagesMenuContent({ } function PrimaryLinks({ - primaryLinks, toggleOpenStateFn, -}: Pick & { toggleOpenStateFn: () => void }) { +}: { + toggleOpenStateFn: () => void +}) { + const { data: myPagesNavigation } = useMyPagesNavigation() + + const primaryLinks = myPagesNavigation?.primaryLinks ?? [] + return (
    {primaryLinks.map((link, i) => ( @@ -106,11 +109,15 @@ function PrimaryLinks({ } function SecondaryLinks({ - secondaryLinks, toggleOpenStateFn, -}: Pick & { toggleOpenStateFn: () => void }) { +}: { + toggleOpenStateFn: () => void +}) { const intl = useIntl() const lang = useLang() + const { data: myPagesNavigation } = useMyPagesNavigation() + + const secondaryLinks = myPagesNavigation?.secondaryLinks ?? [] return (
      @@ -140,3 +147,10 @@ function SecondaryLinks({
    ) } + +const useMyPagesNavigation = () => { + const lang = useLang() + return trpc.navigation.myPages.useQuery({ + lang: lang, + }) +} diff --git a/components/Header/MainMenu/MyPagesMenuWrapper/index.tsx b/components/Header/MainMenu/MyPagesMenuWrapper/index.tsx index 2e1adadcb..6ef9a075c 100644 --- a/components/Header/MainMenu/MyPagesMenuWrapper/index.tsx +++ b/components/Header/MainMenu/MyPagesMenuWrapper/index.tsx @@ -1,14 +1,12 @@ +"use client" + +import { useIntl } from "react-intl" + import { MembershipLevelEnum } from "@/constants/membershipLevels" -import { getMembershipLevelSafely, getName } from "@/lib/trpc/memoizedRequests" -import { serverClient } from "@/lib/trpc/server" +import { trpc } from "@/lib/trpc/client" import LoginButton from "@/components/LoginButton" -import { - getPrimaryLinks, - getSecondaryLinks, -} from "@/components/MyPages/menuItems" -import { getIntl } from "@/i18n" -import { getLang } from "@/i18n/serverContext" +import useLang from "@/hooks/useLang" import Avatar from "../Avatar" import MyPagesMenu, { MyPagesMenuSkeleton } from "../MyPagesMenu" @@ -18,39 +16,41 @@ import MyPagesMobileMenu, { import styles from "./myPagesMenuWrapper.module.css" -export default async function MyPagesMenuWrapper() { - const lang = getLang() - const [intl, user, membership, primaryLinks, secondaryLinks] = - await Promise.all([ - getIntl(), - getName(), - getMembershipLevelSafely(), - getPrimaryLinks({ lang }), - getSecondaryLinks({ lang }), - ]) +export default function MyPagesMenuWrapper() { + const intl = useIntl() + const lang = useLang() - const membershipLevel = membership?.membershipLevel - ? await serverClient().contentstack.loyaltyLevels.byLevel({ - level: MembershipLevelEnum[membership.membershipLevel], - }) - : null + const { data: user, isLoading: isLoadingUser } = trpc.user.name.useQuery() + const { data: membership, isLoading: isLoadingMembership } = + trpc.user.safeMembershipLevel.useQuery() + + const { data: membershipLevel, isLoading: isLoadingMembershipLevel } = + trpc.contentstack.loyaltyLevels.byLevel.useQuery( + { + lang: lang, + level: MembershipLevelEnum[membership?.membershipLevel ?? "L1"], + }, + { + enabled: !!membership?.membershipLevel, + } + ) + + if (isLoadingUser || isLoadingMembership || isLoadingMembershipLevel) { + return + } return ( <> {user ? ( <> diff --git a/components/Header/MainMenu/MyPagesMobileMenu/index.tsx b/components/Header/MainMenu/MyPagesMobileMenu/index.tsx index 62c949724..31db8ee17 100644 --- a/components/Header/MainMenu/MyPagesMobileMenu/index.tsx +++ b/components/Header/MainMenu/MyPagesMobileMenu/index.tsx @@ -22,8 +22,6 @@ import type { MyPagesMenuProps } from "../MyPagesMenu" export default function MyPagesMobileMenu({ membershipLevel, membership, - primaryLinks, - secondaryLinks, user, }: MyPagesMenuProps) { const intl = useIntl() @@ -66,8 +64,6 @@ export default function MyPagesMobileMenu({ toggleDropdown(DropdownTypeEnum.MyPagesMobileMenu) diff --git a/components/MyPages/Sidebar/index.tsx b/components/MyPages/Sidebar/index.tsx index 12d42e6a0..f76965e2f 100644 --- a/components/MyPages/Sidebar/index.tsx +++ b/components/MyPages/Sidebar/index.tsx @@ -1,9 +1,6 @@ import { logout } from "@/constants/routes/handleAuth" +import { serverClient } from "@/lib/trpc/server" -import { - getPrimaryLinks, - getSecondaryLinks, -} from "@/components/MyPages/menuItems" import Divider from "@/components/TempDesignSystem/Divider" import Link from "@/components/TempDesignSystem/Link" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" @@ -30,14 +27,13 @@ export default async function SidebarMyPages() { } async function PrimaryLinks() { - const lang = getLang() - const links = await getPrimaryLinks({ lang }) + const nav = await serverClient().navigation.myPages({}) return ( <>
      - {links.map((link) => ( + {nav?.primaryLinks.map((link) => (
      • - {links.map((link) => ( + {nav?.secondaryLinks.map((link) => (
      • { - const intl = await getIntl() - const scandicSasPromise = safeTry(isScandicXSASActive()) - const teamMemberPromise = safeTry(showTeamMemberCard()) - - const [showSASLink] = await scandicSasPromise - const [showTeamMemberLink] = await teamMemberPromise - - const menuItems: MyPagesLink[] = [ - { - text: intl.formatMessage({ id: "Overview" }), - href: routes.overview[lang], - }, - { - text: intl.formatMessage({ id: "My Points" }), - href: routes.points[lang], - }, - { - text: intl.formatMessage({ id: "My Stays" }), - href: routes.stays[lang], - }, - { - text: intl.formatMessage({ id: "My Benefits" }), - href: routes.benefits[lang], - }, - ] - - if (showSASLink) { - menuItems.push({ - text: intl.formatMessage({ id: "Scandic ♥ SAS" }), - href: routes.scandicXSAS[lang], - }) - } - - if (showTeamMemberLink) { - menuItems.push({ - text: intl.formatMessage({ id: "Team Member Card" }), - href: "#", - }) - } - - return menuItems -} - -export async function getSecondaryLinks({ - lang, -}: Args): Promise { - const intl = await getIntl() - const menuItems: MyPagesLink[] = [ - { - text: intl.formatMessage({ id: "About Scandic Friends" }), - href: routes.scandicFriends[lang], - }, - { - text: intl.formatMessage({ id: "My Profile" }), - href: routes.profile[lang], - }, - ] - - return menuItems -} - -async function isScandicXSASActive() { - async function checkIfLinked() { - // TODO: Implement this check - return true - } - - const isLinked = await checkIfLinked() - - return env.SAS_ENABLED && isLinked -} - -async function showTeamMemberCard() { - async function getIsTeamMember() { - // TODO: Implement this check - return false - } - - const isTeamMember = await getIsTeamMember() - return isTeamMember -} diff --git a/server/index.ts b/server/index.ts index 676958d9f..52d357e38 100644 --- a/server/index.ts +++ b/server/index.ts @@ -2,6 +2,7 @@ import { bookingRouter } from "./routers/booking" import { contentstackRouter } from "./routers/contentstack" import { hotelsRouter } from "./routers/hotels" +import { navitaionRouter } from "./routers/navigation" import { partnerRouter } from "./routers/partners" import { userRouter } from "./routers/user" import { router } from "./trpc" @@ -12,6 +13,7 @@ export const appRouter = router({ hotel: hotelsRouter, user: userRouter, partner: partnerRouter, + navigation: navitaionRouter, }) export type AppRouter = typeof appRouter diff --git a/server/routers/contentstack/loyaltyLevel/input.ts b/server/routers/contentstack/loyaltyLevel/input.ts index 7e10ccfe4..039264777 100644 --- a/server/routers/contentstack/loyaltyLevel/input.ts +++ b/server/routers/contentstack/loyaltyLevel/input.ts @@ -1,7 +1,9 @@ import { z } from "zod" import { MembershipLevelEnum } from "@/constants/membershipLevels" +import { Lang } from "@/constants/languages" export const loyaltyLevelInput = z.object({ level: z.nativeEnum(MembershipLevelEnum), + lang: z.nativeEnum(Lang).optional(), }) diff --git a/server/routers/navigation/index.ts b/server/routers/navigation/index.ts new file mode 100644 index 000000000..bd918ea67 --- /dev/null +++ b/server/routers/navigation/index.ts @@ -0,0 +1,5 @@ +import { router } from "@/server/trpc" + +import { myPagesNavigation } from "./mypages/index" + +export const navitaionRouter = router({ myPages: myPagesNavigation }) diff --git a/server/routers/navigation/mypages/MyPagesLink.ts b/server/routers/navigation/mypages/MyPagesLink.ts new file mode 100644 index 000000000..ce2aca00e --- /dev/null +++ b/server/routers/navigation/mypages/MyPagesLink.ts @@ -0,0 +1,10 @@ +type BaseLink = { + type: "link" | "withbadge" + text: string + href: string +} + +type NormalLink = BaseLink & { type: "link" } +type LinkWithBadge = BaseLink & { type: "withbadge"; number: number } + +export type MyPagesLink = NormalLink | LinkWithBadge diff --git a/server/routers/navigation/mypages/getPrimaryLinks.ts b/server/routers/navigation/mypages/getPrimaryLinks.ts new file mode 100644 index 000000000..f4ee72439 --- /dev/null +++ b/server/routers/navigation/mypages/getPrimaryLinks.ts @@ -0,0 +1,83 @@ +import { cache } from "react" + +import * as routes from "@/constants/routes/myPages" +import { env } from "@/env/server" + +import { getIntl } from "@/i18n" +import { safeTry } from "@/utils/safeTry" + +import type { Lang } from "@/constants/languages" +import type { MyPagesLink } from "./MyPagesLink" + +export const getPrimaryLinks = cache( + async ({ lang }: { lang: Lang }): Promise => { + const intl = await getIntl(lang) + const scandicSasPromise = safeTry(isScandicXSASActive()) + const teamMemberPromise = safeTry(showTeamMemberCard()) + + const [showSASLink] = await scandicSasPromise + const [showTeamMemberLink] = await teamMemberPromise + + const menuItems: MyPagesLink[] = [ + { + type: "link", + text: intl.formatMessage({ id: "Overview" }), + href: routes.overview[lang], + }, + { + type: "link", + text: intl.formatMessage({ id: "My Points" }), + href: routes.points[lang], + }, + { + type: "link", + text: intl.formatMessage({ id: "My Stays" }), + href: routes.stays[lang], + }, + { + type: "link", + text: intl.formatMessage({ id: "My Benefits" }), + href: routes.benefits[lang], + }, + ] + + if (showSASLink) { + menuItems.push({ + type: "link", + text: intl.formatMessage({ id: "Scandic ♥ SAS" }), + href: routes.scandicXSAS[lang], + }) + } + + if (showTeamMemberLink) { + menuItems.push({ + type: "link", + text: intl.formatMessage({ id: "Team Member Card" }), + href: "#", + }) + } + + return menuItems + } +) + +const isScandicXSASActive = cache(async () => { + async function checkIfLinked() { + // TODO: Implement this check + return true + } + + const isLinked = await checkIfLinked() + + return env.SAS_ENABLED && isLinked +}) + +const showTeamMemberCard = cache(async () => { + async function getIsTeamMember() { + // TODO: Implement this check + return false + } + + const isTeamMember = await getIsTeamMember() + return isTeamMember +}) diff --git a/server/routers/navigation/mypages/getSecondaryLinks.ts b/server/routers/navigation/mypages/getSecondaryLinks.ts new file mode 100644 index 000000000..7cb7a59eb --- /dev/null +++ b/server/routers/navigation/mypages/getSecondaryLinks.ts @@ -0,0 +1,28 @@ +import * as routes from "@/constants/routes/myPages" + +import { getIntl } from "@/i18n" + +import type { Lang } from "@/constants/languages" +import type { MyPagesLink } from "./MyPagesLink" + +export async function getSecondaryLinks({ + lang, +}: { + lang: Lang +}): Promise { + const intl = await getIntl() + const menuItems: MyPagesLink[] = [ + { + type: "link", + text: intl.formatMessage({ id: "About Scandic Friends" }), + href: routes.scandicFriends[lang], + }, + { + type: "link", + text: intl.formatMessage({ id: "My Profile" }), + href: routes.profile[lang], + }, + ] + + return menuItems +} diff --git a/server/routers/navigation/mypages/index.ts b/server/routers/navigation/mypages/index.ts new file mode 100644 index 000000000..35b151fb0 --- /dev/null +++ b/server/routers/navigation/mypages/index.ts @@ -0,0 +1,49 @@ +import { TRPCError } from "@trpc/server" +import { z } from "zod" + +import { Lang } from "@/constants/languages" +import { safeProtectedProcedure } from "@/server/trpc" + +import { getPrimaryLinks } from "./getPrimaryLinks" +import { getSecondaryLinks } from "./getSecondaryLinks" + +import type { MyPagesLink } from "./MyPagesLink" + +export const myPagesNavigation = safeProtectedProcedure + .input( + z.object({ + lang: z.nativeEnum(Lang).optional(), + }) + ) + .query( + async ({ + ctx, + input, + }): Promise<{ + primaryLinks: MyPagesLink[] + secondaryLinks: MyPagesLink[] + } | null> => { + if (!ctx.session) { + return null + } + + const lang = input.lang || ctx.lang + + if (!lang) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Language must be provided.", + }) + } + + const [primaryLinks, secondaryLinks] = await Promise.all([ + getPrimaryLinks({ lang }), + getSecondaryLinks({ lang }), + ]) + + return { + primaryLinks, + secondaryLinks, + } + } + )