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 { Button, Typography, Grid, ButtonGroup, Dialog, Box } from '@mui/material';
import { useHistory } from 'react-router-dom';
import currencyDict from '../../../static/assets/currencies.json';
import DepthChart from '../../components/Charts/DepthChart';
import { Book, Favorites, LimitList, Maker } from '../../models';
@ -47,25 +46,6 @@ const BookPage = ({
const maxBookTableWidth = 85;
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(() => {
if (book.orders.length < 1) {
fetchBook(true, false);
@ -87,7 +67,7 @@ const BookPage = ({
return (
<ButtonGroup variant='contained' color='inherit'>
<Button color='primary' onClick={() => setOpenMaker(true)}>
{t('Create Order')}
{t('Create')}
</Button>
{doubleView ? (
<></>
@ -108,9 +88,6 @@ const BookPage = ({
)}
</Button>
)}
<Button color='secondary' onClick={() => history.push('/')}>
{t('Back')}
</Button>
</ButtonGroup>
);
};

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
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 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 {
settings: Settings;
setSettings: (state: Settings) => void;
}
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
const [book, setBook] = useState<Book>({ orders: [], loading: true });
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 [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 }>(
getWindowSize(theme.typography.fontSize),
);
@ -130,6 +143,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
});
};
console.log(page, slideDirection);
return (
<Router basename={basename}>
<div className='temporaryUpperIcons'>
@ -141,17 +155,15 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
>
<SchoolIcon />
</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 className='appCenter'>
<Box
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: `translate(-50%, -50%) translate(0, -${navbarHeight / 2}em`,
}}
>
<Switch>
<Route
exact
@ -161,69 +173,91 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
)}
/>
<Route
path='/ref/:refCode'
path='/robot/:refCode?'
render={(props: any) => (
<UserGenPage match={props.match} theme={theme} robot={robot} setRobot={setRobot} />
)}
/>
<Route
path='/make'
render={() => (
<MakerPage
book={book}
limits={limits}
fetchLimits={fetchLimits}
maker={maker}
setMaker={setMaker}
fav={fav}
setFav={setFav}
windowSize={windowSize}
/>
)}
/>
<Route
path='/book'
render={() => (
<BookPage
book={book}
fetchBook={fetchBook}
limits={limits}
fetchLimits={fetchLimits}
fav={fav}
setFav={setFav}
maker={maker}
setMaker={setMaker}
lastDayPremium={info.last_day_nonkyc_btc_premium}
windowSize={windowSize}
/>
)}
/>
<Route path='/offers'>
<Slide
direction={page === 'offers' ? slideDirection.in : slideDirection.out}
in={page === 'offers'}
appear={slideDirection.in != undefined}
>
<div>
<BookPage
book={book}
fetchBook={fetchBook}
limits={limits}
fetchLimits={fetchLimits}
fav={fav}
setFav={setFav}
maker={maker}
setMaker={setMaker}
lastDayPremium={info.last_day_nonkyc_btc_premium}
windowSize={windowSize}
/>
</div>
</Slide>
</Route>
<Route path='/create'>
<Slide
direction={page === 'create' ? slideDirection.in : slideDirection.out}
in={page === 'create'}
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
path='/order/:orderId'
render={(props: any) => <OrderPage theme={theme} history={history} {...props} />}
/>
<Route
path='/settings'
render={(props: any) => <SettingsPage settings={settings} setSettings={setSettings} />}
/>
<Route path='/settings'>
<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>
</div>
<div
style={{
height: '2.5em',
position: 'fixed',
bottom: 0,
}}
>
<NavBar
width={windowSize.width}
robot={robot}
setRobot={setRobot}
info={info}
setInfo={setInfo}
fetchInfo={fetchInfo}
/>
</div>
</Box>
<NavBar
width={windowSize.width}
height={navbarHeight}
page={page}
setPage={setPage}
setSlideDirection={setSlideDirection}
robot={robot}
setRobot={setRobot}
info={info}
setInfo={setInfo}
fetchInfo={fetchInfo}
/>
</Router>
);
};

View File

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

View File

@ -1,52 +1,137 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom';
import {
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 { Tabs, Tab, Paper, Button, useTheme } from '@mui/material';
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 {
page: Page;
setPage: (state: Page) => void;
slideDirection: { in: Direction; out: Direction };
setSlideDirection: (state: { in: Direction; out: Direction }) => void;
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 { t } = useTranslation();
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) {
setPage(newPage);
history.push(`/${newPage}`);
const pagesPosition = {
robot: 1,
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 (
<Paper elevation={6} style={{ height: '2.5em', width: `${width * 0.9}em` }}>
{page}
<Button onClick={() => changePage('robot')}>ROBOT</Button>
<Button onClick={() => changePage('book')}>BOOK</Button>
<Button onClick={() => changePage('make')}>MAKER</Button>
<Button onClick={() => changePage('order/1')}>ORDER</Button>
<Button onClick={() => changePage('settings')}>SETTINGS</Button>
<Paper
elevation={6}
sx={{ height: `${height}em`, width: `${width * 0.9}em`, position: 'fixed', bottom: 0 }}
>
<Tabs
TabIndicatorProps={{ sx: { height: '0.3em', position: 'absolute', top: 0 } }}
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>
);
};

View File

@ -1,21 +1,30 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Paper, useTheme } from '@mui/material';
import { Grid, Paper, useTheme } from '@mui/material';
import SettingsForm from '../../components/SettingsForm';
import { Settings } from '../../models';
interface SettingsPageProps {
settings: Settings;
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 { t } = useTranslation();
const maxHeight = windowSize.height * 0.85 - 3;
return (
<Paper elevation={12} sx={{ padding: '0.6em', width: '12em', height: '12em' }}>
<SettingsForm settings={settings} setSettings={setSettings} />
<Paper
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>
);
};

View File

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

View File

@ -1,25 +1,87 @@
import React from 'react';
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 SelectLanguage from './SelectLanguage';
import { Language, Palette, LightMode, DarkMode } from '@mui/icons-material';
interface SettingsFormProps {
dense?: boolean;
settings: Settings;
setSettings: (state: Settings) => void;
}
const SettingsForm = ({ settings, setSettings }: SettingsFormProps): JSX.Element => {
const SettingsForm = ({ dense = false, settings, setSettings }: SettingsFormProps): JSX.Element => {
const theme = useTheme();
const { t } = useTranslation();
return (
<Grid container>
<Grid container spacing={1}>
<Grid item>
<SelectLanguage
language={settings.language}
setLanguage={(language) => setSettings({ ...settings, language })}
/>
<List dense={dense}>
<ListItem>
<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>
);

View File

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

View File

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