Add Main component WIP

This commit is contained in:
Reckless_Satoshi 2022-10-17 08:54:55 -07:00
parent e43b274c33
commit 037d46ceef
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
10 changed files with 260 additions and 256 deletions

View File

@ -1,6 +1,6 @@
import React, { Suspense, useState } from 'react';
import ReactDOM from 'react-dom/client';
import HomePage from './HomePage';
import Main from './Main';
import { CssBaseline, IconButton } from '@mui/material';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import UnsafeAlert from './UnsafeAlert';
@ -83,7 +83,7 @@ const App = (): JSX.Element => {
{theme.palette.mode === 'dark' ? <LightModeIcon /> : <DarkModeIcon />}
</IconButton>
<UnsafeAlert className='unsafeAlert' />
<HomePage theme={theme} />
<Main />
</ThemeProvider>
</I18nextProvider>
</Suspense>

View File

@ -5,7 +5,7 @@ import { useHistory } from 'react-router-dom';
import currencyDict from '../../../static/assets/currencies.json';
import DepthChart from '../Charts/DepthChart';
import { Order, LimitList, Maker } from '../../models';
import { Book, Order, LimitList, Maker } from '../../models';
// Icons
import { BarChart, FormatListBulleted } from '@mui/icons-material';
@ -13,27 +13,24 @@ import BookTable from './BookTable';
import { MakerForm } from '../MakerPage';
interface BookPageProps {
bookLoading?: boolean;
bookRefreshing?: boolean;
loadingLimits: boolean;
lastDayPremium: number;
orders: Order[];
book: Book;
limits: LimitList;
fetchLimits: () => void;
type: number;
currency: number;
windowWidth: number;
windowHeight: number;
fetchBook: (loading: boolean, refreshing: boolean) => void;
fetchBook: () => void;
setAppState: (state: object) => void;
}
const BookPage = ({
bookLoading = false,
bookRefreshing = false,
lastDayPremium = 0,
loadingLimits,
orders = [],
book = { orders: [], loading: true },
limits,
fetchLimits,
type,
@ -75,7 +72,7 @@ const BookPage = ({
const [maker, setMaker] = useState<Maker>(defaultMaker);
useEffect(() => {
if (orders.length < 1) {
if (book.orders.length < 1) {
fetchBook(true, false);
} else {
fetchBook(false, true);
@ -184,10 +181,8 @@ const BookPage = ({
>
<Grid item>
<BookTable
loading={bookLoading}
refreshing={bookRefreshing}
clickRefresh={() => fetchBook(false, true)}
orders={orders}
clickRefresh={() => fetchBook()}
book={book}
type={type}
currency={currency}
maxWidth={maxBookTableWidth} // EM units
@ -215,8 +210,7 @@ const BookPage = ({
</Grid>
) : view === 'depth' ? (
<DepthChart
bookLoading={bookLoading}
orders={orders}
book={book}
lastDayPremium={lastDayPremium}
currency={currency}
compact={true}
@ -227,10 +221,8 @@ const BookPage = ({
/>
) : (
<BookTable
loading={bookLoading}
refreshing={bookRefreshing}
clickRefresh={() => fetchBook(false, true)}
orders={orders}
book={book}
clickRefresh={() => fetchBook()}
type={type}
currency={currency}
maxWidth={windowWidth * 0.97} // EM units

View File

@ -18,7 +18,7 @@ import {
} from '@mui/material';
import { DataGrid, GridPagination } from '@mui/x-data-grid';
import currencyDict from '../../../static/assets/currencies.json';
import { Order } from '../../models';
import { Book, Order } from '../../models';
import filterOrders from '../../utils/filterOrders';
import BookControl from './BookControl';
@ -30,13 +30,11 @@ import hexToRgb from '../../utils/hexToRgb';
import statusBadgeColor from '../../utils/statusBadgeColor';
// Icons
import { Fullscreen, FullscreenExit, Refresh, WidthFull } from '@mui/icons-material';
import { Fullscreen, FullscreenExit, Refresh } from '@mui/icons-material';
interface Props {
loading?: boolean;
refreshing?: boolean;
clickRefresh?: () => void;
orders: Order[];
book: Book;
type: number;
currency: number;
maxWidth: number;
@ -52,10 +50,8 @@ interface Props {
}
const BookTable = ({
loading = false,
refreshing = false,
clickRefresh,
orders,
book,
type,
currency,
maxWidth,
@ -702,17 +698,17 @@ const BookTable = ({
rows={
showControls
? filterOrders({
orders,
orders: book.orders,
baseFilter: { currency, type },
paymentMethods,
})
: orders
: book.orders
}
loading={loading || refreshing}
loading={book.loading}
columns={columns}
hideFooter={!showFooter}
components={gridComponents()}
pageSize={loading ? 0 : pageSize}
pageSize={book.loading && book.orders.length == 0 ? 0 : pageSize}
rowsPerPageOptions={width < 22 ? [] : [0, pageSize, defaultPageSize * 2, 50, 100]}
onPageSizeChange={(newPageSize) => {
setPageSize(newPageSize);
@ -728,16 +724,20 @@ const BookTable = ({
<Paper style={{ width: '100%', height: '100%', overflow: 'auto' }}>
<DataGrid
localeText={localeText}
rows={orders.filter(
(order) =>
(order.type == type || type == null) &&
(order.currency == currency || currency == 0),
)}
loading={loading || refreshing}
rows={
showControls
? filterOrders({
orders: book.orders,
baseFilter: { currency, type },
paymentMethods,
})
: book.orders
}
loading={book.loading}
columns={columns}
hideFooter={!showFooter}
components={gridComponents()}
pageSize={loading ? 0 : pageSize}
pageSize={book.loading && book.orders.length == 0 ? 0 : pageSize}
rowsPerPageOptions={[0, pageSize, defaultPageSize * 2, 50, 100]}
onPageSizeChange={(newPageSize) => {
setPageSize(newPageSize);

View File

@ -1,187 +0,0 @@
import React, { Component } from 'react';
import { HashRouter, BrowserRouter, Switch, Route } from 'react-router-dom';
import UserGenPage from './UserGenPage';
import MakerPage from './MakerPage';
import BookPage from './BookPage';
import OrderPage from './OrderPage';
import BottomBar from './BottomBar';
import { apiClient } from '../services/api';
export default class HomePage extends Component {
constructor(props) {
super(props);
this.state = {
nickname: null,
token: null,
copiedToken: false,
avatarLoaded: false,
buyChecked: false,
sellChecked: false,
type: null,
currency: 0,
bookCurrencyCode: 'ANY',
orders: new Array(),
bookLoading: true,
bookRefreshing: false,
activeOrderId: null,
lastOrderId: null,
earnedRewards: 0,
referralCode: '',
lastDayPremium: 0,
limits: {},
loadingLimits: true,
maker: {},
};
}
componentDidMount = () => {
if (typeof window !== undefined) {
this.setState({
windowWidth: window.innerWidth / this.props.theme.typography.fontSize,
windowHeight: window.innerHeight / this.props.theme.typography.fontSize,
});
window.addEventListener('resize', this.onResize);
}
this.fetchBook(true, false);
this.fetchLimits(true);
};
componentWillUnmount = () => {
if (typeof window !== undefined) {
window.removeEventListener('resize', this.onResize);
}
};
onResize = () => {
this.setState({
windowWidth: window.innerWidth / this.props.theme.typography.fontSize,
windowHeight: window.innerHeight / this.props.theme.typography.fontSize,
});
};
setAppState = (newState) => {
this.setState(newState);
};
redirectTo(location) {
this.props.history.push(location);
}
getBasename() {
if (window.NativeRobosats) {
// Only for Android
return window.location.pathname;
}
return '';
}
fetchBook = (loading, refreshing) => {
this.setState({ bookLoading: loading, bookRefreshing: refreshing });
apiClient.get('/api/book/').then((data) =>
this.setState({
bookLoading: false,
bookRefreshing: false,
orders: data.not_found ? [] : data,
}),
);
};
fetchLimits = (loading) => {
this.setState({ loadingLimits: loading });
const limits = apiClient.get('/api/limits/').then((data) => {
this.setState({ limits: data, loadingLimits: false });
return data;
});
return limits;
};
render() {
const fontSize = this.props.theme.typography.fontSize;
const fontSizeFactor = fontSize / 14; // default fontSize is 14
const Router = window.NativeRobosats ? HashRouter : BrowserRouter;
return (
<Router basename={this.getBasename()}>
<div className='appCenter'>
<Switch>
<Route
exact
path='/'
render={(props) => (
<UserGenPage
{...props}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/ref/:refCode'
render={(props) => (
<UserGenPage
{...props}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/make'
render={(props) => (
<MakerPage
{...props}
{...this.state}
{...this.props}
fetchLimits={this.fetchLimits}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/book'
render={(props) => (
<BookPage
{...props}
{...this.state}
{...this.props}
fetchBook={this.fetchBook}
fetchLimits={this.fetchLimits}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/order/:orderId'
render={(props) => (
<OrderPage
{...props}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
)}
/>
</Switch>
</div>
<div
className='bottomBar'
style={{
height: `${40 * fontSizeFactor}px`,
width: `${(this.state.windowWidth / 16) * 14}em`,
}}
>
<BottomBar
redirectTo={this.redirectTo}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
</div>
</Router>
);
}
}

View File

@ -0,0 +1,168 @@
import React, { useEffect, useState } from 'react';
import { HashRouter, BrowserRouter, Switch, Route, useHistory } from 'react-router-dom';
import { useTheme } from '@mui/material';
import UserGenPage from './UserGenPage';
import MakerPage from './MakerPage';
import BookPage from './BookPage';
import OrderPage from './OrderPage';
import BottomBar from './BottomBar';
import { apiClient } from '../services/api';
import { Book, LimitList } from '../models';
interface Limits {
list: LimitList;
loading: boolean;
}
const Main = (): JSX.Element => {
const theme = useTheme();
const history = useHistory();
const Router = window.NativeRobosats ? HashRouter : BrowserRouter;
const basename = window.NativeRobosats ? window.location.pathname : '';
const [windowSize, setWindowSize] = useState<number[]>(); // EM values
// All app data structured
const [book, setBook] = useState<Book>({ orders: [], loading: true });
const [limits, setLimits] = useState<Limits>({ list: [], loading: true });
const [robot, setRobot] = useState();
const [maker, setMaker] = useState();
const [info, setInfo] = useState();
const [favorites, setFavorites] = useState();
const [settings, setSettings] = useState();
// constructor(props) {
// super(props);
// this.state = {
// type: null,
// currency: 0,
// lastDayPremium: 0,
// };
// }
useEffect(() => {
if (typeof window !== undefined) {
onResize();
window.addEventListener('resize', onResize);
}
fetchBook();
fetchLimits();
return () => {
if (typeof window !== undefined) {
window.removeEventListener('resize', onResize);
}
};
}, []);
const onResize = function () {
setWindowSize([
window.innerWidth / theme.typography.fontSize,
window.innerHeight / theme.typography.fontSize,
]);
};
const fetchBook = function () {
setBook({ ...book, loading: true });
apiClient.get('/api/book/').then((data) =>
setBook({
loading: false,
orders: data.not_found ? [] : data,
}),
);
};
const fetchLimits = () => {
setLimits({ ...limits, loading: true });
const data = apiClient.get('/api/limits/').then((data) => {
setLimits({ limits: data, loading: false });
return data;
});
return data;
};
return (
<Router basename={basename}>
<div className='appCenter'>
<Switch>
<Route
exact
path='/'
render={(props) => (
<UserGenPage
{...props}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/ref/:refCode'
render={(props) => (
<UserGenPage
{...props}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/make'
render={() => (
<MakerPage
orders={book.orders}
fetchLimits={fetchLimits}
maker={maker}
setMaker={setMaker}
/>
)}
/>
<Route
path='/book'
render={(props) => (
<BookPage
{...props}
{...this.state}
{...this.props}
book={book}
fetchBook={this.fetchBook}
fetchLimits={this.fetchLimits}
setAppState={this.setAppState}
/>
)}
/>
<Route
path='/order/:orderId'
render={(props) => (
<OrderPage
{...props}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
)}
/>
</Switch>
</div>
<div
className='bottomBar'
style={{
height: '2.857em',
width: `${(windowSize[0] / 16) * 14}em`,
}}
>
<BottomBar
redirectTo={(location) => history.push(location)}
{...this.state}
{...this.props}
setAppState={this.setAppState}
/>
</div>
</Router>
);
};
export default Main;

View File

@ -43,9 +43,8 @@ import { SelfImprovement, Lock, HourglassTop, DeleteSweep, Edit } from '@mui/ico
import { LoadingButton } from '@mui/lab';
interface MakerFormProps {
limits: LimitList;
fetchLimits: (loading) => void;
loadingLimits: boolean;
limits: { list: LimitList; loading: boolean };
fetchLimits: () => LimitList;
pricingMethods: boolean;
maker: Maker;
type: number;
@ -62,7 +61,6 @@ interface MakerFormProps {
const MakerForm = ({
limits,
fetchLimits,
loadingLimits,
pricingMethods,
currency,
type,
@ -94,19 +92,18 @@ const MakerForm = ({
useEffect(() => {
setCurrencyCode(currencyDict[currency == 0 ? 1 : currency]);
if (Object.keys(limits).length === 0) {
setAppState({ loadingLimits: true });
fetchLimits(true).then((data) => {
if (Object.keys(limits.list).length === 0) {
fetchLimits().then((data) => {
updateAmountLimits(data, currency, maker.premium);
updateCurrentPrice(data, currency, maker.premium);
updateSatoshisLimits(data);
});
} else {
updateAmountLimits(limits, currency, maker.premium);
updateCurrentPrice(limits, currency, maker.premium);
updateSatoshisLimits(limits);
updateAmountLimits(limits.list, currency, maker.premium);
updateCurrentPrice(limits.list, currency, maker.premium);
updateSatoshisLimits(limits.list);
fetchLimits(false);
fetchLimits();
}
}, []);
@ -130,10 +127,10 @@ const MakerForm = ({
const updateCurrentPrice = function (limits: LimitList, currency: number, premium: number) {
const index = currency === 0 ? 1 : currency;
let price = '...';
if (maker.is_explicit && maker.amount > 0 && maker.satoshis > 0) {
if (maker.isExplicit && maker.amount > 0 && maker.satoshis > 0) {
price = maker.amount / (maker.satoshis / 100000000);
} else if (!maker.is_explicit) {
price = limits[index].price * (1 + premium / 100);
price = limits.list[index].price * (1 + premium / 100);
}
setCurrentPrice(parseFloat(Number(price).toPrecision(5)));
};
@ -145,13 +142,13 @@ const MakerForm = ({
currency: newCurrency,
bookCurrencyCode: currencyCode,
});
updateAmountLimits(limits, newCurrency, maker.premium);
updateCurrentPrice(limits, newCurrency, maker.premium);
updateAmountLimits(limits.list, newCurrency, maker.premium);
updateCurrentPrice(limits.list, newCurrency, maker.premium);
if (advancedOptions) {
setMaker({
...maker,
minAmount: parseFloat(Number(limits[newCurrency].max_amount * 0.25).toPrecision(2)),
maxAmount: parseFloat(Number(limits[newCurrency].max_amount * 0.75).toPrecision(2)),
minAmount: parseFloat(Number(limits.list[newCurrency].max_amount * 0.25).toPrecision(2)),
maxAmount: parseFloat(Number(limits.list[newCurrency].max_amount * 0.75).toPrecision(2)),
});
}
};
@ -198,8 +195,8 @@ const MakerForm = ({
badPremiumText = t('Must be more than {{min}}%', { min });
premium = -99.99;
}
updateCurrentPrice(limits, currency, premium);
updateAmountLimits(limits, currency, premium);
updateCurrentPrice(limits.list, currency, premium);
updateAmountLimits(limits.list, currency, premium);
setMaker({
...maker,
premium,
@ -331,10 +328,10 @@ const MakerForm = ({
const index = currency === 0 ? 1 : currency;
const minAmount = maker.amount
? parseFloat((maker.amount / 2).toPrecision(2))
: parseFloat(Number(limits[index].max_amount * 0.25).toPrecision(2));
: parseFloat(Number(limits.list[index].max_amount * 0.25).toPrecision(2));
const maxAmount = maker.amount
? parseFloat(maker.amount)
: parseFloat(Number(limits[index].max_amount * 0.75).toPrecision(2));
: parseFloat(Number(limits.list[index].max_amount * 0.75).toPrecision(2));
setMaker({
...maker,
@ -437,12 +434,12 @@ const MakerForm = ({
return (
<Box>
<ConfirmationDialogs />
<Collapse in={loadingLimits}>
<div style={{ display: loadingLimits ? '' : 'none' }}>
<Collapse in={limits.loading}>
<div style={{ display: limits.loading ? '' : 'none' }}>
<LinearProgress />
</div>
</Collapse>
<Collapse in={!(loadingLimits || collapseAll)}>
<Collapse in={!(limits.loading || collapseAll)}>
<Grid container justifyContent='space-between' spacing={0} sx={{ maxHeight: '1em' }}>
<Grid item>
<IconButton
@ -478,7 +475,7 @@ const MakerForm = ({
>
<Switch
size='small'
disabled={loadingLimits}
disabled={limits.loading}
checked={advancedOptions}
onChange={handleClickAdvanced}
/>
@ -944,7 +941,7 @@ const MakerForm = ({
</Typography>
</Grid>
<Collapse in={!loadingLimits}>
<Collapse in={!limits.loading}>
<Tooltip
placement='top'
enterTouchDelay={0}

View File

@ -10,10 +10,9 @@ import { useHistory } from 'react-router-dom';
import filterOrders from '../../utils/filterOrders';
interface MakerPageProps {
limits: LimitList;
limits: { list: LimitList; loading: boolean };
fetchLimits: () => void;
orders: Order[];
loadingLimits: boolean;
type: number;
windowHeight: number;
windowWidth: number;
@ -25,7 +24,6 @@ const MakerPage = ({
limits,
fetchLimits,
orders,
loadingLimits,
currency,
type,
setAppState,
@ -82,7 +80,6 @@ const MakerPage = ({
<MakerForm
limits={limits}
fetchLimits={fetchLimits}
loadingLimits={loadingLimits}
pricingMethods={false}
setAppState={setAppState}
maker={maker}

View File

@ -23,4 +23,9 @@ export interface Order {
maker_status: 'Active' | 'Seen recently' | 'Inactive';
}
export interface Book {
orders: Order[];
loading: boolean;
}
export default Order;

View File

@ -0,0 +1,29 @@
export interface Robot {
nickname: string | null;
token: string | null;
bitsEntropy: number | null;
shannonEntropy: number | null;
stealthInvoices: boolean;
activeOrderId: number | null;
lastOrderId: number | null;
earnedRewards: number;
referralCode: string;
loading: boolean;
copiedToken: boolean;
}
export const defaultRobot: Robot = {
nickname: null,
token: null,
bitsEntropy: null,
shannonEntropy: null,
stealthInvoices: true,
activeOrderId: null,
lastOrderId: null,
earnedRewards: 0,
referralCode: '',
loading: true,
copiedToken: false,
};
export default Robot;

View File

@ -3,3 +3,6 @@ export type { Limit } from './Limit.model';
export type { Maker } from './Maker.model';
export { defaultMaker } from './Maker.model';
export type { Order } from './Order.model';
export type { Book } from './Order.model';
export type { Robot } from './Robot.model';
export { defaultRobot } from './Robot.model';