More styling changes

This commit is contained in:
Justin Ferrari 2024-12-25 15:08:04 -05:00
parent 2fe23b439b
commit 3de91a32d3
7 changed files with 484 additions and 110 deletions

View File

@ -1,5 +1,6 @@
import { Box, Button } from "@mui/material";
import { styled } from "@mui/system";
import CloseIcon from '@mui/icons-material/Close';
export const ReusableModalContainer = styled(Box)(({ theme }) => ({
display: "flex",
@ -21,15 +22,6 @@ export const ReusableModalContainer = styled(Box)(({ theme }) => ({
"0px 4px 5px 0px hsla(0,0%,0%,0.14), \n\t\t0px 1px 10px 0px hsla(0,0%,0%,0.12), \n\t\t0px 2px 4px -1px hsla(0,0%,0%,0.2)",
}));
export const ReusableModalSubContainer = styled(Box)({
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: "20px",
padding: "70px",
});
export const ReusableModalBackdrop = styled(Box)({
position: "fixed",
top: "0",
@ -51,3 +43,16 @@ export const ReusableModalButton = styled(Button)(({ theme }) => ({
color: theme.palette.text.primary,
boxShadow: "1px 4px 10.5px 0px #0000004D"
}));
export const ReusableModalCloseIcon = styled(CloseIcon)(({ theme }) => ({
color: theme.palette.text.primary,
cursor: "pointer",
fontSize: "30px",
position: "absolute",
top: "20px",
right: "20px",
transition: "all 0.3s ease-in-out",
"&:hover": {
transform: "scale(1.1)",
},
}));

View File

@ -1,20 +1,26 @@
import {
ReusableModalBackdrop,
ReusableModalCloseIcon,
ReusableModalContainer,
ReusableModalSubContainer,
} from "./ReusableModal-styles";
interface ReusableModalProps {
backdrop?: boolean;
onClickClose: () => void;
children: React.ReactNode;
}
export const ReusableModal: React.FC<ReusableModalProps> = ({ backdrop, children }) => {
export const ReusableModal: React.FC<ReusableModalProps> = ({
backdrop,
children,
onClickClose,
}) => {
return (
<>
<ReusableModalContainer>
<ReusableModalSubContainer>{children}</ReusableModalSubContainer>
<ReusableModalCloseIcon onClick={onClickClose} />
{children}
</ReusableModalContainer>
{backdrop && <ReusableModalBackdrop />}
{backdrop && <ReusableModalBackdrop onClick={onClickClose} />}
</>
);
};

View File

@ -1,5 +1,5 @@
import { styled } from "@mui/system";
import { Box, Button, Typography } from "@mui/material";
import { Box, Button, Typography, Theme, TextField } from "@mui/material";
import { HomeSVG } from "../common/icons/HomeSVG";
import { QortalLogoSVG } from "../common/icons/QortalLogoSVG";
import { CaretDownSVG } from "../common/icons/CaretDownSVG";
@ -217,3 +217,123 @@ export const CoinSelectRow = styled(Box)({
gap: "5px",
alignSelf: "flex-start",
});
export const CoinActionContainer = styled(Box)({
display: "flex",
flexDirection: "column",
gap: "25px",
alignItems: "center",
justifyContent: "center",
width: "80%",
});
export const CoinActionRow = styled(Box)({
display: "flex",
flexDirection: "row",
width: "100%",
alignItems: "center",
justifyContent: "center",
});
export const HeaderRow = styled(Box)({
display: "flex",
flexDirection: "row",
gap: "10px",
alignItems: "center",
justifyContent: "center",
});
export const SendFont = styled(Typography)(({ theme }) => ({
fontFamily: "Inter",
color: theme.palette.text.primary,
fontWeight: 400,
fontSize: "18px",
lineHeight: "25px",
userSelect: "none",
}));
const customInputStyle = (theme: Theme) => {
return {
fontFamily: "Inter",
fontSize: "18px",
fontWeight: 300,
color: theme.palette.text.primary,
backgroundColor: theme.palette.background.default,
borderColor: theme.palette.background.paper,
"& label": {
color: theme.palette.mode === "light" ? "#808183" : "#edeef0",
fontFamily: "Inter",
fontSize: "18px",
letterSpacing: "0px",
},
"& label.Mui-focused": {
color: theme.palette.mode === "light" ? "#A0AAB4" : "#d7d8da",
},
"& .MuiInput-underline:after": {
borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
},
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#E0E3E7",
},
"&:hover fieldset": {
borderColor: "#B2BAC2",
},
"&.Mui-focused fieldset": {
borderColor: "#6F7E8C",
},
},
"& .MuiInputBase-root": {
fontFamily: "Inter",
fontSize: "18px",
letterSpacing: "0px",
},
"& .MuiFilledInput-root:after": {
borderBottomColor: theme.palette.secondary.main,
},
};
};
export const CustomInputField = styled(TextField)(({ theme }) =>
customInputStyle(theme as Theme)
);
export const CoinCancelBtn = styled(Button)({
backgroundColor: "transparent",
color: "#d62525",
border: "1px solid #d62525",
fontFamily: "Inter, sans-serif",
fontWeight: 500,
fontSize: "14px",
height: "32px",
width: "80px",
lineHeight: "16px",
padding: "5px 10px",
borderRadius: "0px",
transition: "all 0.3s ease-in-out",
"&:hover": {
border: "1px solid #d62525",
backgroundColor: "#d62525",
color: "#000000"
},
});
export const CoinConfirmSendBtn = styled(Button)(({ theme }) => ({
backgroundColor: theme.palette.primary.main,
color: "#000000",
border: `1px solid ${theme.palette.primary.main}`,
fontFamily: "Inter, sans-serif",
fontWeight: 500,
fontSize: "14px",
height: "32px",
width: "80px",
lineHeight: "16px",
padding: "5px 10px",
borderRadius: "0px",
transition: "all 0.3s ease-in-out",
"&:hover": {
border: `1px solid ${theme.palette.text.primary}`,
color: "#000000",
backgroundColor: theme.palette.text.primary,
},
}));

View File

@ -1,15 +1,22 @@
import { useState, useEffect, useRef, useContext, ChangeEvent } from "react";
import {
BubbleCardColored1,
CoinActionContainer,
CoinActionRow,
CoinActionsRow,
CoinCancelBtn,
CoinConfirmSendBtn,
CoinReceiveBtn,
CoinSelectRow,
CoinSendBtn,
CustomInputField,
HeaderNav,
HeaderRow,
HeaderText,
LogoColumn,
NameRow,
RightColumn,
SendFont,
TotalCol,
Username,
} from "./Header-styles";
@ -25,6 +32,7 @@ import {
Box,
Card,
CardContent,
FormControl,
FormControlLabel,
MenuItem,
Select,
@ -42,6 +50,8 @@ import rvnIcon from "../../assets/img/rvn.png";
import dgbIcon from "../../assets/img/dgb.png";
import arrrIcon from "../../assets/img/arrr.png";
import { Spacer } from "../common/Spacer";
import { ReusableModal } from "../common/reusable-modal/ReusableModal";
import { NotificationContext } from "../../contexts/notificationContext";
const checkIfLocal = async () => {
try {
@ -65,6 +75,11 @@ export const Label = styled("label")(
`
);
interface CoinModalProps {
coin: string;
type: string;
}
const getCoinIcon = (coin) => {
let img;
@ -126,6 +141,11 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
const [checked, setChecked] = useState(false);
const [open, setOpen] = useState(false);
const [info, setInfo] = useState<any>(null);
const [openCoinActionModal, setOpenCoinActionModal] =
useState<CoinModalProps | null>(null);
const [receiverAddress, setReceiverAddress] = useState<string>("");
const [senderAddress, setSenderAddress] = useState<string>("");
const { isUsingGateway } = useContext(gameContext);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
@ -138,7 +158,7 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
};
const { userInfo, selectedCoin, setSelectedCoin, getCoinLabel } =
useContext(gameContext);
const { avatar, setAvatar } = useContext(UserContext);
const { setNotification } = useContext(NotificationContext);
const LocalNodeSwitch = styled(Switch)(({ theme }) => ({
padding: 8,
@ -327,8 +347,26 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
<HeaderText>{qortBalance} QORT</HeaderText>
</Box>
<CoinActionsRow>
<CoinSendBtn>Send</CoinSendBtn>
<CoinReceiveBtn>Receive</CoinReceiveBtn>
<CoinSendBtn
onClick={() => {
setOpenCoinActionModal({
coin: "QORT",
type: "send",
});
}}
>
Send
</CoinSendBtn>
<CoinReceiveBtn
onClick={() => {
setOpenCoinActionModal({
coin: "QORT",
type: "receive",
});
}}
>
Receive
</CoinReceiveBtn>
</CoinActionsRow>
</TotalCol>
<Spacer height="10px" />
@ -351,8 +389,26 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
{getCoinLabel()}
</Box>
<CoinActionsRow>
<CoinSendBtn>Send</CoinSendBtn>
<CoinReceiveBtn>Receive</CoinReceiveBtn>
<CoinSendBtn
onClick={() => {
setOpenCoinActionModal({
coin: selectedCoin,
type: "send",
});
}}
>
Send
</CoinSendBtn>
<CoinReceiveBtn
onClick={() => {
setOpenCoinActionModal({
coin: selectedCoin,
type: "receive",
});
}}
>
Receive
</CoinReceiveBtn>
</CoinActionsRow>
</TotalCol>
</CardContent>
@ -400,6 +456,116 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
{info?.message}
</Alert>
</Snackbar>
{openCoinActionModal && (
<ReusableModal
onClickClose={() => {
setOpenCoinActionModal(null);
}}
backdrop
>
<CoinActionContainer>
<CoinActionRow>
<HeaderRow>
{openCoinActionModal.type === "send" &&
openCoinActionModal.coin === "QORT" ? (
<>
<SendFont>Send {openCoinActionModal.coin}</SendFont>
<img
src={qortIcon}
style={{
height: "25px",
width: "auto",
}}
/>
</>
) : openCoinActionModal.type === "send" &&
openCoinActionModal.coin !== "QORT" ? (
<>
<SendFont>Send {openCoinActionModal.coin}</SendFont>
<img
src={getCoinIcon(getCoinLabel())}
style={{
height: "25px",
width: "auto",
}}
/>
</>
) : openCoinActionModal.type === "receive" &&
openCoinActionModal.coin === "QORT" ? (
<>
<SendFont>Receive {openCoinActionModal.coin}</SendFont>
<img
src={qortIcon}
style={{
height: "25px",
width: "auto",
}}
/>
</>
) : openCoinActionModal.type === "receive" &&
openCoinActionModal.coin !== "QORT" ? (
<>
<SendFont>Receive {openCoinActionModal.coin}</SendFont>
<img
src={getCoinIcon(getCoinLabel())}
style={{
height: "25px",
width: "auto",
}}
/>
</>
) : null}
</HeaderRow>
</CoinActionRow>
<CoinActionRow>
<FormControl fullWidth>
<CustomInputField
style={{ flexGrow: 1 }}
name={
openCoinActionModal.type === "send"
? "Sender Address"
: "Receive Address"
}
label={
openCoinActionModal.type === "send"
? "Sender Address"
: "Receive Address"
}
variant="filled"
value={
openCoinActionModal.type === "send"
? senderAddress
: receiverAddress
}
required
onChange={(e) => {
if (openCoinActionModal.type === "send") {
setSenderAddress(e.target.value);
} else {
setReceiverAddress(e.target.value);
}
}}
/>
</FormControl>
</CoinActionRow>
<CoinActionRow style={{gap: "10px"}}>
<CoinCancelBtn onClick={() => setOpenCoinActionModal(null)}>
Cancel
</CoinCancelBtn>
<CoinConfirmSendBtn
onClick={() => {
setNotification({
alertType: "alertInfo",
msg: "Sending...",
});
}}
>
{openCoinActionModal.type === "send" ? "Send" : "Receive"}
</CoinConfirmSendBtn>
</CoinActionRow>
</CoinActionContainer>
</ReusableModal>
)}
</HeaderNav>
</>
);

View File

@ -0,0 +1,57 @@
import { Box, styled } from "@mui/system";
import { Button, Typography } from "@mui/material";
import RefreshIcon from "@mui/icons-material/Refresh";
type HistoryBtnProp = {
activeBtn: boolean;
};
export const HistoryButtonRow = styled(Box)({
display: "flex",
alignItems: "center",
gap: "5px",
margin: "5px 5px 5px 0",
});
export const HistoryButton = styled(Button, {
shouldForwardProp: (prop) => prop !== "activeBtn",
})<HistoryBtnProp>(({ theme, activeBtn }) => ({
fontFamily: "Inter",
color: activeBtn ? theme.palette.text.primary : theme.palette.primary.main,
fontWeight: 400,
fontSize: "16px",
height: "30px",
lineHeight: "40px",
userSelect: "none",
background: activeBtn ? theme.palette.primary.main : "transparent",
border: `1px solid ${theme.palette.primary.main}`,
transition: "all 0.3s ease-in-out",
"&:hover": {
border: `1px solid ${theme.palette.primary.main}`,
background: theme.palette.primary.main,
color: theme.palette.text.primary,
cursor: "pointer",
},
}));
export const Refresh = styled(RefreshIcon)({
cursor: "pointer",
color: "#fff",
fontSize: "25px",
marginLeft: "5px",
transition: "all 0.3s ease-in-out",
"&:hover": {
cursor: "pointer",
transform: "scale(1.1)",
},
});
export const ShowingFont = styled(Typography)(({ theme }) => ({
fontFamily: "Inter",
color: theme.palette.text.primary,
fontWeight: 400,
fontSize: "16px",
lineHeight: "25px",
marginBottom: "5px",
userSelect: "none",
}));

View File

@ -1,110 +1,131 @@
import { Alert, Box, Button, ButtonBase, DialogActions, DialogContent, DialogTitle, IconButton, InputLabel, Snackbar, SnackbarCloseReason, TextField, Typography, styled } from '@mui/material'
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { BootstrapDialog } from '../Terms'
import CloseIcon from '@mui/icons-material/Close';
import { Spacer } from '../common/Spacer';
import gameContext from '../../contexts/gameContext';
import HistoryList from './HistoryList';
import RefreshIcon from "@mui/icons-material/Refresh";
import {
Alert,
Box,
ButtonBase,
Snackbar
} from "@mui/material";
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import gameContext from "../../contexts/gameContext";
import HistoryList from "./HistoryList";
import { ShowingFont, Refresh, HistoryButtonRow, HistoryButton } from "./History-styles";
export const History = ({ qortAddress, show }) => {
const [buyHistory, setBuyHistory] = useState({});
const [sellHistory, setSellHistory] = useState({});
const { selectedCoin } = useContext(gameContext);
const [mode, setMode] = useState("buyHistory");
const [open, setOpen] = useState(false);
const selectedHistory = useMemo(() => {
if (mode === "buyHistory") return buyHistory[selectedCoin] || [];
if (mode === "sellHistory") return sellHistory[selectedCoin] || [];
}, [selectedCoin, buyHistory, sellHistory, mode]);
const getBuyHistory = useCallback(
(address, foreignBlockchain, mode, limit = 20) => {
setOpen(true);
let historyUrl;
if (mode === "buyHistory") {
historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&buyerAddress=${address}&limit=${limit}&reverse=true`;
}
if (mode === "sellHistory") {
historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&sellerAddress=${address}&limit=${limit}&reverse=true`;
}
export const History = ({qortAddress, show}) => {
const [buyHistory, setBuyHistory] = useState({})
const [sellHistory, setSellHistory] = useState({})
fetch(historyUrl)
.then((response) => {
return response.json();
})
.then((data) => {
if (mode === "buyHistory") {
setBuyHistory((prev) => {
return {
...prev,
[foreignBlockchain]: data,
};
});
}
if (mode === "sellHistory") {
setSellHistory((prev) => {
return {
...prev,
[foreignBlockchain]: data,
};
});
}
})
.catch(() => {})
.finally(() => {
setOpen(false);
});
},
[]
);
const { getCoinLabel, selectedCoin} = useContext(gameContext)
const [mode, setMode] = useState('buyHistory')
const [open, setOpen] = useState(false)
useEffect(() => {
if (!qortAddress || !selectedCoin) return;
if (mode === "buyHistory" && buyHistory[selectedCoin]) return;
if (mode === "sellHistory" && sellHistory[selectedCoin]) return;
const selectedHistory = useMemo(()=> {
if(mode === 'buyHistory') return buyHistory[selectedCoin] || []
if(mode === 'sellHistory') return sellHistory[selectedCoin] || []
}, [selectedCoin, buyHistory, sellHistory, mode])
const getBuyHistory = useCallback((address, foreignBlockchain, mode, limit = 20)=> {
setOpen(true)
let historyUrl
if(mode === 'buyHistory'){
historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&buyerAddress=${address}&limit=${limit}&reverse=true`;
}
if(mode === 'sellHistory'){
historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&sellerAddress=${address}&limit=${limit}&reverse=true`;
}
fetch(historyUrl)
.then((response) => {
return response.json();
})
.then((data) => {
if(mode === 'buyHistory'){
setBuyHistory((prev)=> {
return {
...prev,
[foreignBlockchain]: data
}
})
}
if(mode === 'sellHistory'){
setSellHistory((prev)=> {
return {
...prev,
[foreignBlockchain]: data
}
})
}
}).catch(()=> {}).finally(()=> {
setOpen(false)
})
}, [])
useEffect(()=> {
if(!qortAddress || !selectedCoin) return
if(mode === 'buyHistory' && buyHistory[selectedCoin])return
if(mode === 'sellHistory' && sellHistory[selectedCoin])return
getBuyHistory(qortAddress, selectedCoin, mode)
}, [qortAddress, selectedCoin, buyHistory, mode])
getBuyHistory(qortAddress, selectedCoin, mode);
}, [qortAddress, selectedCoin, buyHistory, mode]);
return (
<div style={{
width: '100%',
display: show ? 'block' : 'none'
}}>
<Button variant='outlined' onClick={()=> {
setMode('buyHistory')
}}>Buy History</Button>
<Button onClick={()=> {
setMode('sellHistory')
}} variant='outlined'>Sell History</Button>
<ButtonBase onClick={()=> {
getBuyHistory(qortAddress, selectedCoin, mode)
}}>
<RefreshIcon />
<Box
style={{
width: "100%",
display: show ? "block" : "none",
}}
>
<HistoryButtonRow>
<HistoryButton
activeBtn={mode === "buyHistory"}
onClick={() => {
setMode("buyHistory");
}}
>
Buy History
</HistoryButton>
<HistoryButton
activeBtn={mode === "sellHistory"}
onClick={() => {
setMode("sellHistory");
}}
>
Sell History
</HistoryButton>
<ButtonBase
onClick={() => {
getBuyHistory(qortAddress, selectedCoin, mode);
}}
>
<Refresh />
</ButtonBase>
<Typography>Showing most recent 20 results</Typography>
<HistoryList qortAddress={qortAddress} historyList={selectedHistory} />
<Snackbar
</HistoryButtonRow>
<ShowingFont>Showing most recent 20 results</ShowingFont>
<HistoryList qortAddress={qortAddress} historyList={selectedHistory} />
<Snackbar
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
open={open}
onClose={()=> {
setOpen(false)
onClose={() => {
setOpen(false);
}}
>
<Alert
onClose={()=> setOpen(false)}
onClose={() => setOpen(false)}
severity="info"
variant="filled"
sx={{ width: "100%" }}
>
{'Fetching History'}
{"Fetching History"}
</Alert>
</Snackbar>
</div>
)
}
</Box>
);
};

View File

@ -8,7 +8,6 @@ import { OngoingTrades } from "../../components/Grids/OngoingTrades";
import { Box } from "@mui/material";
import { TextTableTitle } from "../../components/Grids/Table-styles";
import { Spacer } from "../../components/common/Spacer";
import { ReusableModal } from "../../components/common/reusable-modal/ReusableModal";
import { Tab, TabDivider, TabsContainer, TabsRow } from "./Home-Styles";
import { CreateSell } from "../../components/sell/CreateSell";
import { History } from "../../components/history/History";