Browse Source

20230307: integrated Joy Orderbook UI

mkbeefcake 1 year ago
parent
commit
de1c5f75ea

+ 1 - 0
src/components/AppBar/config.ts

@@ -18,6 +18,7 @@ export const routes = {
   issues: "Issues",
   calendar: "Calendar",
   timeline: "Timeline",
+  swap: "JOY OrderBook",
 } as { [key: string]: string };
 
 export const useStyles = makeStyles((theme: Theme) =>

+ 104 - 0
src/components/JoySwapTool/ConnectWallet.tsx

@@ -0,0 +1,104 @@
+import React, { useEffect, useState } from "react";
+import { IState  } from "../../types";
+import SubBlock from "../ui/SubBlock";
+import { Button, Container } from "@material-ui/core";
+import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
+
+import Accordion from '@material-ui/core/Accordion';
+import AccordionSummary from '@material-ui/core/AccordionSummary';
+import AccordionDetails from '@material-ui/core/AccordionDetails';
+import Typography from '@material-ui/core/Typography';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import Line from "../ui/Line";
+import SellOrderDialog from './components/SellOrderDialog';
+
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      width: '100%',
+    },
+    heading: {
+      fontSize: theme.typography.pxToRem(15),
+    },
+    section: {
+      margin:'10px !important', 
+      background:'bottom', 
+      border: '1px solid black', 
+      borderRadius: '10px' 
+    }
+  }),
+);
+
+
+export const ConnectWallet = (props: IState) => {  
+
+  const classes = useStyles();
+  const [isShowSell, setIsShowSell] = useState(false);
+
+  const onHandleSell = () => {
+    setIsShowSell(true)
+  }
+
+  const onHandleClose = () => {
+    setIsShowSell(false)
+  }
+
+  return (
+    <SubBlock title="My Wallet">
+      <div className={classes.root}>
+        <div style={{display: 'flex', justifyContent: 'space-evenly', margin: '10px' }} >
+          <Button variant="outlined">Connect Wallet</Button>
+          <Button variant="outlined" onClick={onHandleSell} >Sell</Button>
+        </div>
+        <Accordion className={classes.section}>
+          <AccordionSummary
+            expandIcon={<ExpandMoreIcon />}
+            aria-controls="panel1a-content"
+            id="panel1a-header"
+          >
+            <Typography className={classes.heading}>Polkadot DOT Wallet</Typography>
+          </AccordionSummary>
+          <AccordionDetails>
+            <div style={{width:'100%'}}>
+              <Line content={"Address"} value={"XXXXXXXXXXXXXXXXXXXXX"} />
+              <Line content={"Balance"} value={"YYYYYYYYYYYYYYYYYYYYY"} />
+            </div>
+          </AccordionDetails>
+        </Accordion>
+        <Accordion className={classes.section}>
+          <AccordionSummary
+            expandIcon={<ExpandMoreIcon />}
+            aria-controls="panel2a-content"
+            id="panel2a-header"
+          >
+            <Typography className={classes.heading}>Joystream Wallet</Typography>
+          </AccordionSummary>
+          <AccordionDetails>
+            <div style={{width:'100%'}}>
+              <Line content={"Address"} value={"XXXXXXXXXXXXXXXXXXXXX"} />
+              <Line content={"Balance"} value={"YYYYYYYYYYYYYYYYYYYYY"} />
+            </div>
+          </AccordionDetails>
+        </Accordion>
+        <Accordion className={classes.section}>
+          <AccordionSummary
+            expandIcon={<ExpandMoreIcon />}
+            aria-controls="panel2a-content"
+            id="panel2a-header"
+          >
+            <Typography className={classes.heading}>Transactions</Typography>
+          </AccordionSummary>
+          <AccordionDetails>
+            <div style={{width:'100%'}}>
+              <Line content={"Buy"} value={"6 DOT => 1000 JOY "} />
+              <Line content={"Sell"} value={"200 JOY => 1.5 DOT"} />
+            </div>
+          </AccordionDetails>
+        </Accordion>
+      </div>
+      <div>
+        <SellOrderDialog open={isShowSell} handleClose={onHandleClose} />
+      </div>
+    </SubBlock>
+  );
+}

