From 9f05dc20f6c40856c37cc5dc5200af26ea9eeb74 Mon Sep 17 00:00:00 2001 From: fabiolalombardim <37227394+fabiolalombardim@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:14:27 +0100 Subject: [PATCH] Merge new designs into develop (#731) * user page initial commit, font changed, tabs & cards updated * upgrades on user page * user movements component * user page - voting and proposals list item updated * user transactions finished - pagination & responsiveness * clean up * votes component logic fixed * fix 733 * tabs updated and pagination added to all tabs * multiple ui fixes * clean up * fix padding * fix quorum values on summary * fix card paddings * drop & expired buttons --- public/index.html | 3 +- src/assets/img/bullet.png | Bin 0 -> 882 bytes src/assets/img/bullet.svg | 3 + src/assets/logos/deposit_icon.svg | 3 + src/assets/logos/transactions_active.svg | 3 + src/assets/logos/transactions_inactive.svg | 3 + src/assets/logos/votes_active.svg | 3 + src/assets/logos/votes_inactive.svg | 3 + src/assets/logos/voting_active.svg | 3 + src/assets/logos/voting_inactive.svg | 3 + src/assets/logos/withdrawal_icon.svg | 3 + src/modules/common/ChangeNetworkButton.tsx | 4 +- src/modules/common/CopyButton.tsx | 18 +- src/modules/common/SmallButton.tsx | 1 + src/modules/common/TitleBlock.tsx | 2 - src/modules/common/Toolbar.tsx | 6 +- src/modules/creator/deployment/index.tsx | 2 +- .../creator/deployment/steps/Config.tsx | 2 +- src/modules/creator/index.tsx | 2 +- src/modules/creator/steps/DaoSettings.tsx | 2 +- src/modules/creator/steps/DeploymentType.tsx | 2 +- src/modules/creator/steps/Governance.tsx | 3 +- src/modules/creator/steps/Quorum.tsx | 2 +- src/modules/creator/steps/Template.tsx | 9 +- .../components/ChangeNetworkButton.tsx | 25 +- .../explorer/components/CodeCollapse.tsx | 2 +- .../components/ConfigProposalFormLambda.tsx | 2 +- .../explorer/components/ContentContainer.tsx | 2 +- .../explorer/components/DAOStatsRow.tsx | 71 ++- .../DelegationChangeProposalForm.tsx | 2 +- src/modules/explorer/components/Dropdown.tsx | 2 +- .../components/GuardianChangeProposalForm.tsx | 2 +- src/modules/explorer/components/Hero.tsx | 3 +- src/modules/explorer/components/HeroTitle.tsx | 8 +- .../explorer/components/NavigationMenu.tsx | 26 +- .../components/NewTreasuryProposalDialog.tsx | 2 +- .../explorer/components/ProposalForm.tsx | 6 +- .../explorer/components/ProposalsList.tsx | 85 +-- .../explorer/components/StatusBadge.tsx | 12 +- src/modules/explorer/components/Toolbar.tsx | 3 +- .../explorer/components/UserBalances.tsx | 120 ++-- .../explorer/components/UsersTable.tsx | 48 +- .../pages/Config/components/DAOInfoTable.tsx | 8 +- src/modules/explorer/pages/DAO/index.tsx | 15 +- .../pages/DAOList/components/DAOItem.tsx | 48 +- src/modules/explorer/pages/DAOList/index.tsx | 6 +- src/modules/explorer/pages/DAOList/styles.css | 12 +- src/modules/explorer/pages/NFTs/index.tsx | 79 ++- .../ProposalDetails/components/CodeVisor.tsx | 2 +- .../components/QuorumThreshold.tsx | 2 +- .../explorer/pages/ProposalDetails/index.tsx | 4 +- .../explorer/pages/Proposals/index.tsx | 404 +++++------- .../Treasury/components/BalancesTable.tsx | 35 +- .../Treasury/components/TransfersTable.tsx | 150 ++++- src/modules/explorer/pages/Treasury/index.tsx | 242 ++++--- .../User/components/DelegationBanner.tsx | 143 +++-- .../pages/User/components/DelegationModal.tsx | 2 +- .../pages/User/components/TransactionItem.tsx | 68 ++ .../pages/User/components/UserMovements.tsx | 589 ++++++++++++++++++ src/modules/explorer/pages/User/index.tsx | 167 +++-- src/modules/home/Header.tsx | 2 +- src/modules/home/LandingHeader.tsx | 2 +- src/modules/lite/creator/index.tsx | 6 +- .../components/ChoiceItemSelected.tsx | 10 +- .../explorer/components/DaoCardDetail.tsx | 2 +- .../components/ProposalDetailCard.tsx | 9 +- .../lite/explorer/components/ProposalList.tsx | 26 +- .../explorer/components/ProposalTableRow.tsx | 47 +- .../ProposalTableRowStatusBadge.tsx | 13 +- .../components/tables/RowContainer.tsx | 5 +- .../lite/explorer/hooks/useUserVotes.tsx | 45 ++ .../explorer/pages/CreateProposal/index.tsx | 6 +- .../explorer/pages/ProposalDetails/index.tsx | 2 +- .../contracts/baseDAO/hooks/useTransfers.ts | 13 +- src/theme/index.ts | 65 +- src/theme/legacy.ts | 24 +- 76 files changed, 1849 insertions(+), 910 deletions(-) create mode 100644 src/assets/img/bullet.png create mode 100644 src/assets/img/bullet.svg create mode 100644 src/assets/logos/deposit_icon.svg create mode 100644 src/assets/logos/transactions_active.svg create mode 100644 src/assets/logos/transactions_inactive.svg create mode 100644 src/assets/logos/votes_active.svg create mode 100644 src/assets/logos/votes_inactive.svg create mode 100644 src/assets/logos/voting_active.svg create mode 100644 src/assets/logos/voting_inactive.svg create mode 100644 src/assets/logos/withdrawal_icon.svg create mode 100644 src/modules/explorer/pages/User/components/TransactionItem.tsx create mode 100644 src/modules/explorer/pages/User/components/UserMovements.tsx create mode 100644 src/modules/lite/explorer/hooks/useUserVotes.tsx diff --git a/public/index.html b/public/index.html index 68600f24..e5b76041 100644 --- a/public/index.html +++ b/public/index.html @@ -4,7 +4,8 @@ - + + diff --git a/src/assets/img/bullet.png b/src/assets/img/bullet.png new file mode 100644 index 0000000000000000000000000000000000000000..8cb4ed70074ce960bd1ff4b5d586835492de185f GIT binary patch literal 882 zcmV-&1C9KNP)0^EU8Pv5(No^}VVbpgTxTI~+%4t(uH4|WG`pl#|;Q4t7{ zKnO{u_YQ7j_aDh*de~8j4v_oC4N@XV`OSP4t@}h#gg#^Ea?ky zX*I#~`=#UJR{0ijM4Fq=LbXwov8<*+A(w|tIt`RPfry*<(wfzPmgC4+Ue7_t?Lw#L zj>y?iQzI6O|DsGU@qmmKp1|^A9wwn$uYq~~XGGq-Zh;8HA{CZXFc6|L_@n{p^QWu# zk`ibS?Iq9`ca!GnDU27M0+1oFYdp-sCb_ zNg939v{+dx$W|l{>J~o~uQ(H8%@2IJA(zR>N>2+S&CCt5^}`T2W9y``K??*enSxnC z9YhE)Nddy(0zeOfL2r`IvqBlRqZmBuq_Gt(`auA*qK9Kn81}nGQkcq63cJ&WS%Kam ze*@H*0W&$~{ymy18z*U&tb3jZ4IB=Fq97%MBOY>gKxRTcNTjE=3z!z<6$C0^!?pp_ z+~=n_ewgW@mQ>{;jcGK24<$XVoy-5!a$di0jz$_&FV|X4=~RRtXD1^gnuKco3ilq% z|M{WIVK)@%S&D1#e>KyuU!vx0V<9~+3t_ddv6zl@DH9;Yv{KQD^muc-6s_I5K~^ifZy7q& zyrvm6_tb)s??z-=N|k!j_@39VtU!e2v(4?je|he@^9;1o5^A%aQdL96iA>@RLK8}N zpM$2}bzLhI;pZ6Vdsr;%CdYq?$K*j<#ZAVITlxsejwYS^3m$@gI7riw5&!@I07*qo IM6N<$f~&BHivR!s literal 0 HcmV?d00001 diff --git a/src/assets/img/bullet.svg b/src/assets/img/bullet.svg new file mode 100644 index 00000000..e2dc8dbc --- /dev/null +++ b/src/assets/img/bullet.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/deposit_icon.svg b/src/assets/logos/deposit_icon.svg new file mode 100644 index 00000000..02cecec3 --- /dev/null +++ b/src/assets/logos/deposit_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/transactions_active.svg b/src/assets/logos/transactions_active.svg new file mode 100644 index 00000000..28fce717 --- /dev/null +++ b/src/assets/logos/transactions_active.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/transactions_inactive.svg b/src/assets/logos/transactions_inactive.svg new file mode 100644 index 00000000..a580de2b --- /dev/null +++ b/src/assets/logos/transactions_inactive.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/votes_active.svg b/src/assets/logos/votes_active.svg new file mode 100644 index 00000000..6345bb6e --- /dev/null +++ b/src/assets/logos/votes_active.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/votes_inactive.svg b/src/assets/logos/votes_inactive.svg new file mode 100644 index 00000000..84c82ee7 --- /dev/null +++ b/src/assets/logos/votes_inactive.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/voting_active.svg b/src/assets/logos/voting_active.svg new file mode 100644 index 00000000..82694183 --- /dev/null +++ b/src/assets/logos/voting_active.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/voting_inactive.svg b/src/assets/logos/voting_inactive.svg new file mode 100644 index 00000000..093055c6 --- /dev/null +++ b/src/assets/logos/voting_inactive.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/logos/withdrawal_icon.svg b/src/assets/logos/withdrawal_icon.svg new file mode 100644 index 00000000..b5a978bb --- /dev/null +++ b/src/assets/logos/withdrawal_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/modules/common/ChangeNetworkButton.tsx b/src/modules/common/ChangeNetworkButton.tsx index 226f2d86..d1ef4b11 100644 --- a/src/modules/common/ChangeNetworkButton.tsx +++ b/src/modules/common/ChangeNetworkButton.tsx @@ -56,9 +56,7 @@ export const ChangeNetworkButton = () => { - - {capitalize(network)} - + {capitalize(network)} diff --git a/src/modules/common/CopyButton.tsx b/src/modules/common/CopyButton.tsx index 3b2d9f0b..976f65a4 100644 --- a/src/modules/common/CopyButton.tsx +++ b/src/modules/common/CopyButton.tsx @@ -1,16 +1,20 @@ import React, { useState } from "react" -import { Box, styled, Tooltip } from "@material-ui/core" -import { FileCopyOutlined, Image } from "@material-ui/icons" +import { Box, Grid, styled, Tooltip, Typography } from "@material-ui/core" import DownloadIcon from "assets/img/download.svg" const CopyIcon = styled("img")({ cursor: "pointer" }) -export const CopyButton: React.FC<{ text: string; style?: any }> = ({ text, style }) => { +export const CopyButton: React.FC<{ text: string; style?: any; displayedText?: string }> = ({ + text, + style, + displayedText +}) => { const [copied, setCopied] = useState(false) return ( { @@ -24,7 +28,13 @@ export const CopyButton: React.FC<{ text: string; style?: any }> = ({ text, styl }} > - + + + + {" "} + {displayedText} + + ) diff --git a/src/modules/common/SmallButton.tsx b/src/modules/common/SmallButton.tsx index e3dd4d6b..df190a0f 100644 --- a/src/modules/common/SmallButton.tsx +++ b/src/modules/common/SmallButton.tsx @@ -9,6 +9,7 @@ export const SmallButton = styled(Button)({ "borderRadius": 8, "backgroundColor": "#81feb7 !important", "color": "#1c1f23", + "padding": "8px 16px", "&$disabled": { boxShadow: "none" diff --git a/src/modules/common/TitleBlock.tsx b/src/modules/common/TitleBlock.tsx index 2eed2299..8aadc35e 100644 --- a/src/modules/common/TitleBlock.tsx +++ b/src/modules/common/TitleBlock.tsx @@ -2,8 +2,6 @@ import { Grid, Link, Paper, styled, Tooltip, Typography } from "@material-ui/cor import React from "react" import { ReactElement } from "react-markdown/lib/react-markdown" import { InfoRounded } from "@material-ui/icons" -import { HashLink } from "react-router-hash-link" -import { CopyButton } from "./CopyButton" const StyledGrid = styled(Grid)({ height: "fit-content", diff --git a/src/modules/common/Toolbar.tsx b/src/modules/common/Toolbar.tsx index 8c63683a..216d1488 100644 --- a/src/modules/common/Toolbar.tsx +++ b/src/modules/common/Toolbar.tsx @@ -107,13 +107,13 @@ const LogoText = styled(Typography)({ fontWeight: "bold", fontSize: "26px", cursor: "pointer", - fontFamily: "Roboto", + fontFamily: "Roboto Flex", letterSpacing: "initial" }) const AddressBarWrapper = styled(Grid)(({ theme }) => ({ borderRadius: 8, - background: theme.palette.primary.main, + background: theme.palette.primary.dark, paddingLeft: 16, paddingRight: 16, paddingTop: 5, @@ -249,7 +249,7 @@ export const Navbar: React.FC<{ - + diff --git a/src/modules/creator/deployment/index.tsx b/src/modules/creator/deployment/index.tsx index ead83584..d066e134 100644 --- a/src/modules/creator/deployment/index.tsx +++ b/src/modules/creator/deployment/index.tsx @@ -55,7 +55,7 @@ const IndicatorValue = styled(Paper)(({ theme }) => ({ userSelect: "none", boxShadow: "none", background: "inherit", - fontFamily: "Roboto Mono" + fontFamily: "Roboto Flex" })) const StepContentContainer = styled(Grid)({ diff --git a/src/modules/creator/deployment/steps/Config.tsx b/src/modules/creator/deployment/steps/Config.tsx index 5fc131bc..eab56514 100644 --- a/src/modules/creator/deployment/steps/Config.tsx +++ b/src/modules/creator/deployment/steps/Config.tsx @@ -29,7 +29,7 @@ const CustomTextarea = styled(withTheme(TextareaAutosize))(props => ({ "marginTop": 14, "fontWeight": 300, "padding": "21px 20px", - "fontFamily": "Roboto Mono", + "fontFamily": "Roboto Flex", "border": "none", "fontSize": 16, "color": props.theme.palette.text.secondary, diff --git a/src/modules/creator/index.tsx b/src/modules/creator/index.tsx index 20985732..805773bc 100644 --- a/src/modules/creator/index.tsx +++ b/src/modules/creator/index.tsx @@ -65,7 +65,7 @@ const IndicatorValue = styled(Paper)(({ theme }) => ({ userSelect: "none", boxShadow: "none", background: "inherit", - fontFamily: "Roboto Mono" + fontFamily: "Roboto Flex" })) const FAQClickToAction = styled(Typography)(({ theme }) => ({ diff --git a/src/modules/creator/steps/DaoSettings.tsx b/src/modules/creator/steps/DaoSettings.tsx index cd100deb..2122f20d 100644 --- a/src/modules/creator/steps/DaoSettings.tsx +++ b/src/modules/creator/steps/DaoSettings.tsx @@ -102,7 +102,7 @@ const CustomTextarea = styled(withTheme(TextareaAutosize))(props => ({ "padding": "21px 20px", "border": "none", "fontSize": 16, - "fontFamily": "Roboto Mono", + "fontFamily": "Roboto Flex", "color": props.theme.palette.text.secondary, "background": "#2F3438", "lineHeight": "135%", diff --git a/src/modules/creator/steps/DeploymentType.tsx b/src/modules/creator/steps/DeploymentType.tsx index 8fd999d4..f68fb7f3 100644 --- a/src/modules/creator/steps/DeploymentType.tsx +++ b/src/modules/creator/steps/DeploymentType.tsx @@ -43,7 +43,7 @@ const styles = makeStyles({ const BoxTitle = styled(Typography)({ fontSize: 18, fontWeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", marginBottom: 10 }) diff --git a/src/modules/creator/steps/Governance.tsx b/src/modules/creator/steps/Governance.tsx index e8b42475..58c2fc4f 100644 --- a/src/modules/creator/steps/Governance.tsx +++ b/src/modules/creator/steps/Governance.tsx @@ -153,7 +153,8 @@ const styles = { voting: { marginTop: 6, marginBottom: 16, - fontWeight: 400 + fontWeight: 400, + fontSize: 17 } } diff --git a/src/modules/creator/steps/Quorum.tsx b/src/modules/creator/steps/Quorum.tsx index 97283600..cf310000 100644 --- a/src/modules/creator/steps/Quorum.tsx +++ b/src/modules/creator/steps/Quorum.tsx @@ -543,7 +543,7 @@ export const Quorum: React.FC = () => { updateCache(newState) setSubmitting(true) - dispatch({ type: ActionTypes.UPDATE_QUORUM_SETTINGS, quorum: values }) + dispatch({ type: ActionTypes.UPDATE_QUORUM_SETTINGS, quorum: typeOfQuorum ? values : fixedValues }) history.push(`summary`) } diff --git a/src/modules/creator/steps/Template.tsx b/src/modules/creator/steps/Template.tsx index 629265e2..960dcc8a 100644 --- a/src/modules/creator/steps/Template.tsx +++ b/src/modules/creator/steps/Template.tsx @@ -14,12 +14,13 @@ const LambdaCustomBox = styled(Grid)(({ theme }) => ({ "marginTop": 30, "background": "#2F3438", "borderRadius": 8, - "maxWidth": 320, + "maxWidth": 342, "width": "-webkit-fill-available", "padding": "40px 44px", "textAlign": "start", "cursor": "pointer", "paddingBottom": 0, + "flexBasis": "47%", "&:hover": { border: "3px solid rgba(129, 254, 183, 0.4)", paddingTop: 37, @@ -50,7 +51,7 @@ const ErrorText = styled(Typography)({ const BoxTitle = styled(Typography)({ fontSize: 18, fontWeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", marginBottom: 10 }) @@ -120,7 +121,7 @@ export const Template = (): JSX.Element => { direction="column" justifyContent="flex-start" alignItems="center" - xs={isMobileSmall ? 12 : 6} + xs={isMobileSmall ? 12 : 5} onClick={() => update("lambda")} className={selectedTemplate === "lambda" ? style.selected : ""} > @@ -136,7 +137,7 @@ export const Template = (): JSX.Element => { direction="column" justifyContent="flex-start" alignItems="center" - xs={isMobileSmall ? 12 : 6} + xs={isMobileSmall ? 12 : 5} onClick={() => update("lite")} className={selectedTemplate === "lite" ? style.selected : ""} > diff --git a/src/modules/explorer/components/ChangeNetworkButton.tsx b/src/modules/explorer/components/ChangeNetworkButton.tsx index d2f484ef..a564b7bb 100644 --- a/src/modules/explorer/components/ChangeNetworkButton.tsx +++ b/src/modules/explorer/components/ChangeNetworkButton.tsx @@ -17,6 +17,7 @@ const StyledConnectedButton = styled(Box)(({ theme }: { theme: Theme }) => ({ "paddingBottom": 6, "cursor": "pointer", "transition": ".15s ease-out", + "height": 23, "&:hover": { background: theme.palette.secondary.dark, @@ -47,20 +48,18 @@ export const ChangeNetworkButton = () => { return ( <> - {canShow ? ( - open()}> - - - - - - - {capitalize(network)} - - + open()}> + + + - - ) : null} + + + {capitalize(network)} + + + + ) } diff --git a/src/modules/explorer/components/CodeCollapse.tsx b/src/modules/explorer/components/CodeCollapse.tsx index 8642ca01..8f9338fc 100644 --- a/src/modules/explorer/components/CodeCollapse.tsx +++ b/src/modules/explorer/components/CodeCollapse.tsx @@ -65,7 +65,7 @@ export const CodeCollapse: React.FC = ({ code }) => { padding={10} style={{ minHeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 14, fontWeight: 400, outlineWidth: 0 diff --git a/src/modules/explorer/components/ConfigProposalFormLambda.tsx b/src/modules/explorer/components/ConfigProposalFormLambda.tsx index 9206a2f2..cda20d42 100644 --- a/src/modules/explorer/components/ConfigProposalFormLambda.tsx +++ b/src/modules/explorer/components/ConfigProposalFormLambda.tsx @@ -45,7 +45,7 @@ const codeEditorcontainerstyles = { const codeEditorStyles = { minHeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 14, fontWeight: 400, outlineWidth: 0 diff --git a/src/modules/explorer/components/ContentContainer.tsx b/src/modules/explorer/components/ContentContainer.tsx index 1cb088d1..76fdc40b 100644 --- a/src/modules/explorer/components/ContentContainer.tsx +++ b/src/modules/explorer/components/ContentContainer.tsx @@ -2,5 +2,5 @@ import { styled, Grid } from "@material-ui/core" export const ContentContainer = styled(Grid)(({ theme }) => ({ borderRadius: 8, - background: theme.palette.primary.main + background: "#24282D" })) diff --git a/src/modules/explorer/components/DAOStatsRow.tsx b/src/modules/explorer/components/DAOStatsRow.tsx index 821e30fe..edf7fc55 100644 --- a/src/modules/explorer/components/DAOStatsRow.tsx +++ b/src/modules/explorer/components/DAOStatsRow.tsx @@ -7,11 +7,13 @@ import { ProposalStatus } from "services/services/dao/mappers/proposal/types" import { useDAOID } from "../pages/DAO/router" import { usePolls } from "modules/lite/explorer/hooks/usePolls" import dayjs from "dayjs" -import { formatNumber } from "../utils/FormatNumber" import { useDAOHoldings, useDAONFTHoldings } from "services/contracts/baseDAO/hooks/useDAOHoldings" +import { useTimeLeftInCycle } from "../hooks/useTimeLeftInCycle" +import { useIsProposalButtonDisabled } from "services/contracts/baseDAO/hooks/useCycleInfo" +import numbro from "numbro" const Item = styled(Paper)(({ theme }) => ({ - backgroundColor: theme.palette.primary.main, + backgroundColor: "#24282d", borderRadius: 8, color: theme.palette.text.primary, height: 84, @@ -36,6 +38,8 @@ const ItemTitle = styled(Typography)(({ theme }) => ({ const ItemValue = styled(Typography)(({ theme }) => ({ fontSize: 32, fontWeight: 300, + overflowX: "scroll", + cursor: "default", [theme.breakpoints.down("sm")]: { fontSize: 28 } @@ -48,9 +52,16 @@ const Percentage = styled(Typography)({ paddingLeft: 18 }) +const formatConfig = { + average: true, + mantissa: 1, + thousandSeparated: true, + trimMantissa: true +} + export const DAOStatsRow: React.FC = () => { const daoId = useDAOID() - const { data, ledger } = useDAO(daoId) + const { data, ledger, cycleInfo } = useDAO(daoId) const symbol = data && data.data.token.symbol.toUpperCase() const theme = useTheme() const { data: activeProposals } = useProposals(daoId, ProposalStatus.ACTIVE) @@ -58,6 +69,9 @@ export const DAOStatsRow: React.FC = () => { const activeLiteProposals = polls?.filter(p => Number(p.endTime) > dayjs().valueOf()) const { tokenHoldings } = useDAOHoldings(daoId) const { nftHoldings } = useDAONFTHoldings(daoId) + const { data: executableProposals } = useProposals(daoId, ProposalStatus.EXECUTABLE) + const { hours, minutes, days } = useTimeLeftInCycle() + const shouldDisable = useIsProposalButtonDisabled(daoId) const amountLocked = useMemo(() => { if (!ledger) { @@ -91,7 +105,18 @@ export const DAOStatsRow: React.FC = () => { Total {symbol} - {formatNumber(totalTokens)} + {numbro(totalTokens).format(formatConfig)} + + + + + + + {symbol} Locked + + + {numbro(amountLocked).format(formatConfig)} + {numbro(amountLockedPercentage).format(formatConfig)}% @@ -108,21 +133,43 @@ export const DAOStatsRow: React.FC = () => { - Tokens + Cycle Status - {tokenHoldings.length || "-"} + {shouldDisable ? "Voting" : "Creating"} - {symbol} Locked + Current Cycle - - {formatNumber(amountLocked)} - {formatNumber(amountLockedPercentage)}% + + {cycleInfo?.currentCycle} + + + + + + + Time Left in Cycle + + + + {" "} + {days}d {hours}h {minutes}m{" "} + + + + + + + + Total Tokens + + + {tokenHoldings.length || "-"} @@ -144,10 +191,10 @@ export const DAOStatsRow: React.FC = () => { - NFTs + Executable Proposals - {nftHoldings?.length || "-"} + {executableProposals?.length} diff --git a/src/modules/explorer/components/DelegationChangeProposalForm.tsx b/src/modules/explorer/components/DelegationChangeProposalForm.tsx index 1f4a2965..8c0f9d74 100644 --- a/src/modules/explorer/components/DelegationChangeProposalForm.tsx +++ b/src/modules/explorer/components/DelegationChangeProposalForm.tsx @@ -103,7 +103,7 @@ export const DelegationChangeProposalForm: React.FC = ({ open, handleClos {dao && ( - + Current Delegate:{" "} diff --git a/src/modules/explorer/components/Dropdown.tsx b/src/modules/explorer/components/Dropdown.tsx index fcf67ced..856209f6 100644 --- a/src/modules/explorer/components/Dropdown.tsx +++ b/src/modules/explorer/components/Dropdown.tsx @@ -25,7 +25,7 @@ const useStyles = makeStyles((theme: Theme) => ({ }, option: { "padding": 8, - "fontFamily": "Roboto Mono", + "fontFamily": "Roboto Flex", "cursor": "pointer", "text-transform": "capitalize", "&:hover": { diff --git a/src/modules/explorer/components/GuardianChangeProposalForm.tsx b/src/modules/explorer/components/GuardianChangeProposalForm.tsx index 10f092c2..8d758861 100644 --- a/src/modules/explorer/components/GuardianChangeProposalForm.tsx +++ b/src/modules/explorer/components/GuardianChangeProposalForm.tsx @@ -98,7 +98,7 @@ export const GuardianChangeProposalForm: React.FC = ({ open, handleClose, {dao && ( - + Current Guardian:{" "} diff --git a/src/modules/explorer/components/Hero.tsx b/src/modules/explorer/components/Hero.tsx index 96f82a85..38ea79f7 100644 --- a/src/modules/explorer/components/Hero.tsx +++ b/src/modules/explorer/components/Hero.tsx @@ -3,8 +3,9 @@ import React from "react" import { ContentContainer } from "./ContentContainer" const Container = styled(ContentContainer)({ - "padding": "38px 38px", + "padding": "0px", "boxSizing": "border-box", + "background": "inherit", "& > *": { height: "100%" diff --git a/src/modules/explorer/components/HeroTitle.tsx b/src/modules/explorer/components/HeroTitle.tsx index e0ddb2f4..408c334e 100644 --- a/src/modules/explorer/components/HeroTitle.tsx +++ b/src/modules/explorer/components/HeroTitle.tsx @@ -1,13 +1,13 @@ import { styled, Typography } from "@material-ui/core" export const HeroTitle = styled(Typography)(({ theme }) => ({ - fontSize: 30, - fontWeight: 500, color: theme.palette.text.primary, - lineHeight: 0.8, marginBottom: "9px", + fontSize: 36, + fontWeight: 500, + lineHeight: 0.9, ["@media (max-width:1030px)"]: { - fontSize: 25 + fontSize: 26 } })) diff --git a/src/modules/explorer/components/NavigationMenu.tsx b/src/modules/explorer/components/NavigationMenu.tsx index ce51e220..52fbe6df 100644 --- a/src/modules/explorer/components/NavigationMenu.tsx +++ b/src/modules/explorer/components/NavigationMenu.tsx @@ -31,23 +31,10 @@ const Container = styled(Grid)(({ theme }) => ({ const InnerContainer = styled(Grid)(({ theme }: { theme: Theme }) => ({ width: "1000px", + paddingLeft: 0, + paddingRight: 0, margin: "auto", borderRadius: 8, - backgroundColor: theme.palette.primary.main, - padding: 16, - alignItems: "center", - justifyContent: "space-between", - - ["@media (max-width:1167px)"]: { - width: "86vw" - } -})) - -const InnerContainerExplorer = styled(Grid)(({ theme }: { theme: Theme }) => ({ - width: "1000px", - margin: "auto", - borderRadius: 8, - backgroundColor: theme.palette.primary.dark, padding: 16, alignItems: "center", justifyContent: "space-between", @@ -61,7 +48,7 @@ const PageItemMobile = styled(Grid)(({ theme, isSelected }: { theme: Theme; isSe "display": "flex", "alignItems": "center", "borderTop": "2px solid transparent", - "backgroundColor": isSelected ? "rgba(129, 254, 183, 0.20)" : "inherit", + "backgroundColor": isSelected ? "#24282D" : "inherit", "height": "auto", "padding": "20px 20px", "borderRadius": 8, @@ -97,12 +84,11 @@ const PageItem = styled(Grid)(({ theme, isSelected }: { theme: Theme; isSelected "display": "flex", "alignItems": "center", "borderTop": "2px solid transparent", - "backgroundColor": isSelected ? "rgba(129, 254, 183, 0.20)" : "inherit", - "height": 40, - "padding": "20px 20px", + "backgroundColor": isSelected ? "#24282D" : "inherit", + "height": 50, + "padding": "20px 16px", "borderRadius": 8, "transition": isSelected ? "0s ease-in" : ".1s ease-out", - "width": 180, "justifyContent": "center", "& > a > *": { diff --git a/src/modules/explorer/components/NewTreasuryProposalDialog.tsx b/src/modules/explorer/components/NewTreasuryProposalDialog.tsx index fb06bf50..c78f82e0 100644 --- a/src/modules/explorer/components/NewTreasuryProposalDialog.tsx +++ b/src/modules/explorer/components/NewTreasuryProposalDialog.tsx @@ -291,7 +291,7 @@ export const NewTreasuryProposalDialog: React.FC<{ open: boolean }> = ({ open }) - {"Amount"} + {"Amount"} {showMax ? ( = { @@ -97,7 +98,8 @@ const Content = styled(Grid)({ }) const SwapText = styled(Typography)({ - opacity: 0.65 + opacity: 0.65, + color: "#fff" }) export const ProposalFormContainer: React.FC = ({ diff --git a/src/modules/explorer/components/ProposalsList.tsx b/src/modules/explorer/components/ProposalsList.tsx index 050a8483..dadd1ebd 100644 --- a/src/modules/explorer/components/ProposalsList.tsx +++ b/src/modules/explorer/components/ProposalsList.tsx @@ -9,8 +9,10 @@ import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp" import { ProposalTableRow } from "modules/lite/explorer/components/ProposalTableRow" import { StyledDivider } from "modules/lite/explorer/components/ProposalList" import { Poll } from "models/Polls" +import ReactPaginate from "react-paginate" +import "../pages/DAOList/styles.css" -const TableContainer = styled(ContentContainer)({ +const TableContainer = styled(Grid)({ width: "100%" }) @@ -21,47 +23,53 @@ const TableHeader = styled(Grid)({ const ProposalsFooter = styled(Grid)({ padding: "16px 46px", - borderTop: ".6px solid rgba(125,140,139, 0.2)", minHeight: 34 }) interface Props { currentLevel: number - proposals: Proposal[] - title: string + proposals: Proposal[] | undefined showFooter?: boolean rightItem?: (proposal: Proposal) => React.ReactElement liteProposals: Poll[] | undefined + proposalStyle?: any } export const ProposalsList: React.FC = ({ currentLevel, proposals, - title, showFooter, rightItem, - liteProposals + liteProposals, + proposalStyle }) => { + const [currentPage, setCurrentPage] = useState(0) + const [offset, setOffset] = useState(0) const [open, setopen] = useState(true) + const pageCount = Math.ceil( + proposals && liteProposals + ? proposals.length + liteProposals.length / 4 + : proposals && liteProposals?.length === undefined + ? proposals.length / 4 + : proposals?.length === undefined && liteProposals + ? liteProposals.length / 4 + : 0 + ) + + // Invoke when user click to request another page. + const handlePageClick = (event: { selected: number }) => { + if (proposals) { + const newOffset = (event.selected * 4) % proposals.length + setOffset(newOffset) + setCurrentPage(event.selected) + } + } + return ( - - - - - {title} - - - {proposals.length && proposals.length > 0 ? ( - - setopen(!open)}> - {open ? : } - - - ) : null} - - {proposals.length && proposals.length > 0 ? ( + + {proposals && proposals.length && proposals.length > 0 ? ( = ({ in={open} timeout="auto" unmountOnExit + // style={{ display: "block" }} direction="column" > - {proposals.map((p, i) => ( - + {proposals.slice(offset, offset + 4).map((p, i) => ( + {rightItem ? rightItem(p) : null} @@ -84,25 +93,15 @@ export const ProposalsList: React.FC = ({ ) : null} {liteProposals && liteProposals.length > 0 - ? liteProposals.map((poll, i) => { + ? liteProposals.slice(offset, offset + 4).map((poll, i) => { return ( -
+
- {liteProposals.length - 1 !== i ? : null}
) }) : null} - {!(proposals.length && proposals.length > 0) && !(liteProposals && liteProposals.length > 0) ? ( - - - - No items - - - - ) : null} {showFooter && ( @@ -115,6 +114,20 @@ export const ProposalsList: React.FC = ({ )} + + + ) } diff --git a/src/modules/explorer/components/StatusBadge.tsx b/src/modules/explorer/components/StatusBadge.tsx index 5fa9579f..9d42ed6b 100644 --- a/src/modules/explorer/components/StatusBadge.tsx +++ b/src/modules/explorer/components/StatusBadge.tsx @@ -6,8 +6,8 @@ const statusColors = (status: ProposalStatus | "all") => { switch (status) { case ProposalStatus.ACTIVE: return { - background: "#0085ff33", - color: "#0085FF", + background: "#2A4660", + color: "#85C4FF", text: "Active" } case ProposalStatus.PENDING: @@ -26,12 +26,12 @@ const statusColors = (status: ProposalStatus | "all") => { return { background: "#35796F", color: "#5AFFE1", - text: "Passed - Executable" + text: "Executable" } case ProposalStatus.REJECTED: return { - background: "#ff5a6433", - color: "#ff5a64", + background: "#513438", + color: "#FF8FA0", text: "Rejected" } case ProposalStatus.EXPIRED: @@ -56,7 +56,7 @@ const statusColors = (status: ProposalStatus | "all") => { return { background: "#2F7952", color: "#58FF98", - text: "Passed - Executed" + text: "Executed" } case "all": return { diff --git a/src/modules/explorer/components/Toolbar.tsx b/src/modules/explorer/components/Toolbar.tsx index c4124dfd..678ed91c 100644 --- a/src/modules/explorer/components/Toolbar.tsx +++ b/src/modules/explorer/components/Toolbar.tsx @@ -71,7 +71,7 @@ const LogoText = styled(Typography)({ fontWeight: "bold", fontSize: "26px", cursor: "pointer", - fontFamily: "Roboto", + fontFamily: "Roboto Flex", letterSpacing: "initial" }) @@ -138,7 +138,6 @@ export const Navbar: React.FC<{ disableMobileMenu?: boolean }> = ({ disableMobil - openUserMenuSheet()}> ({ minHeight: "137px", @@ -35,6 +36,7 @@ interface Balances { const BalanceHeaderText = styled(Typography)({ paddingBottom: 10, fontSize: 18, + fontWeight: 600, ["@media (max-width:710px)"]: { fontSize: 16 @@ -61,7 +63,7 @@ const BalanceGrid = styled(Grid)({ }) const Balance = styled(Typography)({ - fontSize: 36, + fontSize: 32, lineHeight: "0.9", fontWeight: 300, @@ -70,19 +72,57 @@ const Balance = styled(Typography)({ } }) -const BalanceToken = styled(Typography)({ - fontSize: 21, - fontWeight: 300 +const OnChainTitle = styled(Typography)({ + fontSize: 24, + fontWeight: 600 }) -const OnChainTitle = styled(Typography)({ - marginBottom: 16, - fontSize: 24 +const OnChainSubtitle = styled(Typography)({ + fontSize: 18, + fontWeight: 300, + color: "#bfc5ca", + lineHeight: "160%" +}) + +const OnChainBox = styled(Grid)(({ theme }) => ({ + display: "flex", + padding: "36px 48px 33px 48px", + flexDirection: "column", + justifyContent: "center", + alignItems: "flex-start", + gap: 24, + flexShrink: 0, + borderRadius: 8, + background: theme.palette.primary.main, + maxWidth: "32% !important", + [theme.breakpoints.down("sm")]: { + maxWidth: "100% !important", + marginBottom: 12 + } +})) + +const UnstakeText = styled(Typography)({ + marginLeft: 4, + fontSize: 18 }) -export const UserBalances: React.FC<{ daoId: string }> = ({ daoId, children }) => { +const UnstakeButton = styled(Button)({ + "padding": 0, + "&:hover": { + backgroundColor: "inherit", + background: "inherit" + } +}) + +export const UserBalances: React.FC<{ daoId: string; canUnstakeVotes: boolean; onUnstakeFromAllProposals: any }> = ({ + daoId, + children, + canUnstakeVotes, + onUnstakeFromAllProposals +}) => { const { account } = useTezos() const { data: dao, ledger } = useDAO(daoId) + const symbol = dao && dao.data.token.symbol.toUpperCase() const theme = useTheme() const isExtraSmall = useMediaQuery(theme.breakpoints.down(635)) @@ -127,39 +167,41 @@ export const UserBalances: React.FC<{ daoId: string }> = ({ daoId, children }) = - On-Chain Balances + On-Chain {symbol} Balances - {dao && - balancesList.map(({ displayName, balance }, i) => ( - - - {displayName} - - - - {balance} - - - {balance !== "-" ? dao.data.token.symbol : ""} - - - - ))} + + These settings only affect your participation in on-chain polls + + + {dao && + balancesList.map(({ displayName, balance }, i) => ( + + + {displayName} + + + + {balance} + + {i === 2 ? ( + + + + Unstake + + + ) : null} + + + ))} + ) } - -export const UserBalancesBox: React.FC<{ daoId: string }> = ({ daoId }) => { - return ( - - - - ) -} diff --git a/src/modules/explorer/components/UsersTable.tsx b/src/modules/explorer/components/UsersTable.tsx index 797cc1f6..2dc56f43 100644 --- a/src/modules/explorer/components/UsersTable.tsx +++ b/src/modules/explorer/components/UsersTable.tsx @@ -1,30 +1,14 @@ import React from "react" -import { - Table, - TableBody, - TableCell, - TableHead, - TableRow, - styled, - Grid, - Typography, - useTheme, - useMediaQuery -} from "@material-ui/core" +import { TableCell, TableHead, TableRow, styled, Grid, Typography, useTheme, useMediaQuery } from "@material-ui/core" import dayjs from "dayjs" -import { UserBadge } from "modules/explorer/components/UserBadge" import { Blockie } from "modules/common/Blockie" import { CopyButton } from "./CopyButton" import { toShortAddress } from "services/contracts/utils" -import { formatNumber } from "../utils/FormatNumber" -import BigNumber from "bignumber.js" import numbro from "numbro" const localizedFormat = require("dayjs/plugin/localizedFormat") dayjs.extend(localizedFormat) -const titles = ["Rank", "Votes", "Available Staked", "Total Staked", "Proposals Voted"] as const - interface RowData { address: string votes: string @@ -33,36 +17,6 @@ interface RowData { proposalsVoted: string } -const OverflowCell = styled(TableCell)({ - whiteSpace: "nowrap", - overflow: "hidden", - textOverflow: "ellipsis", - maxWidth: 300 -}) - -const StyledTableHead = styled(TableHead)({ - minHeight: 34 -}) - -const StyledTableRow = styled(TableRow)({ - borderBottom: ".6px solid rgba(125,140,139, 0.2)" -}) - -const MobileTableRow = styled(Grid)({ - padding: "30px", - borderBottom: "0.3px solid rgba(125,140,139, 0.2)" -}) - -const TableText = styled(Typography)({ - fontSize: "16px", - fontWeight: 500, - - ["@media (max-width:1155px)"]: { - fontSize: "15px", - whiteSpace: "nowrap" - } -}) - const Title = styled(Typography)({ fontSize: 20 }) diff --git a/src/modules/explorer/pages/Config/components/DAOInfoTable.tsx b/src/modules/explorer/pages/Config/components/DAOInfoTable.tsx index 2f3f7b07..dd25a41e 100644 --- a/src/modules/explorer/pages/Config/components/DAOInfoTable.tsx +++ b/src/modules/explorer/pages/Config/components/DAOInfoTable.tsx @@ -127,8 +127,8 @@ export const DaoInfoTables: React.FC = () => { - - Proposal & Voting Settings + + Proposal & Voting Settings {dao ? ( @@ -221,8 +221,8 @@ export const DaoInfoTables: React.FC = () => {
- - Quorum Settings + + Quorum Settings {dao ? ( diff --git a/src/modules/explorer/pages/DAO/index.tsx b/src/modules/explorer/pages/DAO/index.tsx index 6933125d..2ec151a9 100644 --- a/src/modules/explorer/pages/DAO/index.tsx +++ b/src/modules/explorer/pages/DAO/index.tsx @@ -16,7 +16,7 @@ import { SmallButton } from "../../../common/SmallButton" import { usePolls } from "modules/lite/explorer/hooks/usePolls" import dayjs from "dayjs" import { DaoSettingModal } from "./components/Settings" -import { Visibility } from "@material-ui/icons" +import SettingsIcon from "@mui/icons-material/Settings" export const StyledAvatar = styled(Avatar)({ height: 50, @@ -61,8 +61,9 @@ const ViewSettings = styled(Grid)({ } }) -const SubtitleText = styled(Typography)({ +const SubtitleText = styled(Typography)(({ theme }) => ({ fontSize: 18, + color: theme.palette.primary.light, width: "875px", fontWeight: 300, maxHeight: "200px", @@ -80,7 +81,7 @@ const SubtitleText = styled(Typography)({ width: "100%", margin: "-15px auto 0 auto" } -}) +})) export const DAO: React.FC = () => { const daoId = useDAOID() @@ -125,7 +126,7 @@ export const DAO: React.FC = () => { setOpenDialog(true)}> - + View Settings @@ -135,15 +136,15 @@ export const DAO: React.FC = () => { - {description} + {description} - + {/* - + */} ) } diff --git a/src/modules/explorer/pages/DAOList/components/DAOItem.tsx b/src/modules/explorer/pages/DAOList/components/DAOItem.tsx index a6ba130b..b086ad52 100644 --- a/src/modules/explorer/pages/DAOList/components/DAOItem.tsx +++ b/src/modules/explorer/pages/DAOList/components/DAOItem.tsx @@ -2,10 +2,6 @@ import { styled, Grid, Theme, Typography, Link, useTheme, useMediaQuery } from " import React from "react" import { EnvKey, getEnv } from "services/config" import ReactHtmlParser from "react-html-parser" -import { useProposals } from "services/services/dao/hooks/useProposals" -import { ProposalStatus } from "services/services/dao/mappers/proposal/types" -import { usePolls } from "modules/lite/explorer/hooks/usePolls" -import dayjs from "dayjs" import { formatNumber } from "modules/explorer/utils/FormatNumber" import BigNumber from "bignumber.js" @@ -29,6 +25,12 @@ const Container = styled(Grid)(({ theme }: { theme: Theme }) => ({ minWidth: "inherit" }, + ["@media only screen and (max-device-width: 768px)"]: { + maxWidth: "86vw", + padding: "17px 24px", + minWidth: "320px" + }, + "&:hover": { background: theme.palette.secondary.dark, scale: 1.01, @@ -46,7 +48,6 @@ const SymbolText = styled(Typography)(({ theme }: { theme: Theme }) => ({ color: "#bfc5ca", lineHeight: "normal", marginTop: 8, - marginLeft: "12%", [theme.breakpoints.down("md")]: { fontSize: 18 @@ -88,12 +89,6 @@ const DescriptionText = styled(Typography)({ "maxHeight": 60 }) -const ItemText = styled(Typography)({ - fontWeight: 600, - fontSize: 16, - whiteSpace: "pre" -}) - const ItemTextSmall = styled(Typography)({ fontWeight: 600, fontSize: 16 @@ -112,7 +107,7 @@ const Badge = styled(Grid)(({ theme, dao_type }: { theme: Theme; dao_type: strin "& > div": { height: "100%" }, - "fontFamily": "Roboto Mono", + "fontFamily": "Roboto Flex", "fontWeight": 500 })) @@ -153,29 +148,16 @@ export const DAOItem: React.FC<{ {ReactHtmlParser(dao.description)} - {!isExtraSmall ? ( - - - DAO {"\n"}Token - {dao?.symbol?.toUpperCase()} - - - Voting {"\n"}Addresses{" "} - {formatNumber(new BigNumber(dao.votingAddressesCount))} - + + + DAO {"\n"}Token + {dao?.symbol?.toUpperCase()} - ) : ( - - - DAO {"\n"}Token - {dao?.symbol?.toUpperCase()} - - - Voting Addresses - {formatNumber(new BigNumber(dao.votingAddressesCount))} - + + Voting Addresses + {formatNumber(new BigNumber(dao.votingAddressesCount))} - )} + ) diff --git a/src/modules/explorer/pages/DAOList/index.tsx b/src/modules/explorer/pages/DAOList/index.tsx index f5755d1e..27d123ed 100644 --- a/src/modules/explorer/pages/DAOList/index.tsx +++ b/src/modules/explorer/pages/DAOList/index.tsx @@ -114,7 +114,7 @@ const TabsContainer = styled(Grid)(({ theme }) => ({ })) export const DAOList: React.FC = () => { - const { network, account, tezos } = useTezos() + const { network, account } = useTezos() const { data: daos, isLoading } = useAllDAOs(network) const theme = useTheme() @@ -215,12 +215,12 @@ export const DAOList: React.FC = () => { - + diff --git a/src/modules/explorer/pages/DAOList/styles.css b/src/modules/explorer/pages/DAOList/styles.css index d786ca8d..fc9da373 100644 --- a/src/modules/explorer/pages/DAOList/styles.css +++ b/src/modules/explorer/pages/DAOList/styles.css @@ -2,7 +2,7 @@ display: flex; list-style: none; outline: none; - font-family: "Roboto Mono"; + font-family: "Roboto Flex"; } .pagination > .active > a { background-color: rgba(129, 254, 183, 0.2); @@ -14,6 +14,16 @@ outline: none; cursor: pointer; border-radius: 50%; + margin-left: 8px; + margin-right: 8px; + font-family: "Roboto Flex"; + + @media (max-width:960px) { + font-size: 20px; + margin-right: 4px; + margin-left: 4px; + padding: 3px 6px; + } } .pagination > .active > a, .pagination > .active > span, diff --git a/src/modules/explorer/pages/NFTs/index.tsx b/src/modules/explorer/pages/NFTs/index.tsx index f8638256..742b8eeb 100644 --- a/src/modules/explorer/pages/NFTs/index.tsx +++ b/src/modules/explorer/pages/NFTs/index.tsx @@ -1,17 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { - Box, - Button, - CircularProgress, - Grid, - styled, - Tooltip, - Typography, - useMediaQuery, - useTheme -} from "@material-ui/core" +import { Box, CircularProgress, Grid, styled, Typography, useMediaQuery, useTheme } from "@material-ui/core" import { NFT as NFTModel } from "models/Token" -import { CopyAddress } from "modules/common/CopyAddress" import { NFT } from "modules/explorer/components/NFT" import { NFTDialog } from "modules/explorer/components/NFTDialog" import { ProposalFormContainer, ProposalFormDefaultValues } from "modules/explorer/components/ProposalForm" @@ -23,22 +12,21 @@ import { useTezos } from "services/beacon/hooks/useTezos" import { useDAONFTHoldings } from "services/contracts/baseDAO/hooks/useDAOHoldings" import { useDAO } from "services/services/dao/hooks/useDAO" import { ContentContainer } from "../../components/ContentContainer" -import { Hero } from "../../components/Hero" -import { HeroTitle } from "../../components/HeroTitle" import { useDAOID } from "../DAO/router" -import { InfoIcon } from "../../components/styled/InfoIcon" import { useIsProposalButtonDisabled } from "../../../../services/contracts/baseDAO/hooks/useCycleInfo" import { SmallButton } from "../../../common/SmallButton" -import { MainButton } from "../../../common/MainButton" import { parseUnits } from "services/contracts/utils" +import ReactPaginate from "react-paginate" +import "../DAOList/styles.css" -const Card = styled(ContentContainer)({ +const Card = styled(ContentContainer)(({ theme }) => ({ boxSizing: "border-box", padding: 30, width: 325, minHeight: 500, - cursor: "pointer" -}) + cursor: "pointer", + background: theme.palette.primary.main +})) const FullWidthContainer = styled(Grid)({ width: "100%" @@ -58,6 +46,11 @@ const NFTTitle = styled(Typography)({ fontWeight: 500 }) +const ProposalsFooter = styled(Grid)({ + padding: "16px 46px", + minHeight: 34 +}) + export const NFTs: React.FC = () => { const theme = useTheme() const daoId = useDAOID() @@ -101,14 +94,27 @@ export const NFTs: React.FC = () => { const onCloseTransfer = () => { setOpenTransfer(false) } - + const value = isMobileSmall ? 6 : 3 const shouldDisable = useIsProposalButtonDisabled(daoId) + const [currentPage, setCurrentPage] = useState(0) + const [offset, setOffset] = useState(0) + // Invoke when user click to request another page. + const handlePageClick = (event: { selected: number }) => { + if (nftHoldings) { + const newOffset = (event.selected * value) % nftHoldings.length + setOffset(newOffset) + setCurrentPage(event.selected) + } + } + + const pageCount = Math.ceil(nftHoldings ? nftHoldings.length / value : 0) + return ( <> - - + + {!nftHoldings ? ( <> @@ -117,14 +123,14 @@ export const NFTs: React.FC = () => { ) : ( <> - {nftHoldings.map((nft, i) => ( + {nftHoldings.slice(offset, offset + value).map((nft, i) => ( onClickNFT(nft)} > @@ -182,6 +188,29 @@ export const NFTs: React.FC = () => { ))} + {!(nftHoldings && nftHoldings.length > 0) ? ( + + + + No items + + + + ) : null} + + + )} diff --git a/src/modules/explorer/pages/ProposalDetails/components/CodeVisor.tsx b/src/modules/explorer/pages/ProposalDetails/components/CodeVisor.tsx index d0280c1b..88b21311 100644 --- a/src/modules/explorer/pages/ProposalDetails/components/CodeVisor.tsx +++ b/src/modules/explorer/pages/ProposalDetails/components/CodeVisor.tsx @@ -59,7 +59,7 @@ export const CodeVisor: React.FC = ({ open, title = "View Code", code, ha highlight={code => highlight(code, grammar, "javascript")} padding={10} style={{ - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 14, fontWeight: 400, outlineWidth: 0 diff --git a/src/modules/explorer/pages/ProposalDetails/components/QuorumThreshold.tsx b/src/modules/explorer/pages/ProposalDetails/components/QuorumThreshold.tsx index 8bcf2d00..ba77f2ff 100644 --- a/src/modules/explorer/pages/ProposalDetails/components/QuorumThreshold.tsx +++ b/src/modules/explorer/pages/ProposalDetails/components/QuorumThreshold.tsx @@ -22,7 +22,7 @@ const ProgressText = styled(Typography)(({ textColor }: { textColor: string }) = userSelect: "none", boxShadow: "none", background: "inherit", - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", justifyContent: "center", top: 0 })) diff --git a/src/modules/explorer/pages/ProposalDetails/index.tsx b/src/modules/explorer/pages/ProposalDetails/index.tsx index 67015739..bfd55891 100644 --- a/src/modules/explorer/pages/ProposalDetails/index.tsx +++ b/src/modules/explorer/pages/ProposalDetails/index.tsx @@ -73,7 +73,7 @@ const ProgressText = styled(Typography)(({ textColor }: { textColor: string }) = userSelect: "none", boxShadow: "none", background: "inherit", - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", justifyContent: "center", top: 0 })) @@ -463,7 +463,7 @@ export const ProposalDetails: React.FC = () => { padding={10} style={{ minHeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 14, fontWeight: 400, outlineWidth: 0 diff --git a/src/modules/explorer/pages/Proposals/index.tsx b/src/modules/explorer/pages/Proposals/index.tsx index 527c11c3..1ba71a59 100644 --- a/src/modules/explorer/pages/Proposals/index.tsx +++ b/src/modules/explorer/pages/Proposals/index.tsx @@ -1,5 +1,5 @@ -import React, { useState } from "react" -import { Box, Button, Grid, Paper, styled, Theme, Typography, useMediaQuery, useTheme } from "@material-ui/core" +import React, { useCallback, useState } from "react" +import { Button, Grid, Paper, styled, Theme, Typography, useMediaQuery, useTheme } from "@material-ui/core" import { useDAO } from "services/services/dao/hooks/useDAO" import { useProposals } from "services/services/dao/hooks/useProposals" @@ -10,27 +10,27 @@ import { ReactComponent as LinkInactive } from "assets/img/link_inactive.svg" import { ReactComponent as UnlinkActive } from "assets/img/unlink_active.svg" import { ReactComponent as UnlinkInactive } from "assets/img/unlink_inactive.svg" -import { ProposalStatus } from "services/services/dao/mappers/proposal/types" - import { ContentContainer } from "../../components/ContentContainer" -import { AllProposalsList } from "modules/explorer/components/AllProposalsList" import { SmallButton } from "modules/common/SmallButton" import { ProposalActionsDialog } from "modules/explorer/components/ProposalActionsDialog" -import { useTimeLeftInCycle } from "modules/explorer/hooks/useTimeLeftInCycle" - -import { useIsProposalButtonDisabled } from "services/contracts/baseDAO/hooks/useCycleInfo" -import { ProposalList } from "modules/lite/explorer/components/ProposalList" -import { usePolls } from "modules/lite/explorer/hooks/usePolls" -import dayjs from "dayjs" import { TabPanel } from "modules/explorer/components/TabPanel" +import { usePolls } from "modules/lite/explorer/hooks/usePolls" +import { ProposalsList } from "modules/explorer/components/ProposalsList" +import { useFlush } from "services/contracts/baseDAO/hooks/useFlush" +import { useDropAllExpired } from "services/contracts/baseDAO/hooks/useDropAllExpired" +import { ProposalStatus } from "services/services/dao/mappers/proposal/types" +import NewReleasesIcon from "@mui/icons-material/NewReleases" +import DeleteIcon from "@mui/icons-material/Delete" -const TabsContainer = styled(Grid)(({ theme }) => ({ +const TabsContainer = styled(Grid)({ borderRadius: 8, gap: 16 -})) +}) const HeroContainer = styled(ContentContainer)(({ theme }) => ({ - padding: "38px 48px 38px 48px", + background: "inherit !important", + paddingTop: 0, + padding: "0px", display: "inline-flex", alignItems: "center", [theme.breakpoints.down("xs")]: { @@ -57,10 +57,10 @@ const StyledTab = styled(Button)(({ theme, isSelected }: { theme: Theme; isSelec "paddingTop": 0, "paddingBottom": 0, "borderRadius": 8, + "backgroundColor": isSelected ? "#2B3036" : "inherit", "color": isSelected ? theme.palette.secondary.main : "#fff", - "backgroundColor": isSelected ? "rgba(129, 254, 183, 0.20)" : "inherit", "&:hover": { - backgroundColor: isSelected ? "rgba(129, 254, 183, 0.20)" : theme.palette.secondary.dark, + backgroundColor: isSelected ? "#24282D" : theme.palette.secondary.dark, borderRadius: 8, borderTopLeftRadius: "8px !important", borderTopRightRadius: "8px !important", @@ -69,59 +69,30 @@ const StyledTab = styled(Button)(({ theme, isSelected }: { theme: Theme; isSelec } })) -export const DropButton = styled(Button)({ - verticalAlign: "text-bottom", - fontSize: "16px" -}) - -const DAOItemGrid = styled(Grid)({ - gap: "30px", - marginBottom: 40, - justifyContent: "space-between", - ["@media (max-width: 1155px)"]: { - gap: "32px" - }, - - ["@media (max-width:960px)"]: { - gap: "20px" - }, - - ["@media (max-width:830px)"]: { - width: "86vw", - gap: "20px" - } -}) - -const Item = styled(Paper)(({ theme }) => ({ - backgroundColor: theme.palette.primary.main, +const TabsBox = styled(Grid)(({ theme }) => ({ + background: "#24282D", borderRadius: 8, - color: theme.palette.text.primary, - height: 84, - display: "flex", - padding: "33px 40px 30px 40px", - flexDirection: "column", - gap: 8 + padding: "40px 56px", + minHeight: 300, + width: "100%", + [theme.breakpoints.down("sm")]: { + padding: "30px 36px" + } })) -const ItemContent = styled(Grid)({ - gap: 8 +const ProposalsFooter = styled(Grid)({ + padding: "16px 46px", + minHeight: 34 }) -const ItemTitle = styled(Typography)(({ theme }) => ({ - fontSize: 18, - fontWeight: 600, - [theme.breakpoints.down("md")]: { - fontSize: 15 - } -})) +const NotContainedButton = styled(Button)({ + fontSize: "18px" +}) -const ItemValue = styled(Typography)(({ theme }) => ({ - fontSize: 32, - fontWeight: 300, - [theme.breakpoints.down("sm")]: { - fontSize: 28 - } -})) +export const DropButton = styled(Button)({ + verticalAlign: "text-bottom", + fontSize: "16px" +}) export const Proposals: React.FC = () => { const daoId = useDAOID() @@ -129,48 +100,41 @@ export const Proposals: React.FC = () => { const [selectedTab, setSelectedTab] = React.useState(0) const { data: proposals } = useProposals(daoId) - const { data: activeProposals } = useProposals(daoId, ProposalStatus.ACTIVE) const theme = useTheme() const isMobileSmall = useMediaQuery(theme.breakpoints.down("xs")) const [openDialog, setOpenDialog] = useState(false) - // const { mutate } = useFlush() - // const { mutate: dropAllExpired } = useDropAllExpired() + const { mutate } = useFlush() + const { mutate: dropAllExpired } = useDropAllExpired() + const { data: expiredProposals } = useProposals(daoId, ProposalStatus.EXPIRED) const { data: executableProposals } = useProposals(daoId, ProposalStatus.EXECUTABLE) - // const { data: expiredProposals } = useProposals(daoId, ProposalStatus.EXPIRED) - const { hours, minutes, days } = useTimeLeftInCycle() - - const shouldDisable = useIsProposalButtonDisabled(daoId) const handleCloseModal = () => { setOpenDialog(false) } - // const onFlush = useCallback(async () => { - // if (executableProposals && expiredProposals && executableProposals.length && data) { - // mutate({ - // dao: data, - // numOfProposalsToFlush: executableProposals.length, - // expiredProposalIds: expiredProposals.map(p => p.id) - // }) - // return - // } - // }, [data, mutate, executableProposals, expiredProposals]) - - // const onDropAllExpired = useCallback(async () => { - // if (expiredProposals && expiredProposals.length && data) { - // dropAllExpired({ - // dao: data, - // expiredProposalIds: expiredProposals.map(p => p.id) - // }) - // return - // } - // }, [data, dropAllExpired, expiredProposals]) + const onFlush = useCallback(async () => { + if (executableProposals && expiredProposals && executableProposals.length && data) { + mutate({ + dao: data, + numOfProposalsToFlush: executableProposals.length, + expiredProposalIds: expiredProposals.map(p => p.id) + }) + return + } + }, [data, mutate, executableProposals, expiredProposals]) + + const onDropAllExpired = useCallback(async () => { + if (expiredProposals && expiredProposals.length && data) { + dropAllExpired({ + dao: data, + expiredProposalIds: expiredProposals.map(p => p.id) + }) + return + } + }, [data, dropAllExpired, expiredProposals]) const { data: polls } = usePolls(data?.liteDAOData?._id) - const id = data?.liteDAOData?._id - - const activeLiteProposals = polls?.filter(p => Number(p.endTime) > dayjs().valueOf()) const handleChangeTab = (newValue: number) => { setSelectedTab(newValue) @@ -179,7 +143,7 @@ export const Proposals: React.FC = () => { return ( <> - + { alignItems={isMobileSmall ? "baseline" : "center"} direction={isMobileSmall ? "column" : "row"} > - + Proposals { direction={isMobileSmall ? "column" : "row"} xs={isMobileSmall ? undefined : true} > + + + Execute + + + + Drop Expired + setOpenDialog(true)}> New Proposal {/* - - Execute - */} {/* - - Drop Expired - + */} + + + Create, view, and vote on On-Chain and Off-Chain proposals + + - - - - - - : } - variant="contained" - disableElevation={true} - onClick={() => handleChangeTab(0)} - isSelected={selectedTab === 0} - > - On-Chain - - - - : } - disableElevation={true} - variant="contained" - onClick={() => handleChangeTab(1)} - isSelected={selectedTab === 1} - > - Off-Chain - - - - + + + + + : } + variant="contained" + disableElevation={true} + onClick={() => handleChangeTab(0)} + isSelected={selectedTab === 0} + > + On-Chain + + + + : } + disableElevation={true} + variant="contained" + onClick={() => handleChangeTab(1)} + isSelected={selectedTab === 1} + > + Off-Chain + + + - - - - - - - - - Cycle Status - - - {shouldDisable ? "Voting" : "Creating"} - - - - - - - Current Cycle - - - {cycleInfo?.currentCycle} - - - - - - - Time Left in Cycle - - - - {" "} - {days}d {hours}h {minutes}m{" "} - - - - - - - - Voting Addresses - - - {data?.data.ledger.length || "-"} - - + + {proposals && cycleInfo && ( + + )} + {!(proposals && proposals.length > 0) ? ( + + + + No items + - - - - Active Proposals - - - {Number(activeProposals?.length)} - - - - - - - Executable Proposals - - - {executableProposals?.length} - - - - - - - - {data && cycleInfo && proposals && ( - - )} + + ) : null} + + - - - - - - - - Active Proposals - - - - {activeLiteProposals ? activeLiteProposals?.length : 0} - - - - - - - - Total Addresses - - - {data?.liteDAOData?.votingAddressesCount} - - - - - - - Delegates - - - {0} - - - + + {proposals && cycleInfo && ( + + )} + {!(polls && polls.length > 0) ? ( + + + + No items + - - - - {polls && polls.length > 0 ? : null} + + ) : null} + - + - {proposals?.length === 0 && polls?.length === 0 ? ( - - 0 proposals found - - ) : null} ) diff --git a/src/modules/explorer/pages/Treasury/components/BalancesTable.tsx b/src/modules/explorer/pages/Treasury/components/BalancesTable.tsx index 0b1ae661..548a779f 100644 --- a/src/modules/explorer/pages/Treasury/components/BalancesTable.tsx +++ b/src/modules/explorer/pages/Treasury/components/BalancesTable.tsx @@ -10,6 +10,8 @@ import { useIsProposalButtonDisabled } from "../../../../../services/contracts/b import { SmallButton } from "../../../../common/SmallButton" import { toShortAddress } from "services/contracts/utils" import { CopyButton } from "modules/common/CopyButton" +import ReactPaginate from "react-paginate" +import "../../DAOList/styles.css" const TokenSymbol = styled(Typography)(({ theme }) => ({ color: theme.palette.secondary.main, @@ -104,9 +106,22 @@ const BalancesList: React.FC = ({ shouldDisable, isMobileSmall }) => { + const [currentPage, setCurrentPage] = useState(0) + const [offset, setOffset] = useState(0) + const value = isMobileSmall ? 6 : 2 + // Invoke when user click to request another page. + const handlePageClick = (event: { selected: number }) => { + if (rows) { + const newOffset = (event.selected * value) % rows.length + setOffset(newOffset) + setCurrentPage(event.selected) + } + } + + const pageCount = Math.ceil(rows ? rows.length / value : 0) return ( - + XTZ @@ -129,8 +144,8 @@ const BalancesList: React.FC = ({ - {rows.map((row, i) => ( - + {rows.slice(offset, offset + value).map((row, i) => ( + {row.symbol} @@ -156,6 +171,20 @@ const BalancesList: React.FC = ({ ))} + + + ) } diff --git a/src/modules/explorer/pages/Treasury/components/TransfersTable.tsx b/src/modules/explorer/pages/Treasury/components/TransfersTable.tsx index 9cbb3a2a..c1cb074e 100644 --- a/src/modules/explorer/pages/Treasury/components/TransfersTable.tsx +++ b/src/modules/explorer/pages/Treasury/components/TransfersTable.tsx @@ -1,5 +1,5 @@ import dayjs from "dayjs" -import React, { useMemo } from "react" +import React, { useMemo, useState } from "react" import { Grid, Link, @@ -13,37 +13,36 @@ import { useMediaQuery, useTheme } from "@material-ui/core" -import hexToRgba from "hex-to-rgba" import { TransferWithBN } from "services/contracts/baseDAO/hooks/useTransfers" import { useTezos } from "services/beacon/hooks/useTezos" import { Network } from "services/beacon" import { ContentContainer } from "modules/explorer/components/ContentContainer" import { networkNameMap } from "services/bakingBad" -import { Blockie } from "modules/common/Blockie" import { toShortAddress } from "services/contracts/utils" +import { ReactComponent as BulletIcon } from "assets/img/bullet.svg" +import { CopyButton } from "modules/common/CopyButton" +import ReactPaginate from "react-paginate" +import "../../DAOList/styles.css" const localizedFormat = require("dayjs/plugin/localizedFormat") dayjs.extend(localizedFormat) -const TokenSymbol = styled(Typography)(({ theme }) => ({ - background: hexToRgba(theme.palette.secondary.main, 0.11), - borderRadius: 4, - color: theme.palette.secondary.main, - padding: "1px 8px", - boxSizing: "border-box", - width: "min-content" -})) - const createData = (transfer: TransferWithBN) => { return { token: transfer.name, - date: dayjs(transfer.date).format("ll"), + date: dayjs(transfer.date).format("L"), address: transfer.recipient, amount: transfer.amount.dp(10, 1).toString(), hash: transfer.hash } } +const StyledBullet = styled(BulletIcon)({ + background: "#1DB", + borderRadius: 50, + marginRight: 6 +}) + const TableContainer = styled(ContentContainer)({ width: "100%" }) @@ -53,6 +52,19 @@ const RecipientText = styled(Typography)({ marginTop: 8 }) +const ProposalsFooter = styled(Grid)({ + padding: "16px 46px", + minHeight: 34 +}) + +const ProposalsFooterMobile = styled(Grid)({ + padding: "16px 46px", + minHeight: 34, + backgroundColor: "#2a2e32", + borderBottomLeftRadius: 8, + borderBottomRightRadius: 8 +}) + interface RowData { token: string date: string @@ -61,18 +73,18 @@ interface RowData { hash: string } -const Titles = ["Transfer History", "Date", "Recipient", "Amount"] +const Titles = ["Token", "Date", "Recipient", "Amount"] const titleDataMatcher = (title: (typeof Titles)[number], rowData: RowData) => { switch (title) { - case "Transfer History": + case "Token": return rowData.token case "Date": return rowData.date case "Amount": return rowData.amount case "Recipient": - return rowData.address + return toShortAddress(rowData.address) case "Sender": return rowData.address } @@ -80,17 +92,39 @@ const titleDataMatcher = (title: (typeof Titles)[number], rowData: RowData) => { const MobileTableHeader = styled(Grid)({ width: "100%", padding: 20, - borderBottom: "0.3px solid #3D3D3D" + borderBottom: "0.3px solid #3D3D3D", + backgroundColor: "#383E43", + borderTopRightRadius: 8, + borderTopLeftRadius: 8 }) const MobileTableRow = styled(Grid)({ - padding: "30px", - borderBottom: "0.3px solid #3D3D3D" + "padding": "30px", + "borderTop": "1px solid #575757", + "&:last-child": { + borderBottomRightRadius: 8, + borderBottomLeftRadius: 8 + } }) //TODO: Should mobile table items also redirect to block explorer on click? -const MobileTransfersTable: React.FC<{ data: RowData[] }> = ({ data }) => { +const MobileTransfersTable: React.FC<{ data: RowData[]; network: Network }> = ({ data, network }) => { + const openTxInfo = (data: RowData) => { + window.open(`https://${network === "mainnet" ? "" : networkNameMap[network] + "."}tzkt.io/${data.hash}`) + } + + const [currentPage, setCurrentPage] = useState(0) + const [offset, setOffset] = useState(0) + // Invoke when user click to request another page. + const handlePageClick = (event: { selected: number }) => { + if (data) { + const newOffset = (event.selected * 5) % data.length + setOffset(newOffset) + setCurrentPage(event.selected) + } + } + const pageCount = Math.ceil(data ? data.length / 5 : 0) return ( @@ -98,14 +132,15 @@ const MobileTransfersTable: React.FC<{ data: RowData[] }> = ({ data }) => { Transfer History - {data.map((row, i) => ( + {data.slice(offset, offset + 5).map((row, i) => ( openTxInfo(row)} + style={i % 2 !== 1 ? { gap: 19, backgroundColor: "#2a2e32" } : { gap: 19, backgroundColor: "#383E43" }} > {Titles.map((title, j) => ( @@ -119,11 +154,45 @@ const MobileTransfersTable: React.FC<{ data: RowData[] }> = ({ data }) => { ))} ))} + {!(data && data.length > 0) ? ( + + + + No items + + + + ) : null} + + + ) } const DesktopTransfersTable: React.FC<{ data: RowData[]; network: Network }> = ({ data: rows, network }) => { + const [currentPage, setCurrentPage] = useState(0) + const [offset, setOffset] = useState(0) + // Invoke when user click to request another page. + const handlePageClick = (event: { selected: number }) => { + if (rows) { + const newOffset = (event.selected * 5) % rows.length + setOffset(newOffset) + setCurrentPage(event.selected) + } + } + const pageCount = Math.ceil(rows ? rows.length / 5 : 0) return ( <>
@@ -135,7 +204,7 @@ const DesktopTransfersTable: React.FC<{ data: RowData[]; network: Network }> = ( - {rows.map((row, i) => ( + {rows.slice(offset, offset + 5).map((row, i) => ( = ( target="_blank" > - {row.token} +
+ {row.token} +
{row.date} - {toShortAddress(row.address)} + {row.amount}
))} + {!(rows && rows.length > 0) ? ( + + + + No items + + + + ) : null}
+ + + ) } @@ -175,7 +269,11 @@ export const TransfersTable: React.FC<{ transfers: TransferWithBN[] }> = ({ tran return ( - {isSmall ? : } + {isSmall ? ( + + ) : ( + + )} ) } diff --git a/src/modules/explorer/pages/Treasury/index.tsx b/src/modules/explorer/pages/Treasury/index.tsx index 1e204170..6de16d97 100644 --- a/src/modules/explorer/pages/Treasury/index.tsx +++ b/src/modules/explorer/pages/Treasury/index.tsx @@ -1,4 +1,4 @@ -import { Button, Grid, Theme, Tooltip, useMediaQuery, useTheme } from "@material-ui/core" +import { Button, Grid, Theme, Tooltip, Typography, useMediaQuery, useTheme } from "@material-ui/core" import { CopyAddress } from "modules/common/CopyAddress" import { ProposalFormContainer } from "modules/explorer/components/ProposalForm" @@ -16,20 +16,72 @@ import { styled } from "@material-ui/core" import { MainButton } from "../../../common/MainButton" import { TabPanel } from "modules/explorer/components/TabPanel" import { NFTs } from "../NFTs" +import TollIcon from "@mui/icons-material/Toll" +import PaletteIcon from "@mui/icons-material/Palette" +import ReceiptIcon from "@mui/icons-material/Receipt" +import { SmallButton } from "modules/common/SmallButton" +import { ContentContainer } from "modules/explorer/components/ContentContainer" +import { CopyButton } from "modules/common/CopyButton" const ItemGrid = styled(Grid)({ width: "inherit" }) -const StyledTab = styled(Button)(({ theme, isSelected }: { theme: Theme; isSelected: boolean }) => ({ - "fontSize": 16, - "fontWeight": 400, - "color": isSelected ? theme.palette.primary.dark : "#fff", +const TabsBox = styled(Grid)(({ theme }) => ({ + background: "#24282D", + borderRadius: 8, + padding: "40px 56px", + minHeight: 300, + width: "100%", + [theme.breakpoints.down("sm")]: { + padding: "30px 36px" + } +})) - "backgroundColor": isSelected ? theme.palette.secondary.main : theme.palette.primary.main, +const TabsContainer = styled(Grid)({ + borderRadius: 8, + gap: 16 +}) + +const TitleText = styled(Typography)({ + fontSize: 36, + fontWeight: 500, + lineHeight: 0.9, + ["@media (max-width:1030px)"]: { + fontSize: 26 + } +}) + +const StyledTab = styled(Button)(({ theme, isSelected }: { theme: Theme; isSelected: boolean }) => ({ + "fontSize": 18, + "height": 40, + "fontWeight": 400, + "paddingLeft": 20, + "paddingRight": 20, + "paddingTop": 0, + "paddingBottom": 0, + "borderRadius": 8, + "backgroundColor": isSelected ? "#2B3036" : "inherit", + "color": isSelected ? theme.palette.secondary.main : "#fff", "&:hover": { - backgroundColor: isSelected ? theme.palette.secondary.main : theme.palette.secondary.dark + backgroundColor: isSelected ? "#24282D" : theme.palette.secondary.dark, + borderRadius: 8, + borderTopLeftRadius: "8px !important", + borderTopRightRadius: "8px !important", + borderBottomLeftRadius: "8px !important", + borderBottomRightRadius: "8px !important" + } +})) + +const HeroContainer = styled(ContentContainer)(({ theme }) => ({ + background: "inherit !important", + paddingTop: 0, + padding: "0px", + display: "inline-flex", + alignItems: "center", + [theme.breakpoints.down("xs")]: { + maxHeight: "fit-content" } })) @@ -55,110 +107,118 @@ export const Treasury: React.FC = () => { return ( <> - - - - Treasury - {dao && ( - - )} - - - - - + + + + + + Treasury + + + + {dao && ( + + + + )} + setOpenTransfer(true)} disabled={shouldDisable} > - New Transfer - + New Proposal + {shouldDisable && ( )} + + + Transfer tokens and NFTs, and view balances and transaction history{" "} + + - - - - - - - - handleChangeTab(0)} - isSelected={selectedTab === 0} - > - Tokens - - - - handleChangeTab(1)} - isSelected={selectedTab === 1} - > - NFTs - - + - - handleChangeTab(2)} - isSelected={selectedTab === 2} - > - History - - + + + + + } + variant="contained" + disableElevation={true} + onClick={() => handleChangeTab(0)} + isSelected={selectedTab === 0} + > + Tokens + - + + } + disableElevation={true} + variant="contained" + onClick={() => handleChangeTab(1)} + isSelected={selectedTab === 1} + > + NFTs + + + + } + disableElevation={true} + variant="contained" + onClick={() => handleChangeTab(2)} + isSelected={selectedTab === 2} + > + History + + + - - - - - + + + + - - - + + + - - - - + + + + + ({ minHeight: "178px", - padding: "46px 55px", - background: theme.palette.primary.main, boxSizing: "border-box", borderRadius: 8, boxShadow: "none", @@ -28,14 +26,14 @@ const DelegationBox = styled(Grid)(({ theme }: { theme: Theme }) => ({ })) const Subtitle = styled(Typography)({ - fontWeight: 200, - color: "#fff", - fontSize: 16 + fontWeight: 300, + color: "#bfc5ca", + fontSize: 18 }) const Balance = styled(Typography)({ - fontSize: 24, - fontWeight: 200 + fontSize: 32, + fontWeight: 300 }) const CustomCopyButton = withStyles({ @@ -47,6 +45,24 @@ const CustomCopyButton = withStyles({ disabled: {} })(Grid) +const OffChainBox = styled(Grid)(({ theme }) => ({ + display: "flex", + padding: "36px 48px 33px 48px", + flexDirection: "column", + justifyContent: "center", + alignItems: "flex-start", + gap: 24, + flexShrink: 0, + borderRadius: 8, + background: theme.palette.primary.main +})) + +const DelegationText = styled(Grid)({ + fontSize: 24, + fontWeight: 300, + color: "#fff" +}) + export const matchTextToStatus = (value: DelegationsType | undefined) => { switch (value) { case DelegationsType.NOT_DELEGATING: @@ -97,65 +113,74 @@ export const Delegation: React.FC<{ daoId: string }> = ({ daoId }) => { }, [delegatedTo]) return ( - + Off-chain Delegation - These settings only affect your participation in off-chain polls + These settings only affect your participation in off-chain polls - {dao && voteWeight && ( - - Voting Weight - - {!voteWeight || voteWeight.eq(new BigNumber(0)) ? ( - "-" - ) : ( - <>{`${parseUnits(voteWeight, dao.data.token.decimals).toString()} ${dao.data.token.symbol}`} - )} - - - )} - - - - Delegation Status - - + {dao && voteWeight && ( + - setOpenModal(true)} /> - setOpenModal(true)}> - Edit - + Voting Weight + + {!voteWeight || voteWeight.eq(new BigNumber(0)) ? ( + "-" + ) : ( + <>{`${parseUnits(voteWeight, dao.data.token.decimals).toString()} ${dao.data.token.symbol}`} + )} + + + )} + + + + Delegation Status + + + setOpenModal(true)} /> + setOpenModal(true)}> + Change Status + + - - - {isLoading || loadingRes ? ( - - ) : ( - <> - - {matchTextToStatus(delegationStatus)} - {delegationStatus === DelegationsType.NOT_DELEGATING ? null : ( - - )} - {delegationStatus === DelegationsType.DELEGATING ? delegatedTo : null} - {delegationStatus === DelegationsType.NOT_DELEGATING ? null : ( - - - - )} - - - )} - + + {isLoading || loadingRes ? ( + + ) : ( + <> + + {matchTextToStatus(delegationStatus)} + {delegationStatus === DelegationsType.NOT_DELEGATING ? null : ( + + )} + {delegationStatus === DelegationsType.DELEGATING ? delegatedTo : null} + {delegationStatus === DelegationsType.NOT_DELEGATING ? null : ( + + + + )} + + + )} + + ({ + padding: "37px 42px", + background: theme.palette.primary.main, + borderRadius: 8 +})) + +const ProposalTitle = styled(Typography)({ + fontWeight: 600, + fontSize: 18 +}) + +const DescriptionText = styled(Typography)({ + color: "#BFC5CA", + fontSize: 16, + fontWeight: 300 +}) + +export const TransactionItem: React.FC<{ item: TransferWithBN }> = ({ item, children }) => { + const theme = useTheme() + const isMobileSmall = useMediaQuery(theme.breakpoints.down("sm")) + + return ( + + + + {item.type === "Withdrawal" ? : } + + + + {item.type} + + + {item.type === "Withdrawal" ? "To " : "From "} {toShortAddress(item.recipient)}   {" • "} +   {dayjs(item.date).format("LL")} + + + + + {" "} + {item.type === "Withdrawal" ? "- " : "+ "} {formatNumber(new BigNumber(item.amount))} {item.token?.symbol} + + + + {children} + + ) +} diff --git a/src/modules/explorer/pages/User/components/UserMovements.tsx b/src/modules/explorer/pages/User/components/UserMovements.tsx new file mode 100644 index 00000000..8cb6a02e --- /dev/null +++ b/src/modules/explorer/pages/User/components/UserMovements.tsx @@ -0,0 +1,589 @@ +import React, { useEffect, useMemo, useState } from "react" +import { Button, Grid, Theme, Typography, styled } from "@material-ui/core" +import { ReactComponent as VotingInactiveIcon } from "assets/logos/voting_inactive.svg" +import { ReactComponent as VotingActiveIcon } from "assets/logos/voting_active.svg" +import { ReactComponent as VotesActiveIcon } from "assets/logos/votes_active.svg" +import { ReactComponent as VotesInactiveIcon } from "assets/logos/votes_inactive.svg" +import { ReactComponent as TransactionsInactiveIcon } from "assets/logos/transactions_inactive.svg" +import { ReactComponent as TransactionsActiveIcon } from "assets/logos/transactions_active.svg" +import { TabPanel } from "modules/explorer/components/TabPanel" +import { ProposalsList } from "../../../components/ProposalsList" +import { CycleInfo } from "services/contracts/baseDAO" +import { Proposal } from "services/services/dao/mappers/proposal/types" +import { Poll } from "models/Polls" +import { TransferWithBN, useTransfers } from "services/contracts/baseDAO/hooks/useTransfers" +import { TransactionItem } from "./TransactionItem" +import { useTezos } from "services/beacon/hooks/useTezos" +import ReactPaginate from "react-paginate" +import "../../DAOList/styles.css" + +const TabsContainer = styled(Grid)(({ theme }) => ({ + borderRadius: 8, + gap: 16 +})) + +const ProposalsFooter = styled(Grid)({ + padding: "16px 46px", + minHeight: 34 +}) + +const TransactionsFooter = styled(Grid)({ + padding: "16px 46px", + minHeight: 34 +}) + +const VotedText = styled(Typography)({ + fontSize: 18 +}) + +const StatusText = styled(Typography)({ + textTransform: "uppercase", + marginLeft: 10, + fontSize: 18, + marginRight: 30 +}) + +const StyledTab = styled(Button)(({ theme, isSelected }: { theme: Theme; isSelected: boolean }) => ({ + "fontSize": 18, + "height": 40, + "fontWeight": 400, + "paddingLeft": 20, + "paddingRight": 20, + "paddingTop": 0, + "paddingBottom": 0, + "borderRadius": 8, + "color": isSelected ? theme.palette.secondary.main : "#fff", + "backgroundColor": isSelected ? "#24282D" : "inherit", + "&:hover": { + backgroundColor: isSelected ? "#24282D" : theme.palette.secondary.dark, + borderRadius: 8, + borderTopLeftRadius: "8px !important", + borderTopRightRadius: "8px !important", + borderBottomLeftRadius: "8px !important", + borderBottomRightRadius: "8px !important" + } +})) + +const StyledTabInner = styled(Button)(({ theme, isSelected }: { theme: Theme; isSelected: boolean }) => ({ + "fontSize": 16, + "height": 32, + "fontWeight": 500, + "paddingLeft": 20, + "paddingRight": 20, + "paddingTop": 0, + "paddingBottom": 0, + "borderRadius": 50, + "color": isSelected ? theme.palette.secondary.main : "#bfc5ca", + "backgroundColor": isSelected ? "#24282D" : "#2F3438", + "&:hover": { + backgroundColor: isSelected ? "#24282D" : theme.palette.secondary.dark, + borderRadius: 50, + borderTopLeftRadius: "50px !important", + borderTopRightRadius: "50px !important", + borderBottomLeftRadius: "50px !important", + borderBottomRightRadius: "50px !important" + } +})) + +export const UserMovements: React.FC<{ + daoId: string + proposalsCreated: Proposal[] + cycleInfo: CycleInfo | undefined + pollsPosted: Poll[] | undefined + proposalsVoted: Proposal[] | undefined + pollsVoted: any + getVoteDecision: (proposal: any) => boolean +}> = ({ proposalsCreated, cycleInfo, pollsPosted, proposalsVoted, getVoteDecision, daoId, pollsVoted }) => { + const [selectedTab, setSelectedTab] = React.useState(0) + const [selectedTabProposals, setSelectedTabProposals] = React.useState(0) + const [selectedTabVotes, setSelectedTabVotes] = React.useState(0) + const [selectedTabTransactions, setSelectedTabTransactions] = React.useState(0) + const [filteredTransactions, setFilteredTransactions] = React.useState() + const { account } = useTezos() + + const useUserTransfers = (): TransferWithBN[] | undefined => { + const { data: transfers } = useTransfers(daoId) + + return useMemo(() => { + const filteredTransfers = transfers?.filter(item => item.recipient === account || item.sender === account) + return filteredTransfers + }, [transfers]) + } + + const transfers = useUserTransfers() + + useEffect(() => { + setFilteredTransactions(transfers) + setPageCount(Math.ceil(transfers ? transfers.length / 2 : 0)) + }, [transfers]) + + const [currentPage, setCurrentPage] = useState(0) + const [offset, setOffset] = useState(0) + const count = Math.ceil(transfers ? transfers.length / 2 : 0) + + const [pageCount, setPageCount] = React.useState(count) + + const handleChangeTab = (newValue: number) => { + setSelectedTab(newValue) + } + + const handleChangeTabProposals = (newValue: number) => { + setSelectedTabProposals(newValue) + } + + const handleChangeTabVotes = (newValue: number) => { + setSelectedTabVotes(newValue) + } + + const handleChangeTabTransactions = (newValue: number) => { + if (newValue === 0) { + setFilteredTransactions(transfers) + setPageCount(Math.ceil(transfers ? transfers.length / 2 : 0)) + } + if (newValue === 1) { + const newArray = transfers?.filter(item => item.type === "Withdrawal") + setFilteredTransactions(newArray) + setPageCount(Math.ceil(newArray ? newArray.length / 2 : 1)) + } + if (newValue === 2) { + const newArray = transfers?.filter(item => item.type === "Deposit") + setFilteredTransactions(newArray) + setPageCount(Math.ceil(newArray ? newArray.length / 2 : 1)) + } + setSelectedTabTransactions(newValue) + } + + // Invoke when user click to request another page. + const handlePageClick = (event: { selected: number }) => { + if (transfers) { + const newOffset = (event.selected * 2) % (filteredTransactions ? filteredTransactions.length : 1) + setOffset(newOffset) + setCurrentPage(event.selected) + } + } + + return ( + + + + + + : } + variant="contained" + disableElevation={true} + onClick={() => handleChangeTab(0)} + isSelected={selectedTab === 0} + > + Proposals + + + + : } + disableElevation={true} + variant="contained" + onClick={() => handleChangeTab(1)} + isSelected={selectedTab === 1} + > + Votes + + + + + : } + disableElevation={true} + variant="contained" + onClick={() => handleChangeTab(2)} + isSelected={selectedTab === 2} + > + Transactions + + + + + + + + + + + + + handleChangeTabProposals(0)} + isSelected={selectedTabProposals === 0} + > + All + + + + handleChangeTabProposals(1)} + isSelected={selectedTabProposals === 1} + > + On-Chain + + + + + handleChangeTabProposals(2)} + isSelected={selectedTabProposals === 2} + > + Off-Chain + + + + + + + + + {proposalsCreated && cycleInfo && ( + + )} + {!(proposalsCreated && proposalsCreated.length > 0) && !(pollsPosted && pollsPosted.length > 0) ? ( + + + + No items + + + + ) : null} + + + + + {proposalsCreated && cycleInfo && ( + + )} + {!(proposalsCreated && proposalsCreated.length > 0) ? ( + + + + No items + + + + ) : null} + + + + + {pollsPosted && cycleInfo && ( + + )} + {!(pollsPosted && pollsPosted.length > 0) ? ( + + + + No items + + + + ) : null} + + + + + {/* TAB VOTES CONTENT */} + + + + + + handleChangeTabVotes(0)} + isSelected={selectedTabVotes === 0} + > + All + + + + handleChangeTabVotes(1)} + isSelected={selectedTabVotes === 1} + > + On-Chain + + + + + handleChangeTabVotes(2)} + isSelected={selectedTabVotes === 2} + > + Off-Chain + + + + + + + + + {proposalsVoted && cycleInfo && ( + { + const voteDecision = getVoteDecision(proposal) + return ( + + + Voted + + + + {voteDecision ? "YES" : "NO"} + + + + ) + }} + liteProposals={pollsVoted} + /> + )} + {!(proposalsVoted && proposalsVoted.length > 0) && !(pollsVoted && pollsVoted.length > 0) ? ( + + + + No items + + + + ) : null} + + + + + {proposalsVoted && cycleInfo && ( + { + const voteDecision = getVoteDecision(proposal) + return ( + + + Voted + + + + {voteDecision ? "YES" : "NO"} + + + + ) + }} + liteProposals={[]} + /> + )} + {!(proposalsVoted && proposalsVoted.length > 0) ? ( + + + + No items + + + + ) : null} + + + + + {pollsPosted && cycleInfo && ( + { + const voteDecision = getVoteDecision(proposal) + return ( + + + Voted + + + + {voteDecision ? "YES" : "NO"} + + + + ) + }} + liteProposals={pollsVoted} + /> + )} + {!(pollsPosted && pollsPosted.length > 0) ? ( + + + + No items + + + + ) : null} + + + + + {/* TAB TRANSACTIONS CONTENT */} + + + + + + handleChangeTabTransactions(0)} + isSelected={selectedTabTransactions === 0} + > + All + + + + handleChangeTabTransactions(1)} + isSelected={selectedTabTransactions === 1} + > + Withdrawals + + + + + handleChangeTabTransactions(2)} + isSelected={selectedTabTransactions === 2} + > + Deposits + + + + + + + + {transfers && transfers.length > 0 ? ( + + {transfers && + transfers + .slice(offset, offset + 2) + .map((transfer, i) => )} + + + + + ) : ( + + + + No items + + + + )} + + + {transfers && transfers.length > 0 ? ( + + {filteredTransactions && + filteredTransactions + .slice(offset, offset + 2) + .map((transfer, i) => )} + + + + + ) : ( + + + + No items + + + + )} + + + {transfers && transfers.length > 0 ? ( + + {filteredTransactions && + filteredTransactions + .slice(offset, offset + 2) + .map((transfer, i) => )} + + + + + ) : ( + + + + No items + + + + )} + + + + + ) +} diff --git a/src/modules/explorer/pages/User/index.tsx b/src/modules/explorer/pages/User/index.tsx index 3385afd5..7235a40e 100644 --- a/src/modules/explorer/pages/User/index.tsx +++ b/src/modules/explorer/pages/User/index.tsx @@ -1,4 +1,4 @@ -import { Box, Grid, Theme, Typography, styled } from "@material-ui/core" +import { Box, Button, Grid, Theme, Typography, styled, useMediaQuery, useTheme } from "@material-ui/core" import dayjs from "dayjs" import { useDAOID } from "modules/explorer/pages/DAO/router" import React, { useCallback, useEffect, useMemo, useState } from "react" @@ -16,23 +16,30 @@ import { StatusBadge } from "../../components/StatusBadge" import { ProfileAvatar } from "../../components/styled/ProfileAvatar" import { UserBalances } from "../../components/UserBalances" import { UserProfileName } from "../../components/UserProfileName" -import { DropButton } from "../Proposals" import { usePolls } from "modules/lite/explorer/hooks/usePolls" import { Delegation } from "./components/DelegationBanner" import { useTokenDelegationSupported } from "services/contracts/token/hooks/useTokenDelegationSupported" - -const ContentBlockItem = styled(Grid)({ - padding: "35px 52px", - borderTop: `0.3px solid #4a4e4e` -}) +import { CopyButton } from "modules/common/CopyButton" +import { UserMovements } from "./components/UserMovements" +import { useUserVotes } from "modules/lite/explorer/hooks/useUserVotes" +import { Choice } from "models/Choice" +import { Poll } from "models/Polls" + +const ContentBlockItem = styled(Grid)(({ theme }: { theme: Theme }) => ({ + padding: "37px 42px", + background: theme.palette.primary.main, + borderRadius: 8 +})) const BalancesHeader = styled(Grid)(({ theme }: { theme: Theme }) => ({ minHeight: "178px", - padding: "46px 55px", + padding: "40px 48px", + gap: 16, background: theme.palette.primary.main, boxSizing: "border-box", borderRadius: 8, - boxShadow: "none" + boxShadow: "none", + display: "grid" })) const MainContainer = styled(Box)({ @@ -41,26 +48,22 @@ const MainContainer = styled(Box)({ const UsernameText = styled(Typography)({ fontSize: 18, - wordBreak: "break-all" + wordBreak: "break-all", + marginLeft: 10 }) const ProposalTitle = styled(Typography)({ fontWeight: "bold" }) -const StatusText = styled(Typography)({ - textTransform: "uppercase", - marginLeft: 10, - fontSize: 18, - marginRight: 30 -}) - -const VotedText = styled(Typography)({ - fontSize: 18 +const CreatedText = styled(Typography)({ + fontWeight: 300, + color: "#bfc5ca" }) -const CreatedText = styled(Typography)({ - fontWeight: 300 +const TitleText = styled(Typography)({ + fontWeight: 600, + fontSize: 32 }) export const ProposalItem: React.FC<{ @@ -105,15 +108,27 @@ export const User: React.FC = () => { const { data, cycleInfo } = useDAO(daoId) const { data: proposals } = useProposals(daoId) + const theme = useTheme() + const isMobileSmall = useMediaQuery(theme.breakpoints.down("sm")) + const history = useHistory() const { data: executedProposals } = useProposals(daoId, ProposalStatus.EXECUTED) const { data: droppedProposals } = useProposals(daoId, ProposalStatus.DROPPED) const { mutate: unstakeFromAllProposals } = useUnstakeFromAllProposals() const { data: polls } = usePolls(data?.liteDAOData?._id) - const pollsPosted = polls?.filter(p => p.author === account) + const pollsPosted: Poll[] | undefined = polls?.filter(p => p.author === account) + + const { data: userVotes } = useUserVotes() const { data: isTokenDelegationSupported } = useTokenDelegationSupported(data?.data.token.contract) + const votedPolls: any = [] + pollsPosted?.map((p: Poll) => { + if (userVotes && userVotes.filter(v => p._id === v.pollID).length > 0) { + return votedPolls.push(p) + } + }) + useEffect(() => { if (!account) { history.push(`../${daoId}`) @@ -170,84 +185,56 @@ export const User: React.FC = () => { return ( - - - - + + + My Address + + + + + + + - - - - - - - - - - + + + - - - - - - - - - - Unstake Votes - - - + - + + + + + + + + + + + + + {isTokenDelegationSupported ? : null} - - {proposalsCreated && cycleInfo && ( - - )} - - - {proposalsVoted && cycleInfo && ( - { - const voteDecision = getVoteDecision(proposal) - return ( - - - Voted - - - - {voteDecision ? "YES" : "NO"} - - - - ) - }} - liteProposals={pollsPosted} - /> - )} - + ) diff --git a/src/modules/home/Header.tsx b/src/modules/home/Header.tsx index 4c1c044e..601e71c1 100644 --- a/src/modules/home/Header.tsx +++ b/src/modules/home/Header.tsx @@ -23,7 +23,7 @@ const LogoText = styled(Typography)({ fontWeight: "bold", fontSize: "24px", cursor: "pointer", - fontFamily: "Roboto", + fontFamily: "Roboto Flex", letterSpacing: "initial" }) diff --git a/src/modules/home/LandingHeader.tsx b/src/modules/home/LandingHeader.tsx index 5a74442d..2413386a 100644 --- a/src/modules/home/LandingHeader.tsx +++ b/src/modules/home/LandingHeader.tsx @@ -19,7 +19,7 @@ const LogoText = styled(Typography)({ fontWeight: "bold", fontSize: "26px", cursor: "pointer", - fontFamily: "Roboto", + fontFamily: "Roboto Flex", letterSpacing: "initial" }) diff --git a/src/modules/lite/creator/index.tsx b/src/modules/lite/creator/index.tsx index e43eebe5..63db9626 100644 --- a/src/modules/lite/creator/index.tsx +++ b/src/modules/lite/creator/index.tsx @@ -139,7 +139,7 @@ const CustomTextarea = styled(withTheme(TextareaAutosize))(props => ({ "width": "100%", "fontWeight": 400, "padding": "21px 20px", - "fontFamily": "Roboto Mono", + "fontFamily": "Roboto Flex", "borderTopRightRadius": 0, "border": "none", "fontSize": 16, @@ -159,7 +159,7 @@ const CustomSelect = styled(Field)(({ theme }) => ({ background: theme.palette.primary.dark, border: "none", color: theme.palette.text.secondary, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 18, borderRight: "26px solid transparent", borderRadius: 4, @@ -224,7 +224,7 @@ const CommunityForm = ({ submitForm, values, setFieldValue, errors, touched, set const codeEditorStyles = { minHeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 14, fontWeight: 400, outlineWidth: 0, diff --git a/src/modules/lite/explorer/components/ChoiceItemSelected.tsx b/src/modules/lite/explorer/components/ChoiceItemSelected.tsx index 5afbe0e5..317a74b6 100644 --- a/src/modules/lite/explorer/components/ChoiceItemSelected.tsx +++ b/src/modules/lite/explorer/components/ChoiceItemSelected.tsx @@ -56,7 +56,15 @@ export const ChoiceItemSelected: React.FC<{ spacing={isMobileSmall ? 1 : 2} container item - style={isPartOfVotes() ? { border: "1px solid", borderColor: theme.palette.secondary.main } : {}} + style={ + isPartOfVotes() + ? { + border: "1px solid", + borderColor: theme.palette.secondary.main, + backgroundColor: "#334d43" + } + : {} + } xs={isMobileSmall ? 12 : 6} justifyContent={"center"} alignItems="center" diff --git a/src/modules/lite/explorer/components/DaoCardDetail.tsx b/src/modules/lite/explorer/components/DaoCardDetail.tsx index c495d461..a01a3747 100644 --- a/src/modules/lite/explorer/components/DaoCardDetail.tsx +++ b/src/modules/lite/explorer/components/DaoCardDetail.tsx @@ -26,7 +26,7 @@ const TermsText = styled(Link)(({ theme }) => ({ textDecoration: "underline", color: theme.palette.secondary.main, cursor: "pointer", - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", letterSpacing: "1px !important" })) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index 8e18da67..78154080 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -54,7 +54,7 @@ const Divider = styled(Typography)(({ theme }) => ({ })) const StyledLink = styled(Link)(({ theme }) => ({ - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontWeight: 300, fontSize: 16, marginLeft: 8, @@ -163,7 +163,12 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin - + diff --git a/src/modules/lite/explorer/components/ProposalList.tsx b/src/modules/lite/explorer/components/ProposalList.tsx index c805e5e4..403cb0f2 100644 --- a/src/modules/lite/explorer/components/ProposalList.tsx +++ b/src/modules/lite/explorer/components/ProposalList.tsx @@ -4,7 +4,7 @@ import { Divider, Grid, Typography, styled, useTheme, useMediaQuery } from "@mat import { ProposalTableRow } from "./ProposalTableRow" import { ProposalStatus } from "./ProposalTableRowStatusBadge" import { Poll } from "models/Polls" -import { useParams } from "react-router-dom" +import { useLocation, useParams } from "react-router-dom" import { CommunityToken } from "models/Community" import { useNotification } from "modules/common/hooks/useNotification" import { Dropdown } from "modules/explorer/components/Dropdown" @@ -15,14 +15,9 @@ export enum ProposalPopularity { POPULAR = "popular" } -const ProposalListContainer = styled(Grid)(({ theme }) => ({ - background: theme.palette.primary.main, - borderRadius: 8 -})) - -const Header = styled(Grid)({ +const Header = styled(Grid)(({ theme }) => ({ padding: "24px 41px" -}) +})) export const StyledDivider = styled(Divider)({ height: 0.3, @@ -55,9 +50,11 @@ export const ProposalList: React.FC<{ polls: Poll[]; id: string | undefined; dao const [isFilter, setIsFilter] = useState(false) const [isFilterByStatus, setIsFilterByStatus] = useState(1) const [statusFilter, setStatusFilter] = useState("") + const { pathname } = useLocation() const theme = useTheme() const isMobileSmall = useMediaQuery(theme.breakpoints.down("sm")) + const shouldShowBar = pathname.includes("/lite") ? true : false useEffect(() => { setCommunityPolls(polls) @@ -177,8 +174,13 @@ export const ProposalList: React.FC<{ polls: Poll[]; id: string | undefined; dao ) return ( - -
+ +
Off-Chain @@ -206,13 +208,11 @@ export const ProposalList: React.FC<{ polls: Poll[]; id: string | undefined; dao /> </Grid> </Header> - <StyledDivider /> {communityPolls && communityPolls.length > 0 ? ( communityPolls.map((poll, i) => { return ( <div style={{ width: "inherit" }} key={`poll-${i}`}> <ProposalTableRow poll={poll} daoId={daoId} /> - {communityPolls.length - 1 !== i ? <StyledDivider key={`divider-${i}`} /> : null} </div> ) }) @@ -221,6 +221,6 @@ export const ProposalList: React.FC<{ polls: Poll[]; id: string | undefined; dao <NoProposalsText color="textPrimary">No proposals</NoProposalsText> </Header> )} - </ProposalListContainer> + </Grid> ) } diff --git a/src/modules/lite/explorer/components/ProposalTableRow.tsx b/src/modules/lite/explorer/components/ProposalTableRow.tsx index 3119195c..8ccbe0b2 100644 --- a/src/modules/lite/explorer/components/ProposalTableRow.tsx +++ b/src/modules/lite/explorer/components/ProposalTableRow.tsx @@ -3,37 +3,34 @@ import { styled, Grid, Typography, useTheme, useMediaQuery, LinearProgress } fro import { RowContainer } from "./tables/RowContainer" import { ProposalStatus, TableStatusBadge } from "./ProposalTableRowStatusBadge" import { useHistory } from "react-router" -import { Blockie } from "modules/common/Blockie" -import { toShortAddress } from "services/contracts/utils" import { Poll } from "models/Polls" import ReactHtmlParser from "react-html-parser" - +import dayjs from "dayjs" export interface ProposalTableRowData { daoId?: string id: string } const ArrowInfo = styled(Typography)(({ theme }) => ({ - fontFamily: "Roboto Mono", - fontWeight: 500, + fontFamily: "Roboto Flex", + fontWeight: 300, fontSize: 16, + color: "#bfc5ca", [theme.breakpoints.down("xs")]: { marginTop: 5 } })) -const Address = styled(Typography)({ - marginLeft: 12 -}) - -const BlockieContainer = styled(Grid)({ - marginBottom: 19 +const Title = styled(Typography)({ + fontWeight: 600, + fontSize: 18 }) const DescriptionText = styled(Typography)(({ theme }) => ({ fontWeight: 300, fontSize: 18, width: "inherit", + color: "#BFC5CA", wordBreak: "break-word", [theme.breakpoints.down("sm")]: { fontSize: 16 @@ -48,37 +45,35 @@ export const ProposalTableRow: React.FC<{ poll: Poll; daoId?: string }> = ({ pol return ( <RowContainer + style={{ background: "#2F3438", borderRadius: 8 }} item container - alignItems="center" + alignItems="baseline" onClick={() => navigate.push(`/explorer/lite/dao/${poll.daoID}/community/proposal/${poll._id}`, { poll: poll, daoId: daoId }) } > - <BlockieContainer container direction="row"> - <Blockie address={"tz1bQgEea45ciBpYdFj4y4P3hNyDM8aMF6WB"} size={24} /> - <Address color="textPrimary" variant="subtitle2"> - {toShortAddress(poll.author)} - </Address> - </BlockieContainer> - <Grid container item style={{ gap: 25 }} xs={12} md={12} justifyContent={isMobile ? "center" : "flex-start"}> - <Typography variant="h4" color="textPrimary" align={isMobile ? "center" : "left"}> + <Grid container item style={{ gap: 16 }} xs={12} md={12} justifyContent={isMobile ? "center" : "flex-start"}> + <Title color="textPrimary" align={isMobile ? "center" : "left"}> {poll.name} - </Typography> + + + + {ReactHtmlParser(poll.description)} + {poll.timeFormatted} - - - - {ReactHtmlParser(poll.description)} + {poll.isActive === ProposalStatus.ACTIVE ? ( + •   Created {dayjs(poll.startTime).format("LL")} + ) : null} diff --git a/src/modules/lite/explorer/components/ProposalTableRowStatusBadge.tsx b/src/modules/lite/explorer/components/ProposalTableRowStatusBadge.tsx index e09b2b52..6a3d2600 100644 --- a/src/modules/lite/explorer/components/ProposalTableRowStatusBadge.tsx +++ b/src/modules/lite/explorer/components/ProposalTableRowStatusBadge.tsx @@ -11,19 +11,19 @@ export enum ProposalStatus { const getStatusColor = (status: ProposalStatus, theme: Theme): string => { const statusToColor = { - [ProposalStatus.ACTIVE]: theme.palette.secondary.main, - [ProposalStatus.CLOSED]: "#7e496f" + [ProposalStatus.ACTIVE]: "#85c4ff", + [ProposalStatus.CLOSED]: "#cc8aff" } return statusToColor[status] } const Badge = styled(Grid)(({ status, theme }: { status: ProposalStatus; theme: Theme }) => ({ - "borderRadius": 4, + "borderRadius": 50, "boxSizing": "border-box", "minWidth": 87, "textAlign": "center", - "padding": "2px 16px", + "padding": "4px 16px", "background": hexToRgba(getStatusColor(status, theme), 0.4), "color": getStatusColor(status, theme), @@ -34,14 +34,15 @@ const Badge = styled(Grid)(({ status, theme }: { status: ProposalStatus; theme: const Text = styled(Typography)({ fontWeight: 500, - fontSize: 16 + fontSize: 16, + textTransform: "capitalize" }) export const TableStatusBadge: React.FC<{ status: ProposalStatus } & GridProps> = ({ status }) => ( - {status.toUpperCase()} + {status} diff --git a/src/modules/lite/explorer/components/tables/RowContainer.tsx b/src/modules/lite/explorer/components/tables/RowContainer.tsx index c1f4f713..3a962f8e 100644 --- a/src/modules/lite/explorer/components/tables/RowContainer.tsx +++ b/src/modules/lite/explorer/components/tables/RowContainer.tsx @@ -1,9 +1,10 @@ import { Grid, styled } from "@material-ui/core" export const RowContainer = styled(Grid)(({ theme }) => ({ - minHeight: 145, - padding: "44px 38px", + minHeight: 192, + padding: "37px 48px", cursor: "pointer", + width: "inherit", [theme.breakpoints.down("md")]: { padding: "34px 38px", width: "inherit" diff --git a/src/modules/lite/explorer/hooks/useUserVotes.tsx b/src/modules/lite/explorer/hooks/useUserVotes.tsx new file mode 100644 index 00000000..74d7620f --- /dev/null +++ b/src/modules/lite/explorer/hooks/useUserVotes.tsx @@ -0,0 +1,45 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import React from "react" +import { useNotification } from "modules/common/hooks/useNotification" +import { EnvKey, getEnv } from "services/config" +import { useQuery } from "react-query" +import { useTezos } from "services/beacon/hooks/useTezos" +import { Choice } from "models/Choice" + +export const useUserVotes = () => { + const { account } = useTezos() + const openNotification = useNotification() + + const { data, ...rest } = useQuery( + ["userVotes"], + async () => { + const response = await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/choices/${String(account)}/user_votes`) + + if (!response.ok) { + const data = await response.json() + openNotification({ + message: data.message, + autoHideDuration: 2000, + variant: "error" + }) + return + } + + const userVotedPolls: Choice[] = await response.json() + if (!userVotedPolls) { + return + } + return userVotedPolls + }, + { + refetchInterval: 30000, + enabled: !!account, + refetchOnMount: "always" + } + ) + + return { + data, + ...rest + } +} diff --git a/src/modules/lite/explorer/pages/CreateProposal/index.tsx b/src/modules/lite/explorer/pages/CreateProposal/index.tsx index 96ab1847..d36bffdd 100644 --- a/src/modules/lite/explorer/pages/CreateProposal/index.tsx +++ b/src/modules/lite/explorer/pages/CreateProposal/index.tsx @@ -133,7 +133,7 @@ const PageContainer = styled("div")({ ["@media (max-width:1335px)"]: {}, ["@media (max-width:1167px)"]: { - width: "86vw !important" + width: "inherit !important" }, ["@media (max-width:1030px)"]: {}, @@ -170,7 +170,7 @@ const CustomTextarea = styled(withTheme(TextareaAutosize))(props => ({ "borderRadius": 8, "paddingRight": 40, "wordBreak": "break-word", - "fontFamily": "Roboto Mono", + "fontFamily": "Roboto Flex", "&:focus-visible": { outline: "none" }, @@ -319,7 +319,7 @@ export const ProposalForm = ({ const codeEditorStyles = { minHeight: 500, - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", fontSize: 14, fontWeight: 400, outlineWidth: 0, diff --git a/src/modules/lite/explorer/pages/ProposalDetails/index.tsx b/src/modules/lite/explorer/pages/ProposalDetails/index.tsx index d26410df..82e0643c 100644 --- a/src/modules/lite/explorer/pages/ProposalDetails/index.tsx +++ b/src/modules/lite/explorer/pages/ProposalDetails/index.tsx @@ -137,7 +137,7 @@ export const ProposalDetails: React.FC<{ id: string }> = ({ id }) => { navigate.push(`/explorer/lite/dao/${id}/community/`)} + onClick={() => navigate.goBack()} alignItems="center" > diff --git a/src/services/contracts/baseDAO/hooks/useTransfers.ts b/src/services/contracts/baseDAO/hooks/useTransfers.ts index b703c511..8bfc54b8 100644 --- a/src/services/contracts/baseDAO/hooks/useTransfers.ts +++ b/src/services/contracts/baseDAO/hooks/useTransfers.ts @@ -8,6 +8,14 @@ import { BigNumber } from "bignumber.js" import { getXTZTransfers } from "services/services/dao/services" import dayjs from "dayjs" +interface BNToken { + contract: string + decimals: number + name: string + network: string + symbol: string + token_id: number +} export interface TransferWithBN { name: string amount: BigNumber @@ -15,6 +23,8 @@ export interface TransferWithBN { sender: string date: string hash: string + type?: "Withdrawal" | "Deposit" + token?: BNToken } export const useTransfers = (contractAddress: string) => { @@ -45,7 +55,8 @@ export const useTransfers = (contractAddress: string) => { date: t.timestamp, name: t.token.symbol === "OBJKT" ? `${t.token.symbol}#${t.token.token_id}` : t.token.symbol || "-", hash: t.hash, - amount: parseUnits(new BigNumber(t.amount), t.token.decimals) + amount: parseUnits(new BigNumber(t.amount), t.token.decimals), + type: t.to === dao?.data.address ? "Deposit" : "Withdrawal" })) return tokenTransfers.concat(xtzTransfers).sort((a, b) => (dayjs(a.date).isAfter(dayjs(b.date)) ? 1 : -1)) diff --git a/src/theme/index.ts b/src/theme/index.ts index 841a4703..625f8a99 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -13,7 +13,7 @@ export const theme = createTheme({ primary: { main: "#2F3438", dark: "#1C1F23", - light: "#383e43" + light: "#bfc5ca" }, secondary: { main: "#81FEB7", @@ -21,7 +21,7 @@ export const theme = createTheme({ contrastText: "#1C1F23" }, text: { - primary: "#FFFFFF" + primary: "#FDFDFD" }, error: { main: "#ED254E" @@ -34,7 +34,7 @@ export const theme = createTheme({ } }, typography: { - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", h1: { fontSize: 30, [breakpoints.down("xs")]: { @@ -123,7 +123,7 @@ export const theme = createTheme({ MuiStepLabel: { label: { "cursor": "pointer", - "color": "#fff", + "color": "#FDFDFD", "opacity": 0.5, "marginLeft": 15, "lineHeight": "40px", @@ -138,11 +138,11 @@ export const theme = createTheme({ } }, active: { - color: "#fff !important", + color: "#FDFDFD !important", opacity: 1 }, completed: { - color: "#fff !important", + color: "#FDFDFD !important", opacity: 0.5, fontWeight: 300 } @@ -167,7 +167,7 @@ export const theme = createTheme({ color: "#1C1F23 !important" }, completed: { - color: "#fff !important" + color: "#FDFDFD !important" }, root: { "height": 32, @@ -176,7 +176,7 @@ export const theme = createTheme({ "border": "1px solid #3D3D3D", "borderRadius": "50%", "&$active": { - "fill": "#fff", + "fill": "#FDFDFD", "border": "1px solid #3D3D3D", "borderRadius": "50%", "& $text": { @@ -186,7 +186,7 @@ export const theme = createTheme({ } }, text: { - fill: "#fff" + fill: "#FDFDFD" } }, MuiIconButton: { @@ -250,17 +250,24 @@ export const theme = createTheme({ "padding": "1px 8px", "fontSize": "1rem" }, - disabled: {} + disabled: {}, + text: { + "color": "#81FEB7", + "&$disabled": { + color: "#bfc5ca !important", + background: "inherit !important" + } + } }, MuiInputBase: { input: { textAlign: "center", - color: "#fff" + color: "#FDFDFD" } }, MuiRadio: { root: { - color: "#fff" + color: "#FDFDFD" } }, MuiDivider: { @@ -302,7 +309,7 @@ export const theme = createTheme({ textTransform: "capitalize" }, icon: { - color: "#fff" + color: "#FDFDFD" } }, MuiDialogContentText: { @@ -328,7 +335,7 @@ export const theme = createTheme({ track: { "borderRadius": "40px", "backgroundColor": "inherit", - "border": "1px solid #fff", + "border": "1px solid #FDFDFD", "opacity": 0.5, "$checked$checked + &": { opacity: 1, @@ -345,7 +352,7 @@ export const theme = createTheme({ } }, colorSecondary: { - "color": "#fff", + "color": "#FDFDFD", "$checked$checked + &": { color: "#81FEB7" }, @@ -362,7 +369,8 @@ export const theme = createTheme({ MuiTable: { root: { borderRadius: "8px", - backgroundColor: "#2F3438" + backgroundColor: "#2F3438", + overflow: "hidden" } }, MuiTableHead: { @@ -386,8 +394,8 @@ export const theme = createTheme({ }, MuiTableBody: { root: { - "& > *:not(:first-child)": { - borderTop: "0.3px solid rgba(125,140,139, 0.2)", + "& > *:not(:last-child)": { + borderBottom: "0.3px solid #575757", minHeight: 90 } } @@ -398,6 +406,9 @@ export const theme = createTheme({ }, head: { fontWeight: 300 + }, + body: { + fontWeight: 300 } }, MuiTableRow: { @@ -409,7 +420,17 @@ export const theme = createTheme({ }, "& th:last-child, & td:last-child": { paddingRight: 46 + }, + "&:nth-of-type(odd)": { + backgroundColor: "#2A2E32" + }, + "&:nth-of-type(even)": { + backgroundColor: "#383E43" } + }, + head: { + backgroundColor: "#383E43 !important", + borderBottom: "0.3px solid #575757" } }, MuiGrid: { @@ -417,6 +438,14 @@ export const theme = createTheme({ alignItems: "center" } }, + MuiLink: { + underlineHover: { + "&:hover": { + textUnderlineOffset: "4px", + textDecorationColor: "#fdfdfd" + } + } + }, MuiLinearProgress: { root: { borderRadius: 50, diff --git a/src/theme/legacy.ts b/src/theme/legacy.ts index e24bee3e..51d86fe2 100644 --- a/src/theme/legacy.ts +++ b/src/theme/legacy.ts @@ -12,7 +12,7 @@ export const legacyTheme = createMuiTheme({ }, text: { primary: "#000000", - secondary: "#fff" + secondary: "#FDFDFD" }, error: { main: "#ED254E" @@ -25,7 +25,7 @@ export const legacyTheme = createMuiTheme({ } }, typography: { - fontFamily: "Roboto Mono", + fontFamily: "Roboto Flex", h1: { fontSize: 35, letterSpacing: "-0.01em" @@ -45,7 +45,7 @@ export const legacyTheme = createMuiTheme({ h3: { fontSize: 32, fontWeight: 500, - fontFamily: "Roboto Mono" + fontFamily: "Roboto Flex" }, h2: { color: "#000000", @@ -91,7 +91,7 @@ export const legacyTheme = createMuiTheme({ marginTop: -3 }, label: { - "color": "#fff", + "color": "#FDFDFD", "opacity": 0.5, "marginLeft": 15, "fontSize": 14, @@ -110,11 +110,11 @@ export const legacyTheme = createMuiTheme({ } }, active: { - color: "#fff !important", + color: "#FDFDFD !important", opacity: 1 }, completed: { - color: "#fff !important", + color: "#FDFDFD !important", opacity: 0.5, fontWeight: 300 } @@ -130,7 +130,7 @@ export const legacyTheme = createMuiTheme({ marginTop: -16 }, line: { - borderColor: "#fff", + borderColor: "#FDFDFD", opacity: 0.2 }, active: { @@ -161,7 +161,7 @@ export const legacyTheme = createMuiTheme({ color: "#1C1F23 !important" }, completed: { - color: "#fff !important" + color: "#FDFDFD !important" }, root: { "height": 32, @@ -184,7 +184,7 @@ export const legacyTheme = createMuiTheme({ } }, text: { - fill: "#fff" + fill: "#FDFDFD" } }, MuiInput: { @@ -238,7 +238,7 @@ export const legacyTheme = createMuiTheme({ MuiInputBase: { input: { textAlign: "start", - color: "#fff" + color: "#FDFDFD" }, root: { fontWeight: 300 @@ -303,7 +303,7 @@ export const legacyTheme = createMuiTheme({ track: { "borderRadius": "40px", "backgroundColor": "inherit", - "border": "1px solid #fff", + "border": "1px solid #FDFDFD", "opacity": 0.5, "$checked$checked + &": { opacity: 1, @@ -319,7 +319,7 @@ export const legacyTheme = createMuiTheme({ } }, colorSecondary: { - "color": "#fff", + "color": "#FDFDFD", "$checked$checked + &": { color: "#81FEB7" },