Fix group navigation

This commit is contained in:
Pico2x 2022-09-20 18:03:34 +01:00
parent 6c3338f5d7
commit 64cb7c2474
4 changed files with 72 additions and 95 deletions

View File

@ -6,15 +6,29 @@ import { trackCallback } from 'web/lib/service/analytics'
import TrophyIcon from 'web/lib/icons/trophy-icon' import TrophyIcon from 'web/lib/icons/trophy-icon'
import { useUser } from 'web/hooks/use-user' import { useUser } from 'web/hooks/use-user'
import NotificationsIcon from '../notifications-icon' import NotificationsIcon from '../notifications-icon'
import router from 'next/router'
import { userProfileItem } from './bottom-nav-bar' import { userProfileItem } from './bottom-nav-bar'
import Link from 'next/link'
const mobileGroupNavigation = [ const mobileGroupNavigation = (slug: string) => [
{ name: 'Markets', key: 'markets', icon: HomeIcon }, {
{ name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, name: 'Markets',
{ name: 'About', key: 'about', icon: ClipboardIcon }, key: 'markets',
icon: HomeIcon,
href: `/group/${slug}/markets`,
},
{
name: 'About',
key: 'about',
icon: ClipboardIcon,
href: `/group/${slug}/about`,
},
{
name: 'Leaderboard',
key: 'leaderboards',
icon: TrophyIcon,
href: `/group/${slug}/leaderboards`,
},
] ]
const mobileGeneralNavigation = [ const mobileGeneralNavigation = [
{ {
name: 'Notifications', name: 'Notifications',
@ -24,42 +38,24 @@ const mobileGeneralNavigation = [
}, },
] ]
export function GroupNavBar(props: { export function GroupNavBar(props: { currentPage: string; groupSlug: string }) {
currentPage: string const { currentPage, groupSlug } = props
onClick: (key: string) => void
}) {
const { currentPage } = props
const user = useUser() const user = useUser()
return ( return (
<nav className="z-20 flex justify-between border-t-2 bg-white text-xs text-gray-700 lg:hidden"> <nav className="z-20 flex justify-between border-t-2 bg-white text-xs text-gray-700 lg:hidden">
{mobileGroupNavigation.map((item) => ( {mobileGroupNavigation(groupSlug).map((item) => (
<NavBarItem <NavBarItem key={item.name} item={item} currentPage={currentPage} />
key={item.name}
item={item}
currentPage={currentPage}
onClick={props.onClick}
/>
))} ))}
{mobileGeneralNavigation.map((item) => ( {mobileGeneralNavigation.map((item) => (
<NavBarItem <NavBarItem key={item.name} item={item} currentPage={currentPage} />
key={item.name}
item={item}
currentPage={currentPage}
onClick={() => {
router.push(item.href)
}}
/>
))} ))}
{user && ( {user && (
<NavBarItem <NavBarItem
key={'profile'} key={'profile'}
currentPage={currentPage} currentPage={currentPage}
onClick={() => {
router.push(`/${user.username}?tab=trades`)
}}
item={userProfileItem(user)} item={userProfileItem(user)}
/> />
)} )}
@ -67,18 +63,14 @@ export function GroupNavBar(props: {
) )
} }
function NavBarItem(props: { function NavBarItem(props: { item: Item; currentPage: string }) {
item: Item
currentPage: string
onClick: (key: string) => void
}) {
const { item, currentPage } = props const { item, currentPage } = props
const track = trackCallback( const track = trackCallback(
`group navbar: ${item.trackingEventName ?? item.name}` `group navbar: ${item.trackingEventName ?? item.name}`
) )
return ( return (
<button onClick={() => props.onClick(item.key ?? '#')}> <Link href={item.href}>
<a <a
className={clsx( className={clsx(
'block w-full py-1 px-3 text-center hover:bg-indigo-200 hover:text-indigo-700', 'block w-full py-1 px-3 text-center hover:bg-indigo-200 hover:text-indigo-700',
@ -89,6 +81,6 @@ function NavBarItem(props: {
{item.icon && <item.icon className="my-1 mx-auto h-6 w-6" />} {item.icon && <item.icon className="my-1 mx-auto h-6 w-6" />}
{item.name} {item.name}
</a> </a>
</button> </Link>
) )
} }

View File

@ -13,10 +13,25 @@ import { User } from 'common/user'
import { Row } from '../layout/row' import { Row } from '../layout/row'
import { Spacer } from '../layout/spacer' import { Spacer } from '../layout/spacer'
const groupNavigation = [ const groupNavigation = (slug: string) => [
{ name: 'Markets', key: 'markets', icon: HomeIcon }, {
{ name: 'About', key: 'about', icon: ClipboardIcon }, name: 'Markets',
{ name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, key: 'markets',
icon: HomeIcon,
href: `/group/${slug}/markets`,
},
{
name: 'About',
key: 'about',
icon: ClipboardIcon,
href: `/group/${slug}/about`,
},
{
name: 'Leaderboard',
key: 'leaderboards',
icon: TrophyIcon,
href: `/group/${slug}/leaderboards`,
},
] ]
const generalNavigation = (user?: User | null) => const generalNavigation = (user?: User | null) =>
@ -31,12 +46,12 @@ const generalNavigation = (user?: User | null) =>
export function GroupSidebar(props: { export function GroupSidebar(props: {
groupName: string groupName: string
groupSlug: string
className?: string className?: string
onClick: (key: string) => void
joinOrAddQuestionsButton: React.ReactNode joinOrAddQuestionsButton: React.ReactNode
currentKey: string currentKey: string
}) { }) {
const { className, groupName, currentKey } = props const { className, groupName, currentKey, groupSlug } = props
const user = useUser() const user = useUser()
@ -57,21 +72,11 @@ export function GroupSidebar(props: {
</div> </div>
{/* Desktop navigation */} {/* Desktop navigation */}
{groupNavigation.map((item) => ( {groupNavigation(groupSlug).map((item) => (
<SidebarItem <SidebarItem key={item.key} item={item} currentPage={currentKey} />
key={item.key}
item={item}
currentPage={currentKey}
onClick={props.onClick}
/>
))} ))}
{generalNavigation(user).map((item) => ( {generalNavigation(user).map((item) => (
<SidebarItem <SidebarItem key={item.key} item={item} currentPage={currentKey} />
key={item.key}
item={item}
currentPage={currentKey}
onClick={props.onClick}
/>
))} ))}
<Spacer h={2} /> <Spacer h={2} />

View File

@ -7,23 +7,21 @@ import { trackCallback } from 'web/lib/service/analytics'
export type Item = { export type Item = {
name: string name: string
trackingEventName?: string trackingEventName?: string
href?: string href: string
key?: string key?: string
icon?: React.ComponentType<{ className?: string }> icon?: React.ComponentType<{ className?: string }>
} }
export function SidebarItem(props: { export function SidebarItem(props: { item: Item; currentPage: string }) {
item: Item const { item, currentPage } = props
currentPage: string
onClick?: (key: string) => void
}) {
const { item, currentPage, onClick } = props
const isCurrentPage = const isCurrentPage =
item.href != null ? item.href === currentPage : item.key === currentPage item.href != null ? item.href === currentPage : item.key === currentPage
const sidebarItem = ( const sidebarItem = (
<a <a
onClick={trackCallback('sidebar: ' + item.name)} onClick={() => {
trackCallback('sidebar: ' + item.name)
}}
className={clsx( className={clsx(
isCurrentPage isCurrentPage
? 'bg-gray-200 text-gray-900' ? 'bg-gray-200 text-gray-900'
@ -47,17 +45,5 @@ export function SidebarItem(props: {
</a> </a>
) )
if (item.href) { return <Link href={item.href}>{sidebarItem}</Link>
return (
<Link href={item.href} key={item.name}>
{sidebarItem}
</Link>
)
} else {
return onClick ? (
<button onClick={() => onClick(item.key ?? '#')}>{sidebarItem}</button>
) : (
<> </>
)
}
} }

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react' import React, { useEffect, useState } from 'react'
import Link from 'next/link' import Link from 'next/link'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { toast, Toaster } from 'react-hot-toast' import { toast, Toaster } from 'react-hot-toast'
@ -140,10 +140,16 @@ export default function GroupPage(props: {
const user = useUser() const user = useUser()
const isAdmin = useAdmin() const isAdmin = useAdmin()
const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds
// Note: Keep in sync with sidebarPages // Note: Keep in sync with sidebarPages
const [sidebarIndex, setSidebarIndex] = useState( const [sidebarIndex, setSidebarIndex] = useState(
['markets', 'leaderboards', 'about'].indexOf(page ?? 'markets') ['markets', 'leaderboards', 'about'].indexOf(page ?? 'markets')
) )
useEffect(() => {
setSidebarIndex(
['markets', 'leaderboards', 'about'].indexOf(page ?? 'markets')
)
}, [page])
useSaveReferral(user, { useSaveReferral(user, {
defaultReferrerUsername: creator.username, defaultReferrerUsername: creator.username,
@ -241,16 +247,6 @@ export default function GroupPage(props: {
] ]
const pageContent = sidebarPages[sidebarIndex].content const pageContent = sidebarPages[sidebarIndex].content
const onSidebarClick = (key: string) => {
const index = sidebarPages.findIndex((t) => t.key === key)
setSidebarIndex(index)
// Append the page to the URL, e.g. /group/mexifold/markets
router.replace(
{ query: { ...router.query, slugs: [group.slug, key] } },
undefined,
{ shallow: true }
)
}
const joinOrAddQuestionsButton = ( const joinOrAddQuestionsButton = (
<JoinOrAddQuestionsButtons <JoinOrAddQuestionsButtons
@ -265,7 +261,6 @@ export default function GroupPage(props: {
<TopGroupNavBar <TopGroupNavBar
group={group} group={group}
currentPage={sidebarPages[sidebarIndex].key} currentPage={sidebarPages[sidebarIndex].key}
onClick={onSidebarClick}
/> />
<div> <div>
<div <div
@ -276,8 +271,8 @@ export default function GroupPage(props: {
<Toaster /> <Toaster />
<GroupSidebar <GroupSidebar
groupName={group.name} groupName={group.name}
groupSlug={group.slug}
className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex"
onClick={onSidebarClick}
joinOrAddQuestionsButton={joinOrAddQuestionsButton} joinOrAddQuestionsButton={joinOrAddQuestionsButton}
currentKey={sidebarPages[sidebarIndex].key} currentKey={sidebarPages[sidebarIndex].key}
/> />
@ -296,11 +291,7 @@ export default function GroupPage(props: {
) )
} }
export function TopGroupNavBar(props: { export function TopGroupNavBar(props: { group: Group; currentPage: string }) {
group: Group
currentPage: string
onClick: (key: string) => void
}) {
return ( return (
<header className="sticky top-0 z-50 w-full border-b border-gray-200 md:hidden lg:col-span-12"> <header className="sticky top-0 z-50 w-full border-b border-gray-200 md:hidden lg:col-span-12">
<div className="flex items-center bg-white px-4"> <div className="flex items-center bg-white px-4">
@ -317,7 +308,10 @@ export function TopGroupNavBar(props: {
</h1> </h1>
</div> </div>
</div> </div>
<GroupNavBar currentPage={props.currentPage} onClick={props.onClick} /> <GroupNavBar
groupSlug={props.group.slug}
currentPage={props.currentPage}
/>
</header> </header>
) )
} }