Files
nym/explorer-nextjs/app/components/Nav/DesktopNav.tsx
T
Fouad e5f41731ae Explorer NextJS Rebuild (#4534)
* bootstrap next app + add overview page

* fix AssetList type

* fix up nav stuff

* Refactor Nav component and add network components pages

* Refactor WorldMap component and update TelegramIcon, GitHubIcon, NymVpnIcon, DiscordIcon, and TwitterIcon components

* add service providers page

* mixnodes page

* delegations page + use material react table for all tables

* nodes map page

* Refactor StyledLink component and remove unnecessary console.log statements

* Refactor ESLint configuration, remove unused dependencies, and update component imports

* update deps

* Refactor imports and update dependencies

* fix dark mode

* build single mixnode page

* build single gateway page

* Refactor handleOnDelegate function to use useCallback in mixnodes page.tsx

* Add defaults for constants

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2024-05-16 16:12:06 +01:00

374 lines
9.8 KiB
TypeScript

'use client'
import * as React from 'react'
import { ExpandLess, ExpandMore, Menu } from '@mui/icons-material'
import { CSSObject, styled, Theme, useTheme } from '@mui/material/styles'
import { Link as MuiLink } from '@mui/material'
import Button from '@mui/material/Button'
import Box from '@mui/material/Box'
import ListItem from '@mui/material/ListItem'
import MuiDrawer from '@mui/material/Drawer'
import AppBar from '@mui/material/AppBar'
import Toolbar from '@mui/material/Toolbar'
import Typography from '@mui/material/Typography'
import List from '@mui/material/List'
import IconButton from '@mui/material/IconButton'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemText from '@mui/material/ListItemText'
import { NYM_WEBSITE } from '@/app/api/constants'
import { useMainContext } from '@/app/context/main'
import { MobileDrawerClose } from '@/app/icons/MobileDrawerClose'
import { NavOptionType, originalNavOptions } from '@/app/context/nav'
import { DarkLightSwitchDesktop } from '@/app/components/Switch'
import { Footer } from '@/app/components/Footer'
import { ConnectKeplrWallet } from '@/app/components/Wallet/ConnectKeplrWallet'
import { usePathname, useRouter } from 'next/navigation'
const drawerWidth = 255
const bannerHeight = 80
const openedMixin = (theme: Theme): CSSObject => ({
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
overflowX: 'hidden',
})
const closedMixin = (theme: Theme): CSSObject => ({
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: `calc(${theme.spacing(7)} + 1px)`,
})
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
height: 64,
}))
const Drawer = styled(MuiDrawer, {
shouldForwardProp: (prop) => prop !== 'open',
})(({ theme, open }) => ({
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'border-box',
...(open && {
...openedMixin(theme),
'& .MuiDrawer-paper': openedMixin(theme),
}),
...(!open && {
...closedMixin(theme),
'& .MuiDrawer-paper': closedMixin(theme),
}),
}))
type ExpandableButtonType = {
title: string
url: string
isActive?: boolean
Icon?: React.ReactNode
nested?: NavOptionType[]
isChild?: boolean
isMobile: boolean
drawIsTempOpen: boolean
drawIsFixed: boolean
isExternalLink?: boolean
openDrawer: () => void
closeDrawer?: () => void
fixDrawerClose?: () => void
}
export const ExpandableButton: FCWithChildren<ExpandableButtonType> = ({
title,
url,
drawIsTempOpen,
drawIsFixed,
Icon,
nested,
isMobile,
isChild,
isExternalLink,
openDrawer,
closeDrawer,
fixDrawerClose,
}) => {
const { palette } = useTheme()
const pathname = usePathname()
const router = useRouter()
const handleClick = () => {
if (title === 'Network Components') {
return undefined
}
if (isExternalLink) {
window.open(url, '_blank')
return undefined
}
if (!isExternalLink) {
router.push(url, {})
}
if (closeDrawer) {
closeDrawer()
}
}
const selectedStyle = {
background: palette.nym.networkExplorer.nav.selected.main,
borderRight: `3px solid ${palette.nym.highlight}`,
}
return (
<>
<ListItem
disablePadding
disableGutters
sx={{
borderBottom: isChild ? 'none' : '1px solid rgba(255, 255, 255, 0.1)',
...(pathname === url
? selectedStyle
: {
background: palette.nym.networkExplorer.nav.background,
borderRight: 'none',
}),
}}
>
<ListItemButton
onClick={() => handleClick()}
sx={{
pt: 2,
pb: 2,
background: isChild
? palette.nym.networkExplorer.nav.selected.nested
: 'none',
}}
>
<ListItemIcon sx={{ minWidth: '39px' }}>{Icon}</ListItemIcon>
<ListItemText
primary={title}
sx={{
color: palette.nym.networkExplorer.nav.text,
}}
/>
</ListItemButton>
</ListItem>
{nested?.map((each) => (
<ExpandableButton
url={each.url}
key={each.title}
title={each.title}
openDrawer={openDrawer}
drawIsTempOpen={drawIsTempOpen}
closeDrawer={closeDrawer}
drawIsFixed={drawIsFixed}
fixDrawerClose={fixDrawerClose}
isMobile={isMobile}
isChild
isExternalLink={each.isExternal}
/>
))}
</>
)
}
export const Nav: FCWithChildren = ({ children }) => {
const { environment } = useMainContext()
const [drawerIsOpen, setDrawerToOpen] = React.useState(false)
const [fixedOpen, setFixedOpen] = React.useState(false)
// Set maintenance banner to false by default to don't display it
const [openMaintenance, setOpenMaintenance] = React.useState(false)
const theme = useTheme()
const explorerName = environment
? `${environment} Explorer`
: 'Mainnet Explorer'
const switchNetworkText =
environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet'
const switchNetworkLink =
environment === 'mainnet'
? 'https://sandbox-explorer.nymtech.net'
: 'https://explorer.nymtech.net'
const fixDrawerOpen = () => {
setFixedOpen(true)
setDrawerToOpen(true)
}
const fixDrawerClose = () => {
setFixedOpen(false)
setDrawerToOpen(false)
}
const tempDrawerOpen = () => {
if (!fixedOpen) {
setDrawerToOpen(true)
}
}
const tempDrawerClose = () => {
if (!fixedOpen) {
setDrawerToOpen(false)
}
}
return (
<Box sx={{ display: 'flex' }}>
<AppBar
sx={{
background: theme.palette.nym.networkExplorer.topNav.appBar,
borderRadius: 0,
}}
>
<Toolbar
disableGutters
sx={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
ml: 0.5,
}}
>
<IconButton component="a" href={NYM_WEBSITE} target="_blank">
{/* <NymLogo /> */}
</IconButton>
<Typography
variant="h6"
noWrap
sx={{
color: theme.palette.nym.networkExplorer.nav.text,
fontSize: '18px',
fontWeight: 600,
}}
>
<MuiLink
href="/"
underline="none"
color="inherit"
textTransform="capitalize"
>
{explorerName}
</MuiLink>
<Button
size="small"
variant="outlined"
color="inherit"
href={switchNetworkLink}
sx={{
borderRadius: 2,
textTransform: 'none',
width: 150,
ml: 4,
fontSize: 14,
fontWeight: 600,
}}
>
{switchNetworkText}
</Button>
</Typography>
</Box>
<Box
sx={{
mr: 2,
alignItems: 'center',
display: 'flex',
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
width: 'auto',
pr: 0,
pl: 2,
justifyContent: 'flex-end',
alignItems: 'center',
}}
>
<Box sx={{ mr: 1 }}>
<ConnectKeplrWallet />
</Box>
<DarkLightSwitchDesktop defaultChecked />
</Box>
</Box>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
open={true}
PaperProps={{
style: {
background: theme.palette.nym.networkExplorer.nav.background,
borderRadius: 0,
top: openMaintenance ? bannerHeight : 0,
},
}}
>
<DrawerHeader
sx={{
borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
justifyContent: 'flex-start',
paddingLeft: 0,
display: 'none',
}}
>
<IconButton
onClick={drawerIsOpen ? fixDrawerClose : fixDrawerOpen}
sx={{
padding: 1,
ml: 1,
color: theme.palette.nym.networkExplorer.nav.text,
}}
>
{drawerIsOpen ? <MobileDrawerClose /> : <Menu />}
</IconButton>
</DrawerHeader>
<List
sx={{ pb: 0 }}
onMouseEnter={tempDrawerOpen}
onMouseLeave={tempDrawerClose}
>
{originalNavOptions.map((props) => (
<ExpandableButton
key={props.url}
closeDrawer={tempDrawerClose}
drawIsTempOpen={drawerIsOpen}
drawIsFixed={fixedOpen}
fixDrawerClose={fixDrawerClose}
openDrawer={tempDrawerOpen}
isMobile={false}
{...props}
/>
))}
</List>
</Drawer>
<Box
style={{ width: `calc(100% - ${drawerWidth}px` }}
sx={{ py: 5, px: 6, mt: 7 }}
>
{children}
<Footer />
</Box>
</Box>
)
}