mirror of
https://github.com/RoboSats/robosats.git
synced 2025-02-26 15:19:00 +00:00
TopNavBar Added
This commit is contained in:
parent
6dd32780a7
commit
6729babdb5
@ -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>
|
||||||
|
250
frontend/src/basic/TopNavBar/TopNavBar.tsx
Normal file
250
frontend/src/basic/TopNavBar/TopNavBar.tsx
Normal 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;
|
3
frontend/src/basic/TopNavBar/index.tsx
Normal file
3
frontend/src/basic/TopNavBar/index.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import TopNavBar from './TopNavBar';
|
||||||
|
|
||||||
|
export default TopNavBar;
|
@ -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';
|
||||||
|
Loading…
Reference in New Issue
Block a user