+ 136 - 0
src/components/JoySwapTool/SellerList.tsx

@@ -0,0 +1,136 @@
+import React, { useEffect, useState } from "react";
+import { IState  } from "../../types";
+import SubBlock from "../ui/SubBlock";
+
+import Table from "@material-ui/core/Table";
+import TableBody from "@material-ui/core/TableBody";
+import TableCell from "@material-ui/core/TableCell";
+import TableContainer from "@material-ui/core/TableContainer";
+import TableHead from "@material-ui/core/TableHead";
+import TableRow from "@material-ui/core/TableRow";
+import TableFooter from '@material-ui/core/TableFooter';
+import TablePagination from '@material-ui/core/TablePagination';
+import TablePaginationActions from '../ui/TablePaginationActions';
+import { Button, makeStyles, Typography } from "@material-ui/core";
+import BuyOrderDialog from './components/BuyOrderDialog';
+
+export interface ISeller {
+    seller: string,
+    price: number,
+    amount: number,
+    address?: string
+}
+
+function Seller (props: { seller: ISeller, onHandleBuy: any }) {
+    const { seller, onHandleBuy } = props
+
+	return (
+		<TableRow key={seller.seller}>
+			<TableCell>{seller.seller}</TableCell>
+			<TableCell><i>{Number.isNaN(seller.price) ? "-" : seller.price}</i></TableCell>
+			<TableCell><i>{seller.amount}</i></TableCell>
+			<TableCell>
+                <Button variant="outlined" onClick={() => onHandleBuy(seller)}>Buy</Button>
+            </TableCell>
+		</TableRow>
+	);
+}
+
+const useStyles = makeStyles({
+	table: {
+	},
+    desc: { flexGrow: 1, backgroundColor: "#4038FF", boxShadow: "none", paddingLeft:"16px" },
+})
+
+const sellerGroups: ISeller[] = [
+    {seller: "mkblockchaindev", price: 0.06, amount: 100000},
+    {seller: "xxxxxxxx", price: 0.05623, amount: 40000},
+    {seller: "yyyyyyy", price: 0.05975, amount: 40000},
+    {seller: "aaaaaa", price: 0.05975, amount: 40000},
+    {seller: "bbbbb", price: 0.05975, amount: 40000},
+    {seller: "zzzzz", price: 0.05623, amount: 40000},
+]
+
+const SellerList = (props: IState) => {
+	const {} = props	
+
+	const classes = useStyles()
+	const [page, setPage] = React.useState(0);
+	const [rowsPerPage, setRowsPerPage] = React.useState(4);
+	const [isShowBuy, setIsShowBuy] = useState(false);
+	const [selectedSeller, setSelectedSeller] = useState<ISeller | undefined>();
+
+	const onHandleBuy = (seller: ISeller) => {        
+		console.log(`onhandleBuy: `, seller) 
+		setIsShowBuy(true)
+		setSelectedSeller(seller)
+	}
+
+	const onHandleClose = () => {
+		setIsShowBuy(false)
+	}
+
+	const handleChangePage = (event: unknown, newPage: number) => {
+			setPage(newPage);
+	};
+
+	const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
+			setRowsPerPage(parseInt(event.target.value, 10));
+			setPage(0);
+	};
+	
+	return (
+			<SubBlock title="$JOY Token Sellers" stretch={8} >
+					<>
+							<Typography variant="h6" className={classes.desc}>
+									The normal JOY price is $0.06 USD. This tool can help people to purchase/buy JOY tokens around that price before DEX listing.
+							</Typography>
+							<Button variant="outlined" style={{marginTop: 20}}>Auto Buy</Button>
+							<TableContainer style={{ padding: 10 }}>
+									<Table className={classes.table} aria-label="sell-order table">
+											<TableHead>
+													<TableRow>
+															<TableCell>Seller</TableCell>
+															<TableCell>Price</TableCell>
+															<TableCell>Amount</TableCell>
+															<TableCell>Action</TableCell>
+													</TableRow>
+											</TableHead>
+											{sellerGroups && ( 
+													<TableBody>
+															{ rowsPerPage > 0 ? 
+																			sellerGroups.slice(page * rowsPerPage, page *rowsPerPage + rowsPerPage)
+																					.map((seller) => <Seller key={seller.seller} seller={seller} onHandleBuy={onHandleBuy} />)
+																	: sellerGroups.map((seller) => <Seller key={seller.seller} seller={seller} onHandleBuy={onHandleBuy}/>)
+															}
+													</TableBody>
+											)}
+											<TableFooter>
+													<TableRow>
+															<TablePagination
+																	rowsPerPageOptions={[4]}
+																	colSpan={4}
+																	count={sellerGroups ? sellerGroups.length : 0}
+																	rowsPerPage={rowsPerPage}
+																	page={page}
+																	onPageChange={handleChangePage}
+																	SelectProps={{
+																			inputProps: { 'aria-label': 'rows per page' },
+																			native: true,
+																	}}
+																	onRowsPerPageChange={handleChangeRowsPerPage}
+																	ActionsComponent={TablePaginationActions}
+															/>
+													</TableRow>
+											</TableFooter>
+									</Table>
+							</TableContainer>
+					</>
+					<div>
+							<BuyOrderDialog open={isShowBuy} handleClose={onHandleClose} seller={selectedSeller} />
+					</div>
+			</SubBlock>
+	);
+}
+
+export default SellerList;

