mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-03-25 01:51:37 -04:00
241 lines
6.4 KiB
TypeScript
241 lines
6.4 KiB
TypeScript
import {
|
|
CalendarIcon,
|
|
HomeIcon,
|
|
NewspaperIcon,
|
|
QuestionMarkCircleIcon,
|
|
} from '@heroicons/react/24/outline'
|
|
import {
|
|
CogIcon,
|
|
GlobeAltIcon,
|
|
HomeIcon as SolidHomeIcon,
|
|
LinkIcon,
|
|
QuestionMarkCircleIcon as SolidQuestionIcon,
|
|
UserCircleIcon,
|
|
UsersIcon,
|
|
} from '@heroicons/react/24/solid'
|
|
import clsx from 'clsx'
|
|
import {IS_MAINTENANCE} from 'common/constants'
|
|
import {Profile} from 'common/profiles/profile'
|
|
import {User} from 'common/user'
|
|
import {buildArray} from 'common/util/array'
|
|
import {ReactNode, useState} from 'react'
|
|
import {Toaster} from 'react-hot-toast'
|
|
import {FaEnvelope} from 'react-icons/fa'
|
|
import {MdThumbUp} from 'react-icons/md'
|
|
import {Col} from 'web/components/layout/col'
|
|
import {PrivateMessagesIcon} from 'web/components/messaging/messages-icon'
|
|
import {BottomNavBar} from 'web/components/nav/bottom-nav-bar'
|
|
import {SkipLink} from 'web/components/skip-link'
|
|
import {useIsMobile} from 'web/hooks/use-is-mobile'
|
|
import {useOnline} from 'web/hooks/use-online'
|
|
import {useProfile} from 'web/hooks/use-profile'
|
|
import {useTracking} from 'web/hooks/use-tracking'
|
|
import {useUser} from 'web/hooks/use-user'
|
|
import {GoogleOneTapLogin} from 'web/lib/firebase/google-onetap-login'
|
|
|
|
import Sidebar from './nav/sidebar'
|
|
import {NotificationsIcon, SolidNotificationsIcon} from './notifications-icon'
|
|
|
|
export function PageBase(props: {
|
|
trackPageView?: string | false
|
|
trackPageProps?: Record<string, any>
|
|
className?: string
|
|
children?: ReactNode
|
|
hideSidebar?: boolean
|
|
hideBottomBar?: boolean
|
|
}) {
|
|
const {trackPageView, trackPageProps, children, className, hideSidebar, hideBottomBar} = props
|
|
const user = useUser()
|
|
const isMobile = useIsMobile()
|
|
const profile = useProfile()
|
|
|
|
const bottomNavOptions = user
|
|
? getBottomNavigation(user, profile)
|
|
: getBottomSignedOutNavigation()
|
|
// const [isModalOpen, setIsModalOpen] = useState(false)
|
|
const desktopSidebarOptions = getDesktopNavigation(user)
|
|
|
|
const mobileSidebarOptions = getMobileSidebar(user, () => setIsAddFundsModalOpen(true))
|
|
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
if (trackPageView) useTracking(`view ${trackPageView}`, trackPageProps)
|
|
useOnline()
|
|
const [_, setIsAddFundsModalOpen] = useState(false)
|
|
|
|
const colSpan = className?.split(' ').find((c) => c.startsWith('col-span-')) ?? 'col-span-8'
|
|
const restClassName = className
|
|
?.split(' ')
|
|
.filter((c) => !c.startsWith('col-span-'))
|
|
.join(' ')
|
|
|
|
return (
|
|
<>
|
|
<SkipLink />
|
|
<GoogleOneTapLogin className="fixed bottom-12 right-4 z-[1000]" />
|
|
<Col
|
|
className={clsx(
|
|
'pb-page-base lg:pb-0', // bottom bar padding
|
|
'text-ink-1000 mx-auto min-h-screen w-full lg:grid lg:grid-cols-12',
|
|
)}
|
|
>
|
|
<Toaster
|
|
position={isMobile ? 'bottom-center' : 'top-center'}
|
|
containerClassName="!bottom-[70px]"
|
|
/>
|
|
{/* Maintenance banner */}
|
|
{IS_MAINTENANCE && (
|
|
<div className="lg:col-span-12 w-full bg-orange-500 text-white text-center text-sm py-2 px-3">
|
|
Maintenance in progress: Some features may be broken for the next few hours.
|
|
</div>
|
|
)}
|
|
{hideSidebar ? (
|
|
<div className="lg:col-span-2 lg:flex" />
|
|
) : (
|
|
<Sidebar
|
|
navigationOptions={desktopSidebarOptions}
|
|
className="sticky top-0 hidden self-start px-2 lg:col-span-2 lg:flex sidebar-nav bg-canvas-25"
|
|
/>
|
|
)}
|
|
<main
|
|
id="main-content"
|
|
tabIndex={-1}
|
|
className={clsx('flex flex-1 flex-col lg:mt-6 xl:px-2', colSpan, restClassName)}
|
|
>
|
|
{children}
|
|
</main>
|
|
</Col>
|
|
{!hideBottomBar && (
|
|
<BottomNavBar
|
|
sidebarNavigationOptions={mobileSidebarOptions as any[]}
|
|
navigationOptions={bottomNavOptions}
|
|
/>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
const Profiles = {
|
|
key: 'nav.people',
|
|
name: 'People',
|
|
href: '/',
|
|
icon: UsersIcon,
|
|
}
|
|
const Home = {key: 'nav.home', name: 'Home', href: '/', icon: HomeIcon}
|
|
const faq = {
|
|
key: 'nav.faq',
|
|
name: 'FAQ',
|
|
href: '/faq',
|
|
icon: SolidQuestionIcon,
|
|
}
|
|
const About = {
|
|
key: 'nav.about',
|
|
name: 'About',
|
|
href: '/about',
|
|
icon: QuestionMarkCircleIcon,
|
|
}
|
|
const Signin = {
|
|
key: 'nav.sign_in',
|
|
name: 'Sign in',
|
|
href: '/signin',
|
|
icon: UserCircleIcon,
|
|
}
|
|
const Notifs = {
|
|
key: 'nav.notifs',
|
|
name: 'Notifs',
|
|
href: `/notifications`,
|
|
icon: NotificationsIcon,
|
|
}
|
|
const NotifsSolid = {
|
|
key: 'nav.notifs',
|
|
name: 'Notifs',
|
|
href: `/notifications`,
|
|
icon: SolidNotificationsIcon,
|
|
}
|
|
const Social = {
|
|
key: 'nav.social',
|
|
name: 'Socials',
|
|
href: '/social',
|
|
icon: LinkIcon,
|
|
}
|
|
const Organization = {
|
|
key: 'nav.organization',
|
|
name: 'Organization',
|
|
href: '/organization',
|
|
icon: GlobeAltIcon,
|
|
}
|
|
const Vote = {key: 'nav.vote', name: 'Vote', href: '/vote', icon: MdThumbUp}
|
|
const Contact = {
|
|
key: 'nav.contact',
|
|
name: 'Contact',
|
|
href: '/contact',
|
|
icon: FaEnvelope,
|
|
}
|
|
const News = {
|
|
key: 'nav.news',
|
|
name: "What's new",
|
|
href: '/news',
|
|
icon: NewspaperIcon,
|
|
}
|
|
const Settings = {
|
|
key: 'nav.settings',
|
|
name: 'Settings',
|
|
href: '/settings',
|
|
icon: CogIcon,
|
|
}
|
|
const Events = {
|
|
key: 'nav.events',
|
|
name: 'Events',
|
|
href: '/events',
|
|
icon: CalendarIcon,
|
|
}
|
|
|
|
// Stable component for Messages icon to prevent re-mounting on every render
|
|
const MessagesIconComponent = (props: any) => <PrivateMessagesIcon solid {...props} />
|
|
|
|
const base = [About, faq, Vote, Events, News, Social, Organization, Contact]
|
|
|
|
function getBottomNavigation(user: User, profile: Profile | null | undefined) {
|
|
return buildArray(
|
|
Profiles,
|
|
NotifsSolid,
|
|
{
|
|
key: 'nav.profile',
|
|
name: 'Profile',
|
|
href: profile === null ? '/signup' : `/${user.username}`,
|
|
icon: SolidHomeIcon,
|
|
},
|
|
{
|
|
key: 'nav.messages',
|
|
name: 'Messages',
|
|
href: '/messages',
|
|
icon: MessagesIconComponent,
|
|
},
|
|
)
|
|
}
|
|
|
|
const getBottomSignedOutNavigation = () => [Home, About, Signin]
|
|
|
|
const getDesktopNavigation = (user: User | null | undefined) => {
|
|
if (user)
|
|
return buildArray(
|
|
Profiles,
|
|
Notifs,
|
|
{
|
|
key: 'nav.messages',
|
|
name: 'Messages',
|
|
href: '/messages',
|
|
icon: MessagesIconComponent,
|
|
},
|
|
Settings,
|
|
...base,
|
|
)
|
|
|
|
return buildArray(...base)
|
|
}
|
|
|
|
const getMobileSidebar = (user: User | null | undefined, _toggleModal: () => void) => {
|
|
if (user) return buildArray(Settings, ...base)
|
|
|
|
return buildArray(...base)
|
|
}
|