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 { Box, Button } from "@mui/material";
import { styled } from "@mui/system"; import { styled } from "@mui/system";
import CloseIcon from '@mui/icons-material/Close';
export const ReusableModalContainer = styled(Box)(({ theme }) => ({ export const ReusableModalContainer = styled(Box)(({ theme }) => ({
display: "flex", 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)", "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)({ export const ReusableModalBackdrop = styled(Box)({
position: "fixed", position: "fixed",
top: "0", top: "0",
@ -51,3 +43,16 @@ export const ReusableModalButton = styled(Button)(({ theme }) => ({
color: theme.palette.text.primary, color: theme.palette.text.primary,
boxShadow: "1px 4px 10.5px 0px #0000004D" 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 { import {
ReusableModalBackdrop, ReusableModalBackdrop,
ReusableModalCloseIcon,
ReusableModalContainer, ReusableModalContainer,
ReusableModalSubContainer,
} from "./ReusableModal-styles"; } from "./ReusableModal-styles";
interface ReusableModalProps { interface ReusableModalProps {
backdrop?: boolean; backdrop?: boolean;
onClickClose: () => void;
children: React.ReactNode; children: React.ReactNode;
} }
export const ReusableModal: React.FC<ReusableModalProps> = ({ backdrop, children }) => { export const ReusableModal: React.FC<ReusableModalProps> = ({
backdrop,
children,
onClickClose,
}) => {
return ( return (
<> <>
<ReusableModalContainer> <ReusableModalContainer>
<ReusableModalSubContainer>{children}</ReusableModalSubContainer> <ReusableModalCloseIcon onClick={onClickClose} />
{children}
</ReusableModalContainer> </ReusableModalContainer>
{backdrop && <ReusableModalBackdrop />} {backdrop && <ReusableModalBackdrop onClick={onClickClose} />}
</> </>
); );
}; };

View File

@ -1,5 +1,5 @@
import { styled } from "@mui/system"; 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 { HomeSVG } from "../common/icons/HomeSVG";
import { QortalLogoSVG } from "../common/icons/QortalLogoSVG"; import { QortalLogoSVG } from "../common/icons/QortalLogoSVG";
import { CaretDownSVG } from "../common/icons/CaretDownSVG"; import { CaretDownSVG } from "../common/icons/CaretDownSVG";
@ -217,3 +217,123 @@ export const CoinSelectRow = styled(Box)({
gap: "5px", gap: "5px",
alignSelf: "flex-start", 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 { useState, useEffect, useRef, useContext, ChangeEvent } from "react";
import { import {
BubbleCardColored1, BubbleCardColored1,
CoinActionContainer,
CoinActionRow,
CoinActionsRow, CoinActionsRow,
CoinCancelBtn,
CoinConfirmSendBtn,
CoinReceiveBtn, CoinReceiveBtn,
CoinSelectRow, CoinSelectRow,
CoinSendBtn, CoinSendBtn,
CustomInputField,
HeaderNav, HeaderNav,
HeaderRow,
HeaderText, HeaderText,
LogoColumn, LogoColumn,
NameRow, NameRow,
RightColumn, RightColumn,
SendFont,
TotalCol, TotalCol,
Username, Username,
} from "./Header-styles"; } from "./Header-styles";
@ -25,6 +32,7 @@ import {
Box, Box,
Card, Card,
CardContent, CardContent,
FormControl,
FormControlLabel, FormControlLabel,
MenuItem, MenuItem,
Select, Select,
@ -42,6 +50,8 @@ import rvnIcon from "../../assets/img/rvn.png";
import dgbIcon from "../../assets/img/dgb.png"; import dgbIcon from "../../assets/img/dgb.png";
import arrrIcon from "../../assets/img/arrr.png"; import arrrIcon from "../../assets/img/arrr.png";
import { Spacer } from "../common/Spacer"; import { Spacer } from "../common/Spacer";
import { ReusableModal } from "../common/reusable-modal/ReusableModal";
import { NotificationContext } from "../../contexts/notificationContext";
const checkIfLocal = async () => { const checkIfLocal = async () => {
try { try {
@ -65,6 +75,11 @@ export const Label = styled("label")(
` `
); );
interface CoinModalProps {
coin: string;
type: string;
}
const getCoinIcon = (coin) => { const getCoinIcon = (coin) => {
let img; let img;
@ -126,6 +141,11 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
const [checked, setChecked] = useState(false); const [checked, setChecked] = useState(false);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [info, setInfo] = useState<any>(null); 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 { isUsingGateway } = useContext(gameContext);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => { const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
@ -138,7 +158,7 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
}; };
const { userInfo, selectedCoin, setSelectedCoin, getCoinLabel } = const { userInfo, selectedCoin, setSelectedCoin, getCoinLabel } =
useContext(gameContext); useContext(gameContext);
const { avatar, setAvatar } = useContext(UserContext); const { setNotification } = useContext(NotificationContext);
const LocalNodeSwitch = styled(Switch)(({ theme }) => ({ const LocalNodeSwitch = styled(Switch)(({ theme }) => ({
padding: 8, padding: 8,
@ -327,8 +347,26 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
<HeaderText>{qortBalance} QORT</HeaderText> <HeaderText>{qortBalance} QORT</HeaderText>
</Box> </Box>
<CoinActionsRow> <CoinActionsRow>
<CoinSendBtn>Send</CoinSendBtn> <CoinSendBtn
<CoinReceiveBtn>Receive</CoinReceiveBtn> onClick={() => {
setOpenCoinActionModal({
coin: "QORT",
type: "send",
});
}}
>
Send
</CoinSendBtn>
<CoinReceiveBtn
onClick={() => {
setOpenCoinActionModal({
coin: "QORT",
type: "receive",
});
}}
>
Receive
</CoinReceiveBtn>
</CoinActionsRow> </CoinActionsRow>
</TotalCol> </TotalCol>
<Spacer height="10px" /> <Spacer height="10px" />
@ -351,8 +389,26 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
{getCoinLabel()} {getCoinLabel()}
</Box> </Box>
<CoinActionsRow> <CoinActionsRow>
<CoinSendBtn>Send</CoinSendBtn> <CoinSendBtn
<CoinReceiveBtn>Receive</CoinReceiveBtn> onClick={() => {
setOpenCoinActionModal({
coin: selectedCoin,
type: "send",
});
}}
>
Send
</CoinSendBtn>
<CoinReceiveBtn
onClick={() => {
setOpenCoinActionModal({
coin: selectedCoin,
type: "receive",
});
}}
>
Receive
</CoinReceiveBtn>
</CoinActionsRow> </CoinActionsRow>
</TotalCol> </TotalCol>
</CardContent> </CardContent>
@ -400,6 +456,116 @@ export const Header = ({ qortBalance, foreignCoinBalance }: any) => {
{info?.message} {info?.message}
</Alert> </Alert>
</Snackbar> </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> </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 {
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react' Alert,
import { BootstrapDialog } from '../Terms' Box,
import CloseIcon from '@mui/icons-material/Close'; ButtonBase,
import { Spacer } from '../common/Spacer'; Snackbar
import gameContext from '../../contexts/gameContext'; } from "@mui/material";
import HistoryList from './HistoryList'; import React, {
import RefreshIcon from "@mui/icons-material/Refresh"; 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(() => {
export const History = ({qortAddress, show}) => { if (mode === "buyHistory") return buyHistory[selectedCoin] || [];
const [buyHistory, setBuyHistory] = useState({}) if (mode === "sellHistory") return sellHistory[selectedCoin] || [];
const [sellHistory, setSellHistory] = useState({}) }, [selectedCoin, buyHistory, sellHistory, mode]);
const getBuyHistory = useCallback(
const { getCoinLabel, selectedCoin} = useContext(gameContext) (address, foreignBlockchain, mode, limit = 20) => {
const [mode, setMode] = useState('buyHistory') setOpen(true);
const [open, setOpen] = useState(false) let historyUrl;
if (mode === "buyHistory") {
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`; historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&buyerAddress=${address}&limit=${limit}&reverse=true`;
} }
if(mode === 'sellHistory'){ if (mode === "sellHistory") {
historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&sellerAddress=${address}&limit=${limit}&reverse=true`; historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&sellerAddress=${address}&limit=${limit}&reverse=true`;
} }
fetch(historyUrl) fetch(historyUrl)
.then((response) => { .then((response) => {
return response.json(); return response.json();
}) })
.then((data) => { .then((data) => {
if(mode === 'buyHistory'){ if (mode === "buyHistory") {
setBuyHistory((prev)=> { setBuyHistory((prev) => {
return { return {
...prev, ...prev,
[foreignBlockchain]: data [foreignBlockchain]: data,
};
});
} }
}) if (mode === "sellHistory") {
} setSellHistory((prev) => {
if(mode === 'sellHistory'){
setSellHistory((prev)=> {
return { return {
...prev, ...prev,
[foreignBlockchain]: data [foreignBlockchain]: data,
};
});
} }
}) })
} .catch(() => {})
.finally(() => {
setOpen(false);
});
},
[]
);
}).catch(()=> {}).finally(()=> { useEffect(() => {
setOpen(false) if (!qortAddress || !selectedCoin) return;
}) if (mode === "buyHistory" && buyHistory[selectedCoin]) return;
}, []) if (mode === "sellHistory" && sellHistory[selectedCoin]) return;
useEffect(()=> { getBuyHistory(qortAddress, selectedCoin, mode);
if(!qortAddress || !selectedCoin) return }, [qortAddress, selectedCoin, buyHistory, mode]);
if(mode === 'buyHistory' && buyHistory[selectedCoin])return
if(mode === 'sellHistory' && sellHistory[selectedCoin])return
getBuyHistory(qortAddress, selectedCoin, mode)
}, [qortAddress, selectedCoin, buyHistory, mode])
return ( return (
<div style={{ <Box
width: '100%', style={{
display: show ? 'block' : 'none' width: "100%",
}}> display: show ? "block" : "none",
<Button variant='outlined' onClick={()=> { }}
setMode('buyHistory') >
}}>Buy History</Button> <HistoryButtonRow>
<Button onClick={()=> { <HistoryButton
setMode('sellHistory') activeBtn={mode === "buyHistory"}
}} variant='outlined'>Sell History</Button> onClick={() => {
<ButtonBase onClick={()=> { setMode("buyHistory");
getBuyHistory(qortAddress, selectedCoin, mode) }}
}}> >
<RefreshIcon /> Buy History
</HistoryButton>
<HistoryButton
activeBtn={mode === "sellHistory"}
onClick={() => {
setMode("sellHistory");
}}
>
Sell History
</HistoryButton>
<ButtonBase
onClick={() => {
getBuyHistory(qortAddress, selectedCoin, mode);
}}
>
<Refresh />
</ButtonBase> </ButtonBase>
<Typography>Showing most recent 20 results</Typography> </HistoryButtonRow>
<ShowingFont>Showing most recent 20 results</ShowingFont>
<HistoryList qortAddress={qortAddress} historyList={selectedHistory} /> <HistoryList qortAddress={qortAddress} historyList={selectedHistory} />
<Snackbar <Snackbar
anchorOrigin={{ vertical: "bottom", horizontal: "center" }} anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
open={open} open={open}
onClose={()=> { onClose={() => {
setOpen(false) setOpen(false);
}} }}
> >
<Alert <Alert
onClose={()=> setOpen(false)} onClose={() => setOpen(false)}
severity="info" severity="info"
variant="filled" variant="filled"
sx={{ width: "100%" }} sx={{ width: "100%" }}
> >
{'Fetching History'} {"Fetching History"}
</Alert> </Alert>
</Snackbar> </Snackbar>
</div> </Box>
) );
} };

View File

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