Add sliding pages

This commit is contained in:
Reckless_Satoshi 2022-10-27 16:26:07 -07:00
parent 6dd90aa118
commit da8b70091b
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
9 changed files with 312 additions and 160 deletions

View File

@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Button, Typography, Grid, ButtonGroup, Dialog, Box } from '@mui/material'; import { Button, Typography, Grid, ButtonGroup, Dialog, Box } from '@mui/material';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import currencyDict from '../../../static/assets/currencies.json';
import DepthChart from '../../components/Charts/DepthChart'; import DepthChart from '../../components/Charts/DepthChart';
import { Book, Favorites, LimitList, Maker } from '../../models'; import { Book, Favorites, LimitList, Maker } from '../../models';
@ -47,25 +46,6 @@ const BookPage = ({
const maxBookTableWidth = 85; const maxBookTableWidth = 85;
const chartWidthEm = width - maxBookTableWidth; const chartWidthEm = width - maxBookTableWidth;
const defaultMaker: Maker = {
isExplicit: false,
amount: '',
paymentMethods: [],
paymentMethodsText: 'not specified',
badPaymentMethod: false,
premium: '',
satoshis: '',
publicExpiryTime: new Date(0, 0, 0, 23, 59),
publicDuration: 86340,
escrowExpiryTime: new Date(0, 0, 0, 3, 0),
escrowDuration: 10800,
bondSize: 3,
minAmount: '',
maxAmount: '',
badPremiumText: '',
badSatoshisText: '',
};
useEffect(() => { useEffect(() => {
if (book.orders.length < 1) { if (book.orders.length < 1) {
fetchBook(true, false); fetchBook(true, false);
@ -87,7 +67,7 @@ const BookPage = ({
return ( return (
<ButtonGroup variant='contained' color='inherit'> <ButtonGroup variant='contained' color='inherit'>
<Button color='primary' onClick={() => setOpenMaker(true)}> <Button color='primary' onClick={() => setOpenMaker(true)}>
{t('Create Order')} {t('Create')}
</Button> </Button>
{doubleView ? ( {doubleView ? (
<></> <></>
@ -108,9 +88,6 @@ const BookPage = ({
)} )}
</Button> </Button>
)} )}
<Button color='secondary' onClick={() => history.push('/')}>
{t('Back')}
</Button>
</ButtonGroup> </ButtonGroup>
); );
}; };

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { HashRouter, BrowserRouter, Switch, Route, useHistory } from 'react-router-dom'; import { HashRouter, BrowserRouter, Switch, Route, useHistory } from 'react-router-dom';
import { useTheme, IconButton } from '@mui/material'; import { useTheme, IconButton, Box, Slide } from '@mui/material';
import UserGenPage from './UserGenPage'; import UserGenPage from './UserGenPage';
import MakerPage from './MakerPage'; import MakerPage from './MakerPage';
@ -39,18 +39,18 @@ const getWindowSize = function (fontSize: number) {
}; };
}; };
type Page = 'robot' | 'order' | 'create' | 'offers' | 'settings' | 'none';
interface SlideDirection {
in: 'left' | 'right' | undefined;
out: 'left' | 'right' | undefined;
}
interface MainProps { interface MainProps {
settings: Settings; settings: Settings;
setSettings: (state: Settings) => void; setSettings: (state: Settings) => void;
} }
const Main = ({ settings, setSettings }: MainProps): JSX.Element => { const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
const theme = useTheme();
const history = useHistory();
const Router = window.NativeRobosats != null ? HashRouter : BrowserRouter;
const basename = window.NativeRobosats != null ? window.location.pathname : '';
const [openLearn, setOpenLearn] = useState<boolean>(false);
// All app data structured // All app data structured
const [book, setBook] = useState<Book>({ orders: [], loading: true }); const [book, setBook] = useState<Book>({ orders: [], loading: true });
const [limits, setLimits] = useState<{ list: LimitList; loading: boolean }>({ const [limits, setLimits] = useState<{ list: LimitList; loading: boolean }>({
@ -62,6 +62,19 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
const [info, setInfo] = useState<Info>(defaultInfo); const [info, setInfo] = useState<Info>(defaultInfo);
const [fav, setFav] = useState<Favorites>({ type: null, currency: 0 }); const [fav, setFav] = useState<Favorites>({ type: null, currency: 0 });
const theme = useTheme();
const history = useHistory();
const Router = window.NativeRobosats != null ? HashRouter : BrowserRouter;
const basename = window.NativeRobosats != null ? window.location.pathname : '';
const [page, setPage] = useState<Page>(window.location.pathname.split('/')[1]);
const [slideDirection, setSlideDirection] = useState<SlideDirection>({
in: undefined,
out: undefined,
});
const navbarHeight = 2.5;
const [openLearn, setOpenLearn] = useState<boolean>(false);
const [windowSize, setWindowSize] = useState<{ width: number; height: number }>( const [windowSize, setWindowSize] = useState<{ width: number; height: number }>(
getWindowSize(theme.typography.fontSize), getWindowSize(theme.typography.fontSize),
); );
@ -130,6 +143,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
}); });
}; };
console.log(page, slideDirection);
return ( return (
<Router basename={basename}> <Router basename={basename}>
<div className='temporaryUpperIcons'> <div className='temporaryUpperIcons'>
@ -141,17 +155,15 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
> >
<SchoolIcon /> <SchoolIcon />
</IconButton> </IconButton>
<IconButton
color='inherit'
sx={{ position: 'fixed', right: '0px', color: 'text.secondary' }}
onClick={() =>
setSettings({ ...settings, mode: settings.mode === 'dark' ? 'light' : 'dark' })
}
>
{theme.palette.mode === 'dark' ? <LightModeIcon /> : <DarkModeIcon />}
</IconButton>
</div> </div>
<div className='appCenter'> <Box
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: `translate(-50%, -50%) translate(0, -${navbarHeight / 2}em`,
}}
>
<Switch> <Switch>
<Route <Route
exact exact
@ -161,69 +173,91 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
)} )}
/> />
<Route <Route
path='/ref/:refCode' path='/robot/:refCode?'
render={(props: any) => ( render={(props: any) => (
<UserGenPage match={props.match} theme={theme} robot={robot} setRobot={setRobot} /> <UserGenPage match={props.match} theme={theme} robot={robot} setRobot={setRobot} />
)} )}
/> />
<Route
path='/make' <Route path='/offers'>
render={() => ( <Slide
<MakerPage direction={page === 'offers' ? slideDirection.in : slideDirection.out}
book={book} in={page === 'offers'}
limits={limits} appear={slideDirection.in != undefined}
fetchLimits={fetchLimits} >
maker={maker} <div>
setMaker={setMaker} <BookPage
fav={fav} book={book}
setFav={setFav} fetchBook={fetchBook}
windowSize={windowSize} limits={limits}
/> fetchLimits={fetchLimits}
)} fav={fav}
/> setFav={setFav}
<Route maker={maker}
path='/book' setMaker={setMaker}
render={() => ( lastDayPremium={info.last_day_nonkyc_btc_premium}
<BookPage windowSize={windowSize}
book={book} />
fetchBook={fetchBook} </div>
limits={limits} </Slide>
fetchLimits={fetchLimits} </Route>
fav={fav}
setFav={setFav} <Route path='/create'>
maker={maker} <Slide
setMaker={setMaker} direction={page === 'create' ? slideDirection.in : slideDirection.out}
lastDayPremium={info.last_day_nonkyc_btc_premium} in={page === 'create'}
windowSize={windowSize} appear={slideDirection.in != undefined}
/> >
)} <div>
/> <MakerPage
book={book}
limits={limits}
fetchLimits={fetchLimits}
maker={maker}
setMaker={setMaker}
fav={fav}
setFav={setFav}
windowSize={{ ...windowSize, height: windowSize.height - navbarHeight }}
/>
</div>
</Slide>
</Route>
<Route <Route
path='/order/:orderId' path='/order/:orderId'
render={(props: any) => <OrderPage theme={theme} history={history} {...props} />} render={(props: any) => <OrderPage theme={theme} history={history} {...props} />}
/> />
<Route
path='/settings' <Route path='/settings'>
render={(props: any) => <SettingsPage settings={settings} setSettings={setSettings} />} <Slide
/> direction={page === 'settings' ? slideDirection.in : slideDirection.out}
in={page === 'settings'}
appear={slideDirection.in != undefined}
mountOnEnter
>
<div>
<SettingsPage
settings={settings}
setSettings={setSettings}
windowSize={{ ...windowSize, height: windowSize.height - navbarHeight }}
/>
</div>
</Slide>
</Route>
</Switch> </Switch>
</div> </Box>
<div <NavBar
style={{ width={windowSize.width}
height: '2.5em', height={navbarHeight}
position: 'fixed', page={page}
bottom: 0, setPage={setPage}
}} setSlideDirection={setSlideDirection}
> robot={robot}
<NavBar setRobot={setRobot}
width={windowSize.width} info={info}
robot={robot} setInfo={setInfo}
setRobot={setRobot} fetchInfo={fetchInfo}
info={info} />
setInfo={setInfo}
fetchInfo={fetchInfo}
/>
</div>
</Router> </Router>
); );
}; };