+ 113 - 0
src/components/JoySwapTool/components/BuyOrderDialog.tsx

@@ -0,0 +1,113 @@
+import React from 'react';
+import { createStyles, Theme, withStyles, WithStyles } from '@material-ui/core/styles';
+import Button from '@material-ui/core/Button';
+import Dialog from '@material-ui/core/Dialog';
+import MuiDialogTitle from '@material-ui/core/DialogTitle';
+import MuiDialogContent from '@material-ui/core/DialogContent';
+import MuiDialogActions from '@material-ui/core/DialogActions';
+import IconButton from '@material-ui/core/IconButton';
+import CloseIcon from '@material-ui/icons/Close';
+import Typography from '@material-ui/core/Typography';
+import TextField from '@material-ui/core/TextField';
+
+import { ISeller } from '../SellerList'
+
+const styles = (theme: Theme) =>
+  createStyles({
+    root: {
+      margin: 0,
+      padding: theme.spacing(2),
+      background: "dodgerblue",
+    },
+    closeButton: {
+      position: 'absolute',
+      right: theme.spacing(1),
+      top: theme.spacing(1),
+      color: theme.palette.grey[500],
+    },
+  });
+
+export interface DialogTitleProps extends WithStyles<typeof styles> {
+  id: string;
+  children: React.ReactNode;
+  onClose: () => void;
+}
+
+const DialogTitle = withStyles(styles)((props: DialogTitleProps) => {
+  const { children, classes, onClose, ...other } = props;
+  return (
+    <MuiDialogTitle disableTypography className={classes.root} {...other}>
+      <Typography variant="h6">{children}</Typography>
+      {onClose ? (
+        <IconButton aria-label="close" className={classes.closeButton} onClick={onClose}>
+          <CloseIcon />
+        </IconButton>
+      ) : null}
+    </MuiDialogTitle>
+  );
+});
+
+const DialogContent = withStyles((theme: Theme) => ({
+  root: {
+    padding: theme.spacing(2),
+  },
+}))(MuiDialogContent);
+
+const DialogActions = withStyles((theme: Theme) => ({
+  root: {
+    margin: 0,
+    padding: theme.spacing(1),
+  },
+}))(MuiDialogActions);
+
+const BuyOrderDialog = (props: {open: boolean, handleClose: any, seller: ISeller}) => {
+  const { open, handleClose, seller} = props
+
+  console.log(`seller: `, seller) 
+
+  return (
+      <Dialog onClose={handleClose} aria-labelledby="customized-dialog-title" open={open}>
+        <DialogTitle id="customized-dialog-title" onClose={handleClose}>
+          Buy
+        </DialogTitle>
+        <DialogContent dividers style={{background:"dodgerblue"}}>
+          <div style={{display:'flex', flexDirection:'column', gap:16}} >
+            <TextField
+              required
+              id="outlined-required"
+              label="Seller"
+              defaultValue={seller && seller.seller}
+              inputProps={{
+                readOnly: true,
+              }}
+              variant="outlined"
+            />
+            <TextField
+              required
+              id="outlined-required"
+              label="JOY PRICE"
+              defaultValue="0.06"
+              inputProps={{
+                readOnly: true,
+              }}
+              variant="outlined"
+            />
+            <TextField
+              required
+              id="outlined-required"
+              label="JOY AMOUNT"
+              defaultValue="1000"
+              variant="outlined"
+            />
+          </div>
+        </DialogContent>
+        <DialogActions style={{background:"dodgerblue"}}>
+          <Button autoFocus onClick={handleClose} color="primary">
+            Order
+          </Button>
+        </DialogActions>
+      </Dialog>
+  );
+}
+
+export default BuyOrderDialog;

