TopNavBar Added

This commit is contained in:
sahil-tgs 2024-07-16 00:07:33 +05:30
parent 6dd32780a7
commit 6729babdb5
4 changed files with 297 additions and 54 deletions

View File

@ -1,41 +1,44 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { MemoryRouter, BrowserRouter, Routes, Route } from 'react-router-dom'; import { MemoryRouter, BrowserRouter, Routes, Route } from 'react-router-dom';
import { Box, Slide, Typography, styled } from '@mui/material'; import { Box, Slide, styled } from '@mui/material';
import { type UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext'; import { type UseAppStoreType, AppContext } from '../contexts/AppContext';
import {
import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage, NavBar, MainDialogs } from './'; TopNavBar,
import RobotAvatar from '../components/RobotAvatar'; NavBar,
RobotPage,
MakerPage,
BookPage,
OrderPage,
SettingsPage,
MainDialogs,
} from './';
import Notifications from '../components/Notifications'; import Notifications from '../components/Notifications';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext'; import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext';
const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter; const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter;
const TestnetTypography = styled(Typography)({ const MainContent = styled(Box)(({ theme }) => ({
height: 0, marginTop: '100px',
}); marginBottom: '80px',
padding: theme.spacing(2),
interface MainBoxProps { overflowY: 'auto',
navbarHeight: number; overflowX: 'hidden',
} height: 'calc(100vh - 180px)',
display: 'flex',
const MainBox = styled(Box)<MainBoxProps>((props) => ({ justifyContent: 'center',
position: 'absolute', alignItems: 'center',
top: '50%',
left: '50%',
transform: `translate(-50%, -50%) translate(0, -${props.navbarHeight / 2}em)`,
})); }));
const Main: React.FC = () => { const Main: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { settings, page, slideDirection, setOpen, windowSize, navbarHeight } = const { settings, page, slideDirection, setOpen, windowSize } =
useContext<UseAppStoreType>(AppContext); useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext); const { garage } = useContext<UseGarageStoreType>(GarageContext);
return ( return (
<Router> <Router>
<RobotAvatar style={{ display: 'none' }} hashId={garage.getSlot()?.hashId} /> <TopNavBar />
<Notifications <Notifications
page={page} page={page}
openProfile={() => { openProfile={() => {
@ -44,18 +47,9 @@ const Main: React.FC = () => {
rewards={garage.getSlot()?.getRobot()?.earnedRewards} rewards={garage.getSlot()?.getRobot()?.earnedRewards}
windowWidth={windowSize?.width} windowWidth={windowSize?.width}
/> />
{settings.network === 'testnet' ? ( <MainContent>
<TestnetTypography color='secondary' align='center'>
<i>{t('Using Testnet Bitcoin')}</i>
</TestnetTypography>
) : (
<></>
)}
<MainBox navbarHeight={navbarHeight}>
<Routes> <Routes>
{['/robot/:token?', '/', ''].map((path, index) => { {['/robot/:token?', '/', ''].map((path, index) => (
return (
<Route <Route
path={path} path={path}
element={ element={
@ -71,9 +65,7 @@ const Main: React.FC = () => {
} }
key={index} key={index}
/> />
); ))}
})}
<Route <Route
path={'/offers'} path={'/offers'}
element={ element={
@ -88,7 +80,6 @@ const Main: React.FC = () => {
</Slide> </Slide>
} }
/> />
<Route <Route
path='/create' path='/create'
element={ element={
@ -103,7 +94,6 @@ const Main: React.FC = () => {
</Slide> </Slide>
} }
/> />
<Route <Route
path='/order/:shortAlias/:orderId' path='/order/:shortAlias/:orderId'
element={ element={
@ -118,7 +108,6 @@ const Main: React.FC = () => {
</Slide> </Slide>
} }
/> />
<Route <Route
path='/settings' path='/settings'
element={ element={
@ -134,7 +123,7 @@ const Main: React.FC = () => {
} }
/> />
</Routes> </Routes>
</MainBox> </MainContent>
<NavBar /> <NavBar />
<MainDialogs /> <MainDialogs />
</Router> </Router>

View File

@ -0,0 +1,250 @@
import React, { useContext, useState } from 'react';
import {
AppBar,
Toolbar,
Typography,
IconButton,
Box,
useMediaQuery,
styled,
useTheme,
Drawer,
List,
ListItem,
ListItemText,
Divider,
} from '@mui/material';
import MenuIcon from '@mui/icons-material/Menu';
import CloseIcon from '@mui/icons-material/Close';
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
import { AppContext, type UseAppStoreType, closeAll } from '../../contexts/AppContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
import RobotAvatar from '../../components/RobotAvatar';
import { RoboSatsTextIcon } from '../../components/Icons';
import { useTranslation } from 'react-i18next';
const NAVBAR_HEIGHT = '64px';
const StyledAppBar = styled(AppBar)(({ theme, isMobile, drawerOpen }) => ({
height: NAVBAR_HEIGHT,
display: 'flex',
justifyContent: 'center',
boxShadow: isMobile ? 'none' : '8px 8px 0px 0px rgba(0,0,0,1)',
backgroundColor: theme.palette.background.paper,
borderBottom: isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
border: !isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
borderRadius: isMobile ? '0' : '1vw',
padding: isMobile ? '0' : '1vh',
top: isMobile ? 0 : theme.spacing(2),
left: '50%',
transform: 'translateX(-50%)',
width: isMobile ? '100%' : 'calc(100% - 64px)',
position: 'fixed',
zIndex: 1100,
...(drawerOpen &&
isMobile && {
background: 'none',
backgroundColor: theme.palette.background.paper,
}),
}));
const StyledToolbar = styled(Toolbar)(({ theme }) => ({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
padding: '0 5vw',
minHeight: NAVBAR_HEIGHT,
}));
const CenterBox = styled(Box)({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '2vw',
flexGrow: 1,
});
const CenterButton = styled(Typography)(({ theme }) => ({
cursor: 'pointer',
color: theme.palette.mode === 'dark' ? '#fff' : '#000',
'&:hover': {
textDecoration: 'underline',
},
}));
const MobileToolbarContent = styled(Box)(({ theme }) => ({
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%',
marginLeft: theme.spacing(2),
}));
const TopNavBar = (): JSX.Element => {
const theme = useTheme();
const { t } = useTranslation();
const { setOpen, open } = useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [drawerOpen, setDrawerOpen] = useState(false);
const slot = garage.getSlot();
const navItems = [
{ label: 'Robosats Info', key: 'info' },
{ label: 'Learn Robosats', key: 'learn' },
{ label: 'Community', key: 'community' },
{ label: 'Exchange Summary', key: 'exchange' },
];
const toggleDrawer = (open: boolean) => () => {
setDrawerOpen(open);
};
const handleLogoClick = () => {
setOpen({ ...closeAll, client: !open.client });
};
return (
<>
<StyledAppBar
position='fixed'
elevation={drawerOpen ? 0 : 3}
isMobile={isMobile}
drawerOpen={drawerOpen}
>
<StyledToolbar>
<svg width={0} height={0}>
<linearGradient id='linearColors' x1={1} y1={0} x2={1} y2={1}>
<stop offset={0} stopColor={theme.palette.primary.main} />
<stop offset={1} stopColor={theme.palette.secondary.main} />
</linearGradient>
</svg>
{isMobile ? (
<>
<IconButton edge='start' aria-label='menu' onClick={toggleDrawer(true)}>
{drawerOpen ? (
<CloseIcon style={{ color: theme.palette.mode === 'dark' ? '#fff' : '#000' }} />
) : (
<MenuIcon style={{ color: theme.palette.mode === 'dark' ? '#fff' : '#000' }} />
)}
</IconButton>
<MobileToolbarContent>
<IconButton
edge='end'
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
style={{ visibility: slot?.hashId ? 'visible' : 'hidden' }}
>
{slot?.hashId ? (
<RobotAvatar
style={{ width: '2.5em', height: '2.5em' }}
avatarClass={
theme.palette.mode === 'dark' ? 'navBarAvatarDark' : 'navBarAvatar'
}
hashId={slot?.hashId}
/>
) : (
<AccountCircleIcon style={{ fontSize: '1.5em' }} />
)}
</IconButton>
</MobileToolbarContent>
<Drawer
anchor='left'
open={drawerOpen}
onClose={toggleDrawer(false)}
BackdropProps={{ invisible: true }}
PaperProps={{
style: {
marginTop: NAVBAR_HEIGHT,
borderLeft: '2px solid black',
borderRight: '2px solid black',
borderBottom: '2px solid black',
},
}}
>
<List>
<ListItem
button
onClick={handleLogoClick}
sx={{ borderBottom: '1px solid black' }}
>
<RoboSatsTextIcon
sx={{
height: '2em',
width: 'auto',
cursor: 'pointer',
fill: 'url(#linearColors)',
}}
/>
</ListItem>
<Divider />
{navItems.map((item) => (
<ListItem
button
key={item.key}
onClick={() => setOpen({ ...closeAll, [item.key]: !open[item.key] })}
sx={{
borderBottom: `1px solid ${theme.palette.divider}`,
padding: theme.spacing(2),
}}
>
<ListItemText primary={t(item.label)} />
</ListItem>
))}
</List>
</Drawer>
</>
) : (
<>
<RoboSatsTextIcon
sx={{
height: '1.5em',
width: 'auto',
cursor: 'pointer',
marginLeft: -2,
fill: 'url(#linearColors)',
}}
onClick={handleLogoClick}
/>
<CenterBox>
{navItems.map((item) => (
<CenterButton
key={item.key}
onClick={() => setOpen({ ...closeAll, [item.key]: !open[item.key] })}
>
{t(item.label)}
</CenterButton>
))}
</CenterBox>
<IconButton
edge='end'
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
style={{ visibility: slot?.hashId ? 'visible' : 'hidden' }}
>
{slot?.hashId ? (
<RobotAvatar
style={{ width: '2.5em', height: '2.5em' }}
avatarClass={
theme.palette.mode === 'dark' ? 'navBarAvatarDark' : 'navBarAvatar'
}
hashId={slot?.hashId}
/>
) : (
<AccountCircleIcon style={{ fontSize: '1.5em' }} />
)}
</IconButton>
</>
)}
</StyledToolbar>
</StyledAppBar>
</>
);
};
export default TopNavBar;

View File

@ -0,0 +1,3 @@
import TopNavBar from './TopNavBar';
export default TopNavBar;

View File

@ -5,3 +5,4 @@ export { default as NavBar } from './NavBar';
export { default as OrderPage } from './OrderPage'; export { default as OrderPage } from './OrderPage';
export { default as RobotPage } from './RobotPage'; export { default as RobotPage } from './RobotPage';
export { default as SettingsPage } from './SettingsPage'; export { default as SettingsPage } from './SettingsPage';
export { default as TopNavBar } from './TopNavBar';