View File

@ -1,6 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom';
import { Button, Grid, Paper, Collapse, Typography } from '@mui/material'; import { Button, Grid, Paper, Collapse, Typography } from '@mui/material';
import { LimitList, Maker, Book, Favorites } from '../../models'; import { LimitList, Maker, Book, Favorites } from '../../models';
@ -32,9 +31,8 @@ const MakerPage = ({
windowSize, windowSize,
}: MakerPageProps): JSX.Element => { }: MakerPageProps): JSX.Element => {
const { t } = useTranslation(); const { t } = useTranslation();
const history = useHistory();
const maxHeight = windowSize.height * 0.85 - 7; const maxHeight = windowSize.height * 0.85 - 3;
const [showMatches, setShowMatches] = useState<boolean>(false); const [showMatches, setShowMatches] = useState<boolean>(false);
const matches = filterOrders({ const matches = filterOrders({
@ -96,11 +94,6 @@ const MakerPage = ({
/> />
</Paper> </Paper>
</Grid> </Grid>
<Grid item>
<Button color='secondary' variant='contained' onClick={() => history.push('/')}>
{t('Back')}
</Button>
</Grid>
</Grid> </Grid>
); );
}; };

View File

@ -1,52 +1,137 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { import { Tabs, Tab, Paper, Button, useTheme } from '@mui/material';
Badge,
Tooltip,
ListItemAvatar,
Paper,
Button,
Grid,
IconButton,
Select,
MenuItem,
ListItemText,
ListItem,
ListItemIcon,
ListItemButton,
useTheme,
} from '@mui/material';
import { Link as LinkRouter } from 'react-router-dom';
import { apiClient } from '../../services/api';
import { systemClient } from '../../services/System';
import RobotAvatar from '../../components/RobotAvatar'; import RobotAvatar from '../../components/RobotAvatar';
import {
SettingsApplications,
SmartToy,
Storefront,
AddBox,
Assignment,
MoreHoriz,
} from '@mui/icons-material';
type Page = 'robot' | 'offers' | 'create' | 'order' | 'settings' | 'none';
type Direction = 'left' | 'right' | 'none';
interface NavBarProps { interface NavBarProps {
page: Page;
setPage: (state: Page) => void;
slideDirection: { in: Direction; out: Direction };
setSlideDirection: (state: { in: Direction; out: Direction }) => void;
width: number; width: number;
height: number;
} }
type Page = 'robot' | 'order' | 'make' | 'book' | 'settings';
const NavBar = ({ width }: NavBarProps): JSX.Element => { const NavBar = ({
page,
setPage,
slideDirection,
setSlideDirection,
width,
height,
}: NavBarProps): JSX.Element => {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation();
const history = useHistory(); const history = useHistory();
const { pathname } = history.location; const smallBar = width < 50;
const tabWidth = smallBar ? 1 : 1;
const [page, setPage] = useState<Page>(history.location.pathname.split('/')); const [showMore, setShowMore] = useState<boolean>(false);
const [newPage, setNewPage] = useState<Page>(history.location.pathname.split('/')[1]);
const changePage = function (newPage: Page) { const pagesPosition = {
setPage(newPage); robot: 1,
history.push(`/${newPage}`); offers: 2,
create: 3,
order: 4,
settings: 5,
};
const handleSlideDirection = function (oldPage: Page, newPage: Page) {
const oldPos: number = pagesPosition[oldPage];
const newPos: number = pagesPosition[newPage];
setSlideDirection(
newPos > oldPos ? { in: 'left', out: 'right' } : { in: 'right', out: 'left' },
);
}; };
const changePage = function (mouseEvent: any, newPage: Page) {
if (newPage === 'none') {
return null;
} else {
handleSlideDirection(page, newPage);
setNewPage(newPage);
setTimeout(() => history.push(`/${newPage}`), theme.transitions.duration.leavingScreen * 3);
}
};
useEffect(() => {
setPage(newPage);
}, [slideDirection, newPage]);
return ( return (
<Paper elevation={6} style={{ height: '2.5em', width: `${width * 0.9}em` }}> <Paper
{page} elevation={6}
<Button onClick={() => changePage('robot')}>ROBOT</Button> sx={{ height: `${height}em`, width: `${width * 0.9}em`, position: 'fixed', bottom: 0 }}
<Button onClick={() => changePage('book')}>BOOK</Button> >
<Button onClick={() => changePage('make')}>MAKER</Button> <Tabs
<Button onClick={() => changePage('order/1')}>ORDER</Button> TabIndicatorProps={{ sx: { height: '0.3em', position: 'absolute', top: 0 } }}
<Button onClick={() => changePage('settings')}>SETTINGS</Button> variant={smallBar ? 'scrollable' : 'fullWidth'}
centered={!smallBar}
allowScrollButtonsMobile
scrollButtons={smallBar}
value={page}
onChange={changePage}
aria-label='navigation bar'
>
<Tab
sx={{ maxWidth: `${tabWidth}em` }}
label={smallBar ? undefined : t('Robot')}
value='robot'
icon={<SmartToy />}
iconPosition='start'
/>
<Tab
sx={{ maxWidth: `${tabWidth}em` }}
label={smallBar ? undefined : t('Offers')}
value='offers'
icon={<Storefront />}
iconPosition='start'
/>
<Tab
sx={{ maxWidth: `${tabWidth}em` }}
label={smallBar ? undefined : t('Create')}
value='create'
icon={<AddBox />}
iconPosition='start'
/>
<Tab
sx={{ maxWidth: `${tabWidth}em` }}
label={smallBar ? undefined : t('Order')}
value='order/1'
icon={<Assignment />}
iconPosition='start'
/>
<Tab
sx={{ maxWidth: `${tabWidth}em` }}
label={smallBar ? undefined : t('Settings')}
value='settings'
icon={<SettingsApplications />}
iconPosition='start'
/>
<Tab
sx={{ maxWidth: `${tabWidth}em` }}
label={smallBar ? undefined : t('More')}
value={'none'}
onClick={() => {
setShowMore(!showMore);
}}
icon={<MoreHoriz />}
iconPosition='start'
/>
</Tabs>
</Paper> </Paper>
); );
}; };

View File

@ -1,21 +1,30 @@
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Paper, useTheme } from '@mui/material'; import { Grid, Paper, useTheme } from '@mui/material';
import SettingsForm from '../../components/SettingsForm'; import SettingsForm from '../../components/SettingsForm';
import { Settings } from '../../models'; import { Settings } from '../../models';
interface SettingsPageProps { interface SettingsPageProps {
settings: Settings; settings: Settings;
setSettings: (state: Settings) => void; setSettings: (state: Settings) => void;
windowSize: { width: number; height: number };
} }
const SettingsPage = ({ settings, setSettings }: SettingsPageProps): JSX.Element => { const SettingsPage = ({ settings, setSettings, windowSize }: SettingsPageProps): JSX.Element => {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(); const { t } = useTranslation();
const maxHeight = windowSize.height * 0.85 - 3;
return ( return (
<Paper elevation={12} sx={{ padding: '0.6em', width: '12em', height: '12em' }}> <Paper
<SettingsForm settings={settings} setSettings={setSettings} /> elevation={12}
sx={{ padding: '0.6em', width: '17.25em', maxHeight: `${maxHeight}em`, overflow: 'auto' }}
>
<Grid container>
<Grid item>
<SettingsForm settings={settings} setSettings={setSettings} />
</Grid>
</Grid>
</Paper> </Paper>
); );
}; };

View File

@ -28,6 +28,7 @@ interface SelectLanguageProps {
language: Language; language: Language;
setLanguage: (lang: Language) => void; setLanguage: (lang: Language) => void;
} }
const SelectLanguage = ({ language, setLanguage }: SelectLanguageProps): JSX.Element => { const SelectLanguage = ({ language, setLanguage }: SelectLanguageProps): JSX.Element => {
const theme = useTheme(); const theme = useTheme();
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
@ -42,10 +43,9 @@ const SelectLanguage = ({ language, setLanguage }: SelectLanguageProps): JSX.Ele
i18n.changeLanguage(e.target.value); i18n.changeLanguage(e.target.value);
}; };
console.log(language);
return ( return (
<Select <Select
autoWidth={true} fullWidth={true}
value={language} value={language}
inputProps={{ inputProps={{
style: { textAlign: 'center' }, style: { textAlign: 'center' },

View File

@ -1,25 +1,87 @@
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Grid, useTheme } from '@mui/material'; import {
Grid,
Paper,
Switch,
useTheme,
FormControlLabel,
List,
ListItem,
ListItemIcon,
} from '@mui/material';
import { Settings } from '../../models'; import { Settings } from '../../models';
import SelectLanguage from './SelectLanguage'; import SelectLanguage from './SelectLanguage';
import { Language, Palette, LightMode, DarkMode } from '@mui/icons-material';
interface SettingsFormProps { interface SettingsFormProps {
dense?: boolean;
settings: Settings; settings: Settings;
setSettings: (state: Settings) => void; setSettings: (state: Settings) => void;
} }
const SettingsForm = ({ settings, setSettings }: SettingsFormProps): JSX.Element => { const SettingsForm = ({ dense = false, settings, setSettings }: SettingsFormProps): JSX.Element => {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Grid container> <Grid container spacing={1}>
<Grid item> <Grid item>
<SelectLanguage <List dense={dense}>
language={settings.language} <ListItem>
setLanguage={(language) => setSettings({ ...settings, language })} <ListItemIcon>
/> <Language />
</ListItemIcon>
<SelectLanguage
language={settings.language}
setLanguage={(language) => setSettings({ ...settings, language })}
/>
</ListItem>
<ListItem>
<ListItemIcon>
<Palette />
</ListItemIcon>
<FormControlLabel
labelPlacement='end'
label={settings.mode === 'dark' ? t('Dark') : t('Light')}
control={
<Switch
checked={settings.mode === 'dark'}
checkedIcon={
<Paper
elevation={3}
sx={{
width: '1.2em',
height: '1.2em',
borderRadius: '0.4em',
backgroundColor: 'white',
}}
>
<DarkMode sx={{ width: '0.8em', height: '0.8em', color: '#666' }} />
</Paper>
}
icon={
<Paper
elevation={3}
sx={{
width: '1.2em',
height: '1.2em',
borderRadius: '0.4em',
backgroundColor: 'white',
padding: '0.07em',
}}
>
<LightMode sx={{ width: '0.7em', height: '0.7em', color: '#666' }} />
</Paper>
}
onChange={(e) =>
setSettings({ ...settings, mode: e.target.checked ? 'dark' : 'light' })
}
/>
}
/>
</ListItem>
</List>
</Grid> </Grid>
</Grid> </Grid>
); );

View File

@ -46,13 +46,6 @@ body {
} }
} }
.appCenter {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) translate(0, -20px);
}
.alertUnsafe { .alertUnsafe {
position: absolute; position: absolute;
width: 100%; width: 100%;

View File

@ -4,13 +4,12 @@ from .views import basic, pro
urlpatterns = [ urlpatterns = [
path("", basic), path("", basic),
path("make/", basic), path("create/", basic),
path("robot/", basic), path("robot/", basic),
path("ref/<refCode>", basic), path("robot/<refCode>", basic),
path("book/", basic), path("offers/", basic),
path("order/<int:orderId>", basic), path("order/<int:orderId>", basic),
path("settings/", basic), path("settings/", basic),
path("", basic), path("", basic),
path("ref/<refCode>", basic),
path("pro/", pro), path("pro/", pro),
] ]