+ 94 - 0
src/components/JoySwapTool/components/SellOrderDialog.tsx

@@ -0,0 +1,94 @@
+import React from 'react';
+import { createStyles, Theme, withStyles, WithStyles } from '@material-ui/core/styles';
+import Button from '@material-ui/core/Button';
+import Dialog from '@material-ui/core/Dialog';
+import MuiDialogTitle from '@material-ui/core/DialogTitle';
+import MuiDialogContent from '@material-ui/core/DialogContent';
+import MuiDialogActions from '@material-ui/core/DialogActions';
+import IconButton from '@material-ui/core/IconButton';
+import CloseIcon from '@material-ui/icons/Close';
+import Typography from '@material-ui/core/Typography';
+import TextField from '@material-ui/core/TextField';
+
+const styles = (theme: Theme) =>
+  createStyles({
+    root: {
+      margin: 0,
+      padding: theme.spacing(2),
+      background: "dodgerblue",
+    },
+    closeButton: {
+      position: 'absolute',
+      right: theme.spacing(1),
+      top: theme.spacing(1),
+      color: theme.palette.grey[500],
+    },
+  });
+
+export interface DialogTitleProps extends WithStyles<typeof styles> {
+  id: string;
+  children: React.ReactNode;
+  onClose: () => void;
+}
+
+const DialogTitle = withStyles(styles)((props: DialogTitleProps) => {
+  const { children, classes, onClose, ...other } = props;
+  return (
+    <MuiDialogTitle disableTypography className={classes.root} {...other}>
+      <Typography variant="h6">{children}</Typography>
+      {onClose ? (
+        <IconButton aria-label="close" className={classes.closeButton} onClick={onClose}>
+          <CloseIcon />
+        </IconButton>
+      ) : null}
+    </MuiDialogTitle>
+  );
+});
+
+const DialogContent = withStyles((theme: Theme) => ({
+  root: {
+    padding: theme.spacing(2),
+  },
+}))(MuiDialogContent);
+
+const DialogActions = withStyles((theme: Theme) => ({
+  root: {
+    margin: 0,
+    padding: theme.spacing(1),
+  },
+}))(MuiDialogActions);
+
+const SellOrderDialog = ({open, handleClose}) => {
+  return (
+      <Dialog onClose={handleClose} aria-labelledby="customized-dialog-title" open={open}>
+        <DialogTitle id="customized-dialog-title" onClose={handleClose}>
+          Sell
+        </DialogTitle>
+        <DialogContent dividers style={{background:"dodgerblue"}}>
+          <div style={{display:'flex', flexDirection:'column', gap:16}} >
+            <TextField
+              required
+              id="outlined-required"
+              label="JOY PRICE"
+              defaultValue="0.06"
+              variant="outlined"
+            />
+            <TextField
+              required
+              id="outlined-required"
+              label="JOY AMOUNT"
+              defaultValue="1000"
+              variant="outlined"
+            />
+          </div>
+        </DialogContent>
+        <DialogActions style={{background:"dodgerblue"}}>
+          <Button autoFocus onClick={handleClose} color="primary">
+            Order
+          </Button>
+        </DialogActions>
+      </Dialog>
+  );
+}
+
+export default SellOrderDialog;

+ 26 - 0
src/components/JoySwapTool/index.tsx

@@ -0,0 +1,26 @@
+import React, { useEffect, useState } from "react";
+import { IState  } from "../../types";
+import { Container, Grid, TableContainer } from "@material-ui/core";
+import { ConnectWallet } from './ConnectWallet'
+import SellerList from './SellerList'
+import Banner from "../ui/Banner";
+import SubBlock from "../ui/SubBlock";
+
+const JoySwapTool = (props: IState) => {
+	const {} = props	
+
+	console.log(`joyswaptool screen`)
+
+  return (
+    <div style={{ flexGrow: 1 }}>
+      <Container maxWidth="xl">
+        <Grid container spacing={3}>
+          <ConnectWallet {...props} />
+					<SellerList {...props} />
+        </Grid>
+      </Container>
+    </div>
+  );
+}
+
+export default JoySwapTool;

+ 4 - 0
src/components/NavBar/index.tsx

@@ -14,6 +14,7 @@ import {
   Twitch,
   Mail,
   Target,
+  Zap
 } from "react-feather";
 import { Link } from "react-router-dom";
 import joystream from "../../joystream.svg";
@@ -32,6 +33,9 @@ const NavBar = (props) => {
       <Navbar.Toggle aria-controls="basic-navbar-nav" />
       <Navbar.Collapse id="basic-navbar-nav">
         <Nav className="p-2 d-flex flex-wrap">
+          <Link to={"/swap"} className="mr-1" title="Joy Orderbook">
+            <Zap />
+          </Link>
           <Link to={"/media"} className="mr-1" title="Videos">
             <Film />
           </Link>

+ 2 - 1
src/components/Routes/index.tsx

@@ -34,6 +34,7 @@ const Openings = React.lazy(() => import("../Openings"));
 const Notes = React.lazy(() => import("../Notes"));
 const Media = React.lazy(() => import("../Media"));
 const Settings = React.lazy(() => import("../Settings"));
+const JoySwapTool = React.lazy(() => import("../JoySwapTool"));
 
 interface IProps extends IState {
   toggleStar: (a: string) => void;
@@ -197,7 +198,7 @@ const Routes = (props: IProps) => {
         />
         <Route path="/issues" render={(routeprops) => <IssueTracker />} />
         <Route path="/survey" render={(routeprops) => <Survey />} />
-
+        <Route path="/swap" render={(routeprops) => <JoySwapTool {...routeprops} {...props} />} />
         <Route path="/" render={() => <Dashboard {...props} />} />
       </Switch>
     </Suspense>

+ 1 - 0
src/components/index.ts

@@ -45,6 +45,7 @@ export { default as Openings } from "./Openings";
 export { default as Notes } from "./Notes";
 export { default as Settings } from "./Settings";
 export { default as Log } from "./Log";
+export { default as JoySwapTool } from "./JoySwapTool";
 
 export { default as Spinner } from "./Spinner";
 export { default as Modals } from "./Modals";