diff --git a/packages/apps/dashboard/client/src/App.css b/packages/apps/dashboard/client/src/App.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/apps/dashboard/client/src/App.tsx b/packages/apps/dashboard/client/src/App.tsx index 5ed277c1f9..fd00554e6d 100644 --- a/packages/apps/dashboard/client/src/App.tsx +++ b/packages/apps/dashboard/client/src/App.tsx @@ -1,11 +1,13 @@ -import React from 'react'; +import { FC } from 'react'; + import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; -import Home from '@pages/Home'; + import Graph from '@pages/Graph'; +import Home from '@pages/Home'; +import LeaderBoard from '@pages/Leaderboard'; import SearchResults from '@pages/SearchResults'; -import { LeaderBoard } from '@pages/Leaderboard'; -const App: React.FC = () => { +const App: FC = () => { return ( diff --git a/packages/apps/dashboard/client/src/assets/react.svg b/packages/apps/dashboard/client/src/assets/react.svg deleted file mode 100644 index 6c87de9bb3..0000000000 --- a/packages/apps/dashboard/client/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/apps/dashboard/client/src/assets/styles/_breadcrumbs.scss b/packages/apps/dashboard/client/src/assets/styles/_breadcrumbs.scss deleted file mode 100644 index 3d21ae1cb6..0000000000 --- a/packages/apps/dashboard/client/src/assets/styles/_breadcrumbs.scss +++ /dev/null @@ -1,11 +0,0 @@ -.breadcrumbs{ - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 62px; - - @media(max-width: 1100px) { - margin-bottom: 24px; - } - -} diff --git a/packages/apps/dashboard/client/src/assets/styles/_footer.scss b/packages/apps/dashboard/client/src/assets/styles/_footer.scss deleted file mode 100644 index 9942d4a1d9..0000000000 --- a/packages/apps/dashboard/client/src/assets/styles/_footer.scss +++ /dev/null @@ -1,72 +0,0 @@ -footer{ - min-height: 124px; - margin-top: auto; - @media(max-width: 1100px) { - padding: 0 24px; - flex-direction: column-reverse; - justify-content: center; - align-items: center; - background-color: $maWhite; - } - - .footer-wrapper { - display: flex; - padding: 32px 18px; - flex-direction: row; - justify-content: space-between; - align-items: stretch; - - @media (max-width: 1100px) { - flex-direction: column-reverse; - } - } - - .footer-link { - gap: 24px; - margin-bottom: 24px; - align-items: flex-start; - } - - .footer-icon { - justify-content: flex-start; - gap: 30px; - margin-bottom: 0; - align-items: flex-end; - - @media (max-width: 600px) { - justify-content: space-between; - align-items: flex-start; - margin-bottom: 32px; - } - - @media (max-width: 1100px) { - margin-bottom: 32px; - } - } - - .footer-link, .footer-icon{ - display: flex; - flex-wrap: wrap; - span { - cursor: pointer; - font-size: 12px; - } - svg { - font-size: 32px; - cursor: pointer; - } - } - - @media (max-width: 1100px) { - .footer-link-wrapper{ - .footer-link{ - flex-direction: column; - } - } - } - - .footer-link, .footer-icon{ - justify-content: flex-start; - align-items: flex-start; - } -} diff --git a/packages/apps/dashboard/client/src/assets/styles/_graph-swipper.scss b/packages/apps/dashboard/client/src/assets/styles/_graph-swipper.scss index 4176d2fffd..70b3f74ea0 100644 --- a/packages/apps/dashboard/client/src/assets/styles/_graph-swipper.scss +++ b/packages/apps/dashboard/client/src/assets/styles/_graph-swipper.scss @@ -1,5 +1,9 @@ .swiper-button-next, .swiper-button-prev { - top: 35% + top: 50%; + + @media (max-width: 900px) { + top: 30%; + } } .swiper-button-next::after, .swiper-button-prev::after { diff --git a/packages/apps/dashboard/client/src/assets/styles/_header.scss b/packages/apps/dashboard/client/src/assets/styles/_header.scss deleted file mode 100644 index 348816444b..0000000000 --- a/packages/apps/dashboard/client/src/assets/styles/_header.scss +++ /dev/null @@ -1,72 +0,0 @@ -.header-toolbar { - height: 82px; - justify-content: space-between; - - .header-list-link { - display: flex; - gap: 16px; - align-items: center; - .header-link { - font-weight: 600; - padding: 6px 8px; - cursor: pointer; - font-size: 14px; - } - } - - .mobile-icon { - display: none; - } - - .logo-mobile, - .search-header-mobile { - display: none; - } - - @media (max-width: 1300px) { - .logo { - display: none; - } - .logo-mobile { - display: block; - } - } - - @media (max-width: 1280px) { - height: 62px; - .mobile-icon, - .search-header-mobile { - display: block; - } - .header-list-link, - .search-header { - display: none; - } - - .logo-mobile { - margin-left: 24px; - } - - .mobile-icon { - margin-right: 16px; - } - } -} - -.header-mobile-menu { - padding: 20px 10px; - .header-list-link { - display: flex; - gap: 16px; - flex-direction: column; - .header-link { - font-weight: 600; - padding: 6px 8px; - font-size: 14px; - } - - span { - cursor: pointer; - } - } -} diff --git a/packages/apps/dashboard/client/src/assets/styles/_home-page.scss b/packages/apps/dashboard/client/src/assets/styles/_home-page.scss index a6c4853400..e0c55f0895 100644 --- a/packages/apps/dashboard/client/src/assets/styles/_home-page.scss +++ b/packages/apps/dashboard/client/src/assets/styles/_home-page.scss @@ -1,189 +1,7 @@ -.home-page-header { - color: $white; - .home-page-search { - margin-top: 24px; - } +.home-page-search { + margin-top: 24px; } -.home-page-boxes { - display: flex; - gap: 24px; - margin-top: 62px; - - .home-page-box { - color: $primary; - background-color: $white; - border-radius: 16px; - padding: 24px 32px; - width: calc(38% - 24px); - - @media (max-width: 660px) { - padding: 24px 16px; - } - - .box-title { - font-size: 14px; - height: 32px; - margin-bottom: 24px; - display: flex; - align-items: center; - justify-content: space-between; - } - .box-content { - display: flex; - .count { - font-size: 20px; - font-weight: 500; - margin-top: 3px; - } - .box-icon { - margin-right: 10px; - } - } - } - - .home-page-box:first-child { - width: 24%; - } - @media (max-width: 1250px) { - flex-wrap: wrap; - .home-page-box, - .home-page-box:first-child { - width: 100%; - } - } -} - -.home-page-find { - font-size: 14px; - margin-top: 32px; - display: flex; - gap: 32px; - align-items: center; - height: 60px; - white-space: nowrap; - span { - display: flex; - align-items: center; - gap: 16px; - } - @media (max-width: 1100px) { - span { - min-width: 120px; - } - } -} - -.home-page-find-title-mobile { - margin-top: 32px; - font-size: 14px; - @media (max-width: 1100px) { - display: block; - } -} .home-page-leaderboard { margin-top: 60px; } - -.home-page-table-header { - background-color: $whiteSolid; - height: 72px; - color: #320a8d; - text-transform: uppercase; - border: 0; - margin-bottom: 15px; - - th { - font-size: 12px; - } - .icon-table { - display: flex; - align-items: center; - gap: 8px; - } -} - -.home-page-table-row { - td { - padding: 32px 16px; - font-size: 16px; - } - - .icon-table { - background-color: $groundwaterOpacity; - display: flex; - align-items: center; - justify-content: center; - border-radius: 10px; - width: 52px; - height: 52px; - } - - .reputation-table { - padding: 4px 8px; - border-radius: 16px; - font-size: 13px; - display: inline; - } - - .reputation-table-medium { - color: $medium; - border: 1px solid $mediumBorder; - } - - .reputation-table-low { - color: $low; - border: 1px solid $lowBorder; - } - - .reputation-table-high { - color: $high; - border: 1px solid $highBorder; - } - .reputation-table-soon { - color: $soon; - border: 1px solid $soonBorder; - } - - &:hover { - transition: opacity 8ms; - opacity: 0.8; - } -} - -#network-select { - svg { - display: none; - } -} - -.select-item { - display: flex; - gap: 10px; -} - -.mobile-select { - width: 270px; - background-color: $whiteSolid; - padding: 10px; - display: none; - margin-bottom: 20px; - @media (max-width: 1100px) { - display: block; - } -} - -.table-filter-select { - @media (max-width: 1100px) { - div { - display: none; - } - } - .mobile-title { - display: none; - font-weight: 400; - @media (max-width: 1100px) { - display: block; - } - } -} diff --git a/packages/apps/dashboard/client/src/assets/styles/_nothing-found.scss b/packages/apps/dashboard/client/src/assets/styles/_nothing-found.scss deleted file mode 100644 index 4730145a62..0000000000 --- a/packages/apps/dashboard/client/src/assets/styles/_nothing-found.scss +++ /dev/null @@ -1,16 +0,0 @@ -.nothing-found-title{ - font-size: 34px; - font-weight: 600; -} - -.nothing-found-desc{ - font-size: 16px; - margin-top: 30px; -} - -.nothing-found-link{ - color: $secondary; - margin-left: 10px; - margin-top: 20px; - font-weight: 600; -} diff --git a/packages/apps/dashboard/client/src/assets/styles/_page-wrapper.scss b/packages/apps/dashboard/client/src/assets/styles/_page-wrapper.scss index 6891dda980..647bdf1945 100644 --- a/packages/apps/dashboard/client/src/assets/styles/_page-wrapper.scss +++ b/packages/apps/dashboard/client/src/assets/styles/_page-wrapper.scss @@ -1,32 +1,23 @@ .page-wrapper { + display: flex; + flex-direction: column; margin: 0 56px; - min-height: calc(100vh - 206px); - border-bottom-left-radius: 20px; - border-bottom-right-radius: 20px; - display: flex; - flex-direction: column; - padding: 14px 0; - height: 100vh; + padding: 0; + min-height: 100dvh; @media (max-width: 1280px) { - border-radius: 0; - height: auto; + margin: 0 24px; } .container { margin: auto; padding: 30px 80px 100px; - @media (max-width: 1100px) { - padding: 30px 16px; + @media (max-width: 1200px) { + padding: 24px 16px; } } - @media (max-width: 1280px) { - min-height: calc(100vh - 386px); - margin: 0 24px; - } - @media (max-width: 600px) { margin: 0; } @@ -36,11 +27,15 @@ z-index: 10; border-radius: 20px; background-size: 100% 100%; - background: linear-gradient(to bottom, $primary 252px, $maWhite 1px); + background: linear-gradient(to bottom, $primary 252px, $maWhite 0px); + + @media (max-width: 900px) { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } @media (max-width: 600px) { - border-top-left-radius: 0; - border-top-right-radius: 0; + border-radius: 0; } } diff --git a/packages/apps/dashboard/client/src/assets/styles/_shadow-icon.scss b/packages/apps/dashboard/client/src/assets/styles/_shadow-icon.scss index bf50fc4162..3dfec75db9 100644 --- a/packages/apps/dashboard/client/src/assets/styles/_shadow-icon.scss +++ b/packages/apps/dashboard/client/src/assets/styles/_shadow-icon.scss @@ -1,9 +1,13 @@ .shadow-icon{ display: flex; + align-items: center; gap: 16px; - height: 90px; + height: 78px; + &__icon { - width: 65px; + width: 66px; + height: 100%; + padding: 6px; display: flex; justify-content: center; align-items: center; @@ -14,14 +18,12 @@ height: 130px; } span{ - padding-top: 20px; font-size: 28px; font-weight: 600; } - @media (max-width: 400px) { + @media (max-width: 600px) { span { - padding-top: 30px; font-size: 20px; font-weight: 500; } diff --git a/packages/apps/dashboard/client/src/assets/styles/color-palette.ts b/packages/apps/dashboard/client/src/assets/styles/color-palette.ts index 0d1b0e298e..ed67fcb013 100644 --- a/packages/apps/dashboard/client/src/assets/styles/color-palette.ts +++ b/packages/apps/dashboard/client/src/assets/styles/color-palette.ts @@ -55,12 +55,6 @@ export const colorPalette = { main: '#ED6C02', light: '#ED6C0280', }, - textSecondary: { - main: '#858ec6', - light: '#858ec6', - dark: '#858ec6', - contrastText: '#858ec6', - }, table: { main: '#FFFFFF01', selected: '#1406B21F', diff --git a/packages/apps/dashboard/client/src/assets/styles/main.scss b/packages/apps/dashboard/client/src/assets/styles/main.scss index e1848c1a11..2ddc2cf6e3 100644 --- a/packages/apps/dashboard/client/src/assets/styles/main.scss +++ b/packages/apps/dashboard/client/src/assets/styles/main.scss @@ -1,10 +1,6 @@ @import 'const'; -@import 'header'; @import 'page-wrapper'; -@import 'footer'; @import 'home-page'; @import 'search'; @import 'shadow-icon'; -@import 'breadcrumbs'; -@import 'nothing-found'; @import "graph-swipper"; diff --git a/packages/apps/dashboard/client/src/components/Breadcrumbs/Breadcrumbs.tsx b/packages/apps/dashboard/client/src/components/Breadcrumbs/Breadcrumbs.tsx index 18bb584207..8505e7439c 100644 --- a/packages/apps/dashboard/client/src/components/Breadcrumbs/Breadcrumbs.tsx +++ b/packages/apps/dashboard/client/src/components/Breadcrumbs/Breadcrumbs.tsx @@ -1,28 +1,29 @@ import { FC } from 'react'; + +import { Link as RouterLink } from 'react-router-dom'; +import Link from '@mui/material/Link'; +import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; + import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; -import { useNavigate } from 'react-router-dom'; const Breadcrumbs: FC<{ title?: string }> = ({ title }) => { - const navigate = useNavigate(); return ( -
- { - navigate('/'); - }} - component="span" - fontSize={16} - sx={{ textDecoration: 'unset', cursor: 'pointer' }} + + Dashboard - + - - {title} - -
+ {title} + ); }; diff --git a/packages/apps/dashboard/client/src/components/Charts/AreaChart.tsx b/packages/apps/dashboard/client/src/components/Charts/AreaChart.tsx index 4300ff5fe8..990e9cabbe 100644 --- a/packages/apps/dashboard/client/src/components/Charts/AreaChart.tsx +++ b/packages/apps/dashboard/client/src/components/Charts/AreaChart.tsx @@ -155,16 +155,17 @@ export const AreaChart = ({ return ( @@ -360,9 +361,9 @@ export const AreaChart = ({ {elem.title} - {elem.amount ? : ''} + {elem.amount ? : 0} {elem.name === 'totalTransactionAmount' && elem.isAreaChart && ( HMT diff --git a/packages/apps/dashboard/client/src/components/Clipboard/Clipboard.tsx b/packages/apps/dashboard/client/src/components/Clipboard/Clipboard.tsx index da3bc72a74..967c27340e 100644 --- a/packages/apps/dashboard/client/src/components/Clipboard/Clipboard.tsx +++ b/packages/apps/dashboard/client/src/components/Clipboard/Clipboard.tsx @@ -1,11 +1,11 @@ +import { useState } from 'react'; + import Card from '@mui/material/Card'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import ContentCopyIcon from '@mui/icons-material/ContentCopy'; -import { colorPalette } from '@assets/styles/color-palette'; import CustomTooltip from '@components/CustomTooltip'; -import { useState } from 'react'; interface ClipboardProps { value: string; @@ -16,9 +16,11 @@ const Clipboard = ({ value }: ClipboardProps) => { return ( @@ -29,7 +31,7 @@ const Clipboard = ({ value }: ClipboardProps) => { justifyContent="space-between" > { diff --git a/packages/apps/dashboard/client/src/components/DataEntry/ToggleButtons.tsx b/packages/apps/dashboard/client/src/components/DataEntry/ToggleButtons.tsx index 808d5ec296..88da0dd274 100644 --- a/packages/apps/dashboard/client/src/components/DataEntry/ToggleButtons.tsx +++ b/packages/apps/dashboard/client/src/components/DataEntry/ToggleButtons.tsx @@ -2,21 +2,25 @@ import ToggleButton from '@mui/material/ToggleButton'; import Typography from '@mui/material/Typography'; import { styled } from '@mui/material'; import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; -import { colorPalette } from '@assets/styles/color-palette'; import { TIME_PERIOD_OPTIONS, TimePeriod, useGraphPageChartParams, } from '@utils/hooks/use-graph-page-chart-params'; +import dayjs from 'dayjs'; -export const StyledToggleButtonGroup = styled(ToggleButtonGroup)({ - '.MuiToggleButtonGroup-grouped': { - border: 'none', - borderRadius: 4, - width: 50, - color: colorPalette.primary.main, - }, -}); +export const StyledToggleButtonGroup = styled(ToggleButtonGroup)( + ({ theme }) => ({ + gap: 8, + '.MuiToggleButtonGroup-grouped': { + border: 'none', + borderRadius: 4, + width: 47, + height: 30, + color: theme.palette.primary.main, + }, + }) +); const ToggleButtons = () => { const { setTimePeriod, selectedTimePeriod, dateRangeParams } = @@ -24,7 +28,10 @@ const ToggleButtons = () => { const checkIfSelected = (element: TimePeriod) => { if (element.name !== 'ALL') { - return element.value.isSame(dateRangeParams.from); + return ( + element.value.isSame(dateRangeParams.from) && + dateRangeParams.to.isSame(dayjs(), 'day') + ); } }; @@ -36,27 +43,24 @@ const ToggleButtons = () => { > {TIME_PERIOD_OPTIONS.map((elem) => ( { - setTimePeriod(elem); - }} - selected={checkIfSelected(elem)} key={elem.name} + onClick={() => setTimePeriod(elem)} + selected={checkIfSelected(elem)} + value={elem.name} sx={{ '.MuiTypography-root': { wordBreak: 'normal', }, '&.Mui-selected': { - backgroundColor: colorPalette.primary.main, - color: colorPalette.white, + backgroundColor: 'primary.main', + color: 'white.main', }, '&.Mui-selected:hover': { - cursor: 'pointer', - backgroundColor: colorPalette.primary.main, + backgroundColor: 'primary.main', }, }} - value={elem.name} > - {elem.name} + {elem.name} ))} diff --git a/packages/apps/dashboard/client/src/components/Footer/Footer.tsx b/packages/apps/dashboard/client/src/components/Footer/Footer.tsx index f89a3f7dcd..31e4281a67 100644 --- a/packages/apps/dashboard/client/src/components/Footer/Footer.tsx +++ b/packages/apps/dashboard/client/src/components/Footer/Footer.tsx @@ -1,83 +1,132 @@ import { FC } from 'react'; + +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import { IconButton, styled } from '@mui/material'; import Typography from '@mui/material/Typography'; import TwitterIcon from '@mui/icons-material/Twitter'; import LinkedInIcon from '@mui/icons-material/LinkedIn'; import GitHubIcon from '@mui/icons-material/GitHub'; import TelegramIcon from '@mui/icons-material/Telegram'; + import DiscordIcon from '@components/Icons/DiscordIcon'; -import { colorPalette } from '@assets/styles/color-palette'; import { env } from '@helpers/env'; +const StyledLink = styled(Link)(({ theme }) => ({ + textDecoration: 'none', + color: theme.palette.text.secondary, + '&:visited': { + color: theme.palette.text.secondary, + }, +})); + +const SocialMediaIconButton = styled(IconButton)(({ theme }) => ({ + padding: 0, + color: theme.palette.text.secondary, + + '&:hover': { + background: 'none', + color: 'inherit', + }, + '& > svg': { + fontSize: '32px', + }, +})); + const Footer: FC = () => { const handleClick = (url: string) => { window.open(url, '_blank'); }; return ( -
-
-
-
- handleClick(env.VITE_FOOTER_LINK_PRIVACY_POLICY)} + + + + + Privacy Policy - - handleClick(env.VITE_FOOTER_LINK_TERMS_OF_SERVICE)} + + Terms of Service - - handleClick(env.VITE_FOOTER_LINK_HUMAN_PROTOCOL)} + + HUMAN Protocol - -
- + + + © 2021 HPF. HUMAN Protocol® is a registered trademark -
-
- + + handleClick(env.VITE_FOOTER_LINK_GITHUB)} - /> - + + + handleClick(env.VITE_FOOTER_LINK_DISCORD)} - /> - + + + handleClick(env.VITE_FOOTER_LINK_X)} - /> - + + + handleClick(env.VITE_FOOTER_LINK_TELEGRAM)} - /> - + + + handleClick(env.VITE_FOOTER_LINK_LINKEDIN)} - /> -
-
-
+ > + + + + + ); }; diff --git a/packages/apps/dashboard/client/src/components/Header/Header.tsx b/packages/apps/dashboard/client/src/components/Header/Header.tsx index 97db534fe9..b323190c2d 100644 --- a/packages/apps/dashboard/client/src/components/Header/Header.tsx +++ b/packages/apps/dashboard/client/src/components/Header/Header.tsx @@ -1,20 +1,33 @@ import { FC, useState } from 'react'; -import clsx from 'clsx'; -import Toolbar from '@mui/material/Toolbar'; + +import AppBar from '@mui/material/AppBar'; +import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import IconButton from '@mui/material/IconButton'; +import { Link as MuiLink } from '@mui/material'; +import CloseIcon from '@mui/icons-material/Close'; import MenuIcon from '@mui/icons-material/Menu'; import Drawer from '@mui/material/Drawer'; -import Box from '@mui/material/Box'; -import Link from '@mui/material/Link'; -import { env } from '@helpers/env'; -import { useNavigate } from 'react-router-dom'; +import Toolbar from '@mui/material/Toolbar'; +import styled from '@mui/material/styles/styled'; +import { Link } from 'react-router-dom'; + import { LogoBlockIcon } from '@components/Icons/LogoBlockIcon'; import { LogoBlockIconMobile } from '@components/Icons/LogoBlockIconMobile'; -import CloseIcon from '@mui/icons-material/Close'; +import { env } from '@helpers/env'; + +const NavLink = styled(MuiLink)(({ theme }) => ({ + color: theme.palette.primary.main, + padding: '6px 8px', + fontSize: '14px', + fontWeight: 600, + lineHeight: '150%', + cursor: 'pointer', + textDecoration: 'none', + width: 'fit-content', +})); const Header: FC = () => { - const navigate = useNavigate(); const [open, setState] = useState(false); const handleClick = (url: string) => { @@ -26,130 +39,104 @@ const Header: FC = () => { }; return ( - - { - navigate('/'); - }} - underline="none" + + - - - - - - - + + + + -
- handleClick(env.VITE_NAVBAR_LINK_GITBOOK)} - > - GitBook - - handleClick(env.VITE_NAVBAR_LINK_FAUCETS)} - > - Faucet - - handleClick(env.VITE_NAVBAR_LINK_HUMAN_WEBSITE)} + - HUMAN Website - - - -
+ GitBook + Faucet + + HUMAN Website + + + + - toggleDrawer(true)} - > - - + toggleDrawer(true)} + > + + - toggleDrawer(false)} - PaperProps={{ - sx: { - width: '80%', - }, - }} - > - - - toggleDrawer(false)} /> - + toggleDrawer(false)} + PaperProps={{ + sx: { + width: '80%', + }, + }} + > + + + toggleDrawer(false)} /> + -
-
- handleClick(env.VITE_NAVBAR_LINK_GITBOOK)} - > - GitBook - -
-
- handleClick(env.VITE_NAVBAR_LINK_FAUCETS)} + + GitBook + Faucet + + HUMAN Website + +
-
- handleClick(env.VITE_NAVBAR_LINK_HUMAN_WEBSITE)} + Launch Jobs + +
- - -
-
-
-
+ Work & Earn + + + + +
+ ); }; diff --git a/packages/apps/dashboard/client/src/components/Home/SmallGraph.tsx b/packages/apps/dashboard/client/src/components/Home/SmallGraph.tsx index 0b2327b214..18c3af1b8f 100644 --- a/packages/apps/dashboard/client/src/components/Home/SmallGraph.tsx +++ b/packages/apps/dashboard/client/src/components/Home/SmallGraph.tsx @@ -1,3 +1,5 @@ +import { Fragment } from 'react'; + import { AreaChart, Area, @@ -8,15 +10,16 @@ import { ResponsiveContainer, TooltipProps, } from 'recharts'; -import Card from '@mui/material/Card'; -import { colorPalette } from '@assets/styles/color-palette'; import Box from '@mui/material/Box'; -import { Typography } from '@mui/material'; +import Card from '@mui/material/Card'; import Stack from '@mui/material/Stack'; import ToggleButtons from '@components/DataEntry/ToggleButtons'; -import { Fragment } from 'react'; +import Typography from '@mui/material/Typography'; + +import { colorPalette } from '@assets/styles/color-palette'; import { formatDate } from '@helpers/formatDate'; import { formatNumber } from '@helpers/formatNumber'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; const CustomSmallChartTooltip = ({ payload, @@ -25,22 +28,19 @@ const CustomSmallChartTooltip = ({ if (active) { return ( - + {payload?.map((elem) => ( - + {formatDate(elem.payload.date, 'MMMM DD, YYYY')} - + {elem.value ? elem.value.toLocaleString('en-US') : ''} @@ -60,10 +60,31 @@ interface SmallGraphProps { title: string; } +const GraphSettings = ({ title }: { title: string }) => ( + + + {title} + + + +); + const SmallGraph = ({ title, graphData }: SmallGraphProps) => { + const isMobile = useIsMobile(); + return ( <> - + {!isMobile && } + { > - - + + { stroke={colorPalette.fog.main} tickFormatter={formatNumber} /> - + } /> - - - {title} - - - + {isMobile && } ); }; diff --git a/packages/apps/dashboard/client/src/components/NothingFound/NothingFound.tsx b/packages/apps/dashboard/client/src/components/NothingFound/NothingFound.tsx index aee9c6aef8..39162a97e4 100644 --- a/packages/apps/dashboard/client/src/components/NothingFound/NothingFound.tsx +++ b/packages/apps/dashboard/client/src/components/NothingFound/NothingFound.tsx @@ -1,17 +1,21 @@ import { FC } from 'react'; + import Link from '@mui/material/Link'; +import Typography from '@mui/material/Typography'; const NothingFound: FC = () => { return ( <> -
Nothing found :(
-
+ Nothing found :( + We couldn't find anything within this criteria.
- Please search by wallet address or escrow address. -
- -
Back Home
+ Please search by wallet address or escrow address. +
+ + + Back Home + ); diff --git a/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.styles.ts b/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.styles.ts index 228cd04a4c..20a24ae2c5 100644 --- a/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.styles.ts +++ b/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.styles.ts @@ -22,10 +22,7 @@ export const gridSx = { overflow: 'hidden', }; -export const muiSelectSx = (mobile: { - isMobile: boolean; - mediaQuery: string; -}) => ({ +export const muiSelectSx = () => ({ backgroundColor: `${colorPalette.white}`, width: 'unset', fontSize: '16px', @@ -41,9 +38,6 @@ export const muiSelectSx = (mobile: { backgroundColor: `${colorPalette.white}`, border: 0, }, - [mobile.mediaQuery]: { - width: 'unset', - }, }); export const menuItemSx = (isSelected: boolean) => ({ @@ -66,16 +60,11 @@ export const muiTextFieldInputPropsSx = (borderColor: string) => ({ padding: '0 5px', }); -export const muiTextFieldSx = (mobile: { - isMobile: boolean; - mediaQuery: string; -}) => ({ +export const muiTextFieldSx = (isMobile: boolean) => ({ fontSize: '16px', '& .MuiOutlinedInput-root': { '& input': { - [mobile.mediaQuery]: { - padding: '12px 0px', - }, + padding: isMobile ? '12px 0px' : '16px 0px', }, '& fieldset': { border: 'none', diff --git a/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.tsx b/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.tsx index 60b49386ca..b57d3b7b28 100644 --- a/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.tsx +++ b/packages/apps/dashboard/client/src/components/SearchBar/SearchBar.tsx @@ -17,7 +17,7 @@ import { } from '@mui/material'; import { colorPalette } from '@assets/styles/color-palette'; import { useFilteredNetworks } from '@utils/hooks/use-filtered-networks'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; import { NetworkIcon } from '@components/NetworkIcon'; import { useWalletSearch } from '@utils/hooks/use-wallet-search'; import { @@ -40,7 +40,7 @@ const SearchBar: FC = ({ className = '', initialInputValue = '', }) => { - const { mobile } = useBreakPoints(); + const isMobile = useIsMobile(); const { filteredNetworks, isLoading } = useFilteredNetworks(); const { filterParams, setChainId, setAddress } = useWalletSearch(); const navigate = useNavigate(); @@ -102,7 +102,9 @@ const SearchBar: FC = ({ if (isLoading) return ; const renderEmptyValue = ( - Network + + Network + ); const renderSelectedValue = ( @@ -113,7 +115,7 @@ const SearchBar: FC = ({ } />
- {mobile.isMobile || filterParams.chainId === -1 + {isMobile || filterParams.chainId === -1 ? null : filteredNetworks.find((n) => n.id === filterParams.chainId)?.name || ''} @@ -133,7 +135,7 @@ const SearchBar: FC = ({ error={!!error} helperText={error} fullWidth - sx={muiTextFieldSx(mobile)} + sx={muiTextFieldSx(isMobile)} InputProps={{ sx: muiTextFieldInputPropsSx( focus ? colorPalette.secondary.main : colorPalette.skyOpacity @@ -146,7 +148,7 @@ const SearchBar: FC = ({ value={filterParams.chainId} displayEmpty - sx={muiSelectSx(mobile)} + sx={muiSelectSx()} onChange={handleSelectChange} renderValue={() => filterParams.chainId === -1 @@ -173,9 +175,9 @@ const SearchBar: FC = ({ @@ -186,13 +188,11 @@ const SearchBar: FC = ({ type="submit" aria-label="search" sx={{ - [mobile.mediaQuery]: { - padding: '4px', - }, + p: 0.5, }} > { underline="none" sx={{ zIndex: 1, + color: 'text.primary', + '&:visited': { + color: 'text.primary', + }, }} > {abbreviateValue(value)} diff --git a/packages/apps/dashboard/client/src/components/SearchResults/TitleSectionWrapper.tsx b/packages/apps/dashboard/client/src/components/SearchResults/TitleSectionWrapper.tsx index 8a91684560..dd8bbf8d8e 100644 --- a/packages/apps/dashboard/client/src/components/SearchResults/TitleSectionWrapper.tsx +++ b/packages/apps/dashboard/client/src/components/SearchResults/TitleSectionWrapper.tsx @@ -1,56 +1,50 @@ +import { FC, PropsWithChildren } from 'react'; + import Stack from '@mui/material/Stack'; -import IconButton from '@mui/material/IconButton'; +import Box from '@mui/material/Box'; import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; import Typography from '@mui/material/Typography'; -import { colorPalette } from '@assets/styles/color-palette'; +import { SxProps } from '@mui/material'; + import CustomTooltip from '@components/CustomTooltip'; -const TitleSectionWrapper = ({ +type Props = { + title: string; + tooltip?: string; + sx?: SxProps; +}; + +const TitleSectionWrapper: FC> = ({ title, - children, tooltip, -}: { - title: string; - children: React.ReactNode; - tooltip?: { - description: string; - }; + sx, + children, }) => { return ( {tooltip ? ( - - - - - + + + {title} ) : ( - + {title} )} - {children} + + {children} + ); }; diff --git a/packages/apps/dashboard/client/src/components/SectionWrapper/index.tsx b/packages/apps/dashboard/client/src/components/SectionWrapper/index.tsx new file mode 100644 index 0000000000..df126af5fe --- /dev/null +++ b/packages/apps/dashboard/client/src/components/SectionWrapper/index.tsx @@ -0,0 +1,23 @@ +import { FC, PropsWithChildren } from 'react'; + +import Card from '@mui/material/Card'; + +const SectionWrapper: FC = ({ children }) => { + return ( + + {children} + + ); +}; + +export default SectionWrapper; diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/components/AddressCell.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/components/AddressCell.tsx index e1699a869a..bfaa2633be 100644 --- a/packages/apps/dashboard/client/src/features/Leaderboard/components/AddressCell.tsx +++ b/packages/apps/dashboard/client/src/features/Leaderboard/components/AddressCell.tsx @@ -8,7 +8,7 @@ export const AddressCell = ({ chainId: string; address: string; }) => ( - + value?.length ? ( - + + + ) : null; const getCategoryLabel = (category: string) => { diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/components/ChainCell.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/components/ChainCell.tsx index 32b40e4831..e341f5b7ba 100644 --- a/packages/apps/dashboard/client/src/features/Leaderboard/components/ChainCell.tsx +++ b/packages/apps/dashboard/client/src/features/Leaderboard/components/ChainCell.tsx @@ -5,7 +5,7 @@ import { getNetwork } from '@utils/config/networks'; export const ChainCell = ({ chainId }: { chainId: number }) => ( { - const apiRef = useGridApiRef(); - const { columns, visibleRows } = useDataGrid(data); - const { customizedColumns, handleSortModelChange, pinnedColSx } = - useDatagridOptions<(typeof visibleRows)[number]>({ - apiRef, - columns, - isRowIdx: true, - pinnedColumnName: 'role', - }); - const { - mobile: { isMobile }, - } = useBreakPoints(); + const { columns, rows } = useDataGrid(data); + const isMobile = useIsMobile(); - const tableIsEmpty = status === 'success' && visibleRows.length === 0; + const tableIsEmpty = status === 'success' && rows.length === 0; const tableMinHeight = status === 'success' && !tableIsEmpty ? 'unset' : 300; return ( ({ + top: 4, + bottom: 0, + })} loading={status === 'pending'} - rows={visibleRows} - columns={customizedColumns} - autosizeOptions={{ - expand: true, - }} - onSortModelChange={handleSortModelChange} slots={{ noRowsOverlay() { if (status === 'error') { @@ -72,38 +66,30 @@ export const DataGridWrapper = ({ return ; }, }} - rowHeight={125} - columnHeaderHeight={72} sx={{ position: 'relative', border: 0, - marginBottom: '16px', + mb: 2, '& .MuiDataGrid-cell': { borderTop: 'none', - padding: '0 8px', + p: 2, overflow: 'visible !important', }, - '& .MuiDataGrid-row': { - borderTop: isMobile ? '15px solid rgb(255, 255, 255)' : '', - }, '& .MuiDataGrid-row:hover': { background: 'rgba(20, 6, 178, 0.04)', }, - '& .MuiDataGrid-cell:focus': { - outline: 'none', - }, - '& .MuiDataGrid-cell:focus-within': { + '& .MuiDataGrid-cell:focus, & .MuiDataGrid-cell:focus-within': { outline: 'none', }, '& .MuiDataGrid-columnSeparator--sideRight': { display: 'none', }, '& .MuiDataGrid-columnHeader': { - padding: '0 16px', + fontSize: '12px', + p: 2, overflow: 'visible !important', - }, - '& .MuiDataGrid-columnHeader:hover': { - color: 'rgb(133, 142, 198)', + textTransform: 'uppercase', + bgcolor: colorPalette.whiteSolid, }, '& .MuiDataGrid-row--borderBottom .MuiDataGrid-withBorderColor': { borderColor: 'transparent', @@ -116,6 +102,7 @@ export const DataGridWrapper = ({ }, '& .MuiDataGrid-columnHeaderTitleContainer': { overflow: 'unset', + whiteSpace: 'normal', }, '& .MuiDataGrid-columnHeader:focus': { outline: 'none', @@ -123,12 +110,10 @@ export const DataGridWrapper = ({ '& .MuiDataGrid-virtualScroller': { position: 'relative', }, - '& .MuiDataGrid-filler': { + '& .MuiDataGrid-filler, & .MuiDataGrid-cellEmpty': { display: 'none', }, - ...pinnedColSx, }} - getRowClassName={() => 'home-page-table-row'} /> ); diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/components/ReputationLabel.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/components/ReputationLabel.tsx deleted file mode 100644 index 7ace7dc2af..0000000000 --- a/packages/apps/dashboard/client/src/features/Leaderboard/components/ReputationLabel.tsx +++ /dev/null @@ -1,36 +0,0 @@ -export const ReputationLabel: React.FC<{ reputation: string }> = ({ - reputation, -}) => { - switch (reputation) { - case 'High': - return ( -
- {reputation} -
- ); - case 'Medium': - return ( -
- {reputation} -
- ); - case 'Low': - return ( -
- {reputation} -
- ); - case 'Coming soon': - return ( -
- {reputation} -
- ); - default: - return ( -
- Coming soon -
- ); - } -}; diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/components/RoleCell.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/components/RoleCell.tsx index 56a154a708..3fb3e6b34f 100644 --- a/packages/apps/dashboard/client/src/features/Leaderboard/components/RoleCell.tsx +++ b/packages/apps/dashboard/client/src/features/Leaderboard/components/RoleCell.tsx @@ -1,6 +1,6 @@ import { Box, Typography } from '@mui/material'; import { Launch as LaunchIcon } from '@mui/icons-material'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; import { Link } from 'react-router-dom'; import { EntityIcon } from './EntityIcon'; import { CaseConverter } from '@utils/case-converter'; @@ -30,46 +30,37 @@ const Wrapper = ({ }; export const RoleCell = ({ + rank, role, websiteUrl, name, }: { + rank: number; role: string; websiteUrl?: string; name?: string; }) => { - const { - mobile: { isMobile }, - } = useBreakPoints(); + const isMobile = useIsMobile(); const humanReadableRole = CaseConverter.convertSnakeToHumanReadable(role); + const formattedName = name ? name.split(' ')[0] : null; + return ( - - {!isMobile && } + + + {rank} + + - - {name ?? humanReadableRole} + + {formattedName ?? humanReadableRole} {websiteUrl ? : null} {name && role ? ( - + {humanReadableRole} ) : null} diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/components/SelectNetwork.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/components/SelectNetwork.tsx index dfc9488530..8ce48e5d04 100644 --- a/packages/apps/dashboard/client/src/features/Leaderboard/components/SelectNetwork.tsx +++ b/packages/apps/dashboard/client/src/features/Leaderboard/components/SelectNetwork.tsx @@ -5,7 +5,7 @@ import MenuItem from '@mui/material/MenuItem'; import Box from '@mui/material/Box'; import { useLeaderboardSearch } from '@utils/hooks/use-leaderboard-search'; import { useFilteredNetworks } from '@utils/hooks/use-filtered-networks'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; import { NetworkIcon } from '@components/NetworkIcon'; import CircularProgress from '@mui/material/CircularProgress'; import { useEffect } from 'react'; @@ -24,9 +24,7 @@ export const SelectNetwork = () => { } }, [chainId, filteredNetworks, setChainId]); - const { - mobile: { isMobile }, - } = useBreakPoints(); + const isMobile = useIsMobile(); const handleChange = (event: SelectChangeEvent) => { const value = Number(event.target.value); @@ -59,6 +57,11 @@ export const SelectNetwork = () => { value={chainId === -1 ? '' : chainId} label="By Network" onChange={handleChange} + sx={{ + '& #network-select svg': { + display: 'none', + }, + }} > {filteredNetworks.map((network) => ( { +import { LeaderBoardData } from '@services/api/use-leaderboard-details'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; +import { useLeaderboardSearch } from '@utils/hooks/use-leaderboard-search'; + +// eslint-disable-next-line react-refresh/only-export-components +const InfoTooltip = ({ title }: { title: string }) => ( + + + +); + +const useDataGrid = (data: LeaderBoardData) => { const { filterParams: { chainId }, } = useLeaderboardSearch(); - const { - mobile: { isMobile }, - } = useBreakPoints(); + const isMobile = useIsMobile(); + const formattedData = useMemo(() => { return data.map((row, idx) => { return { @@ -33,7 +44,7 @@ export const useDataGrid = (data: LeaderBoardData) => { }); }, [data]); - const visibleRows = useMemo(() => { + const rows = useMemo(() => { if (chainId !== -1) { return formattedData.filter((elem) => elem.chainId === chainId); } @@ -41,24 +52,17 @@ export const useDataGrid = (data: LeaderBoardData) => { return formattedData; }, [formattedData, chainId]); - const columns: GridColDef<(typeof visibleRows)[number]>[] = useMemo( + const columns: GridColDef[] = useMemo( () => [ { field: 'role', + flex: 1.5, + minWidth: isMobile ? 250 : 340, sortable: false, - flex: isMobile ? 0.8 : 1.5, - minWidth: isMobile ? 100 : 360, - headerClassName: isMobile - ? 'home-page-table-header pinned-column--header' - : 'home-page-table-header', - cellClassName: isMobile ? 'pinned-column--cell' : '', - renderHeader: () => ( - - Role - - ), + renderHeader: () => Role, renderCell: (params: GridRenderCellParams) => ( { field: 'address', sortable: false, flex: 1, - minWidth: 150, - headerClassName: 'home-page-table-header', + minWidth: isMobile ? 180 : 260, renderHeader: () => ( - - - - - - Address - + + + Address ), renderCell: (params: GridRenderCellParams) => ( @@ -91,21 +86,13 @@ export const useDataGrid = (data: LeaderBoardData) => { }, { field: 'amountStaked', + sortable: false, flex: 1, - minWidth: 130, - headerClassName: 'home-page-table-header', + minWidth: isMobile ? 130 : 260, renderHeader: () => ( - - - - - - Stake - + + + Stake ), valueFormatter: (value: string) => { @@ -119,16 +106,12 @@ export const useDataGrid = (data: LeaderBoardData) => { field: 'chainId', headerName: 'Network', flex: isMobile ? 1 : 1.5, - sortable: false, - minWidth: isMobile ? 150 : 245, - headerClassName: 'home-page-table-header', + minWidth: isMobile ? 130 : 245, renderHeader: () => { return ( <> {isMobile ? ( - - Network - + Network ) : ( )} @@ -141,25 +124,21 @@ export const useDataGrid = (data: LeaderBoardData) => { }, { field: 'category', - minWidth: 200, + sortable: false, + minWidth: isMobile ? 180 : 260, headerName: 'Category', - headerClassName: 'home-page-table-header', - renderHeader: () => ( - - Category - - ), + renderHeader: () => Category, renderCell: (params: GridRenderCellParams) => ( ), }, { field: 'fee', - minWidth: 150, + sortable: false, + minWidth: isMobile ? 100 : 130, headerName: 'Operator Fee', - headerClassName: 'home-page-table-header', renderHeader: () => ( - + Operator Fee ), @@ -180,6 +159,8 @@ export const useDataGrid = (data: LeaderBoardData) => { return { columns, - visibleRows, + rows, }; }; + +export default useDataGrid; diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/hooks/useDatagridOptions.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/hooks/useDatagridOptions.tsx deleted file mode 100644 index 94386e4bdb..0000000000 --- a/packages/apps/dashboard/client/src/features/Leaderboard/hooks/useDatagridOptions.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { Typography } from '@mui/material'; -import { - GridColDef, - GridRenderCellParams, - GridSortModel, - GridCallbackDetails, - GridValidRowModel, -} from '@mui/x-data-grid'; -import { GridApiCommunity } from '@mui/x-data-grid/models/api/gridApiCommunity'; -import { useMemo, useCallback, MutableRefObject } from 'react'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; - -interface IColPossibleOptions { - isRowIdx?: boolean; - pinnedColumnName?: string; -} - -interface IProps extends IColPossibleOptions { - columns: GridColDef[]; - apiRef: MutableRefObject; -} - -export function useDatagridOptions({ - apiRef, - columns, - isRowIdx, - pinnedColumnName, -}: IProps) { - const { - mobile: { isMobile }, - } = useBreakPoints(); - - const handlePinnedColOption = useCallback( - (cols: GridColDef[]) => - cols.map((col) => - col.field === pinnedColumnName - ? { - ...col, - headerClassName: isMobile - ? 'home-page-table-header pinned-column--header' - : 'home-page-table-header', - cellClassName: isMobile ? 'pinned-column--cell' : '', - } - : col - ), - [isMobile, pinnedColumnName] - ); - - const handleRowOrderNum = useCallback( - (cols: GridColDef[]) => { - return isMobile - ? cols - : [ - { - field: 'rowIndex', - headerName: '', - width: 30, - headerClassName: 'home-page-table-header', - sortable: false, - renderCell: (params: GridRenderCellParams) => { - return ( - - {params.value + 1} - - ); - }, - }, - ...cols, - ]; - }, - [isMobile] - ); - - const handleColumnOptions = useCallback( - (cols: GridColDef[]) => { - let colsWithOptions = cols; - if (isRowIdx) { - colsWithOptions = handleRowOrderNum(colsWithOptions); - } - if (pinnedColumnName) { - colsWithOptions = handlePinnedColOption(colsWithOptions); - } - - return colsWithOptions; - }, - [handlePinnedColOption, handleRowOrderNum, isRowIdx, pinnedColumnName] - ); - - const handleSortModelChange = useCallback( - (_model: GridSortModel, details: GridCallbackDetails) => { - apiRef.current.applySorting(); - const sortedRows = details.api.getSortedRows(); - sortedRows.forEach((row, index) => { - apiRef.current.updateRows([{ ...row, rowIndex: index }]); - }); - }, - [apiRef] - ); - - const pinnedColSx = { - '& .pinned-column--header': { - position: 'sticky', - left: 0, - zIndex: 1000, - transform: 'translateZ(0)', - }, - '& .pinned-column--cell': { - position: 'sticky', - left: 0, - zIndex: 1000, - background: '#fff', - transform: 'translateZ(0)', - borderRight: isMobile ? '1px solid rgb(224, 224, 224)' : '', - }, - }; - - const customizedColumns: GridColDef[] = useMemo( - () => handleColumnOptions(columns), - [columns, handleColumnOptions] - ); - - return { - customizedColumns, - handleSortModelChange, - pinnedColSx, - }; -} diff --git a/packages/apps/dashboard/client/src/features/Leaderboard/index.tsx b/packages/apps/dashboard/client/src/features/Leaderboard/index.tsx index 40b5a20ea5..c401e08ebc 100644 --- a/packages/apps/dashboard/client/src/features/Leaderboard/index.tsx +++ b/packages/apps/dashboard/client/src/features/Leaderboard/index.tsx @@ -1,49 +1,53 @@ -import { colorPalette } from '@assets/styles/color-palette'; -import Paper from '@mui/material/Paper'; -import TableContainer from '@mui/material/TableContainer'; -import { LeaderBoardData } from '@services/api/use-leaderboard-details'; +import { FC } from 'react'; + +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Typography from '@mui/material/Typography'; import { useNavigate } from 'react-router-dom'; -import SimpleBar from 'simplebar-react'; + import { SelectNetwork } from './components/SelectNetwork'; import { DataGridWrapper } from './components/DataGridWrapper'; -import { Button, Typography } from '@mui/material'; +import { LeaderBoardData } from '@services/api/use-leaderboard-details'; +import { colorPalette } from '@assets/styles/color-palette'; -export type LeaderboardCommonProps = { +type Props = { data: LeaderBoardData | undefined; status: 'success' | 'error' | 'pending'; error: unknown; + viewAllBanner?: boolean; }; -export const Leaderboard = ({ +export const Leaderboard: FC = ({ data, status, error, viewAllBanner, -}: LeaderboardCommonProps & { - viewAllBanner?: boolean; }) => { const navigate = useNavigate(); return ( - -
+ -
- - - +
+ {viewAllBanner ? ( ) : null} - +
); }; diff --git a/packages/apps/dashboard/client/src/index.css b/packages/apps/dashboard/client/src/index.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/apps/dashboard/client/src/main.tsx b/packages/apps/dashboard/client/src/main.tsx index 6d62a8b395..6ede097359 100644 --- a/packages/apps/dashboard/client/src/main.tsx +++ b/packages/apps/dashboard/client/src/main.tsx @@ -11,7 +11,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const queryClient = new QueryClient({ defaultOptions: { mutations: { retry: 0 }, - queries: { retry: 0 }, + queries: { retry: 0, refetchOnWindowFocus: false }, }, }); diff --git a/packages/apps/dashboard/client/src/pages/Home/HMTPrice.tsx b/packages/apps/dashboard/client/src/pages/Home/HMTPrice.tsx index 20b9474c58..0d7236c038 100644 --- a/packages/apps/dashboard/client/src/pages/Home/HMTPrice.tsx +++ b/packages/apps/dashboard/client/src/pages/Home/HMTPrice.tsx @@ -1,18 +1,21 @@ -import { useHMTPrice } from '../../services/api/use-hmt-price'; +import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; -export function HMTPrice() { - const { data, status } = useHMTPrice(); +import { useHMTPrice } from '../../services/api/use-hmt-price'; + +const HMTPrice = () => { + const { data, isError, isPending, isSuccess } = useHMTPrice(); + return ( -
- - HMT Price + + HMT Price + + {isSuccess && `$${data}`} + {isPending && '...'} + {isError && 'No data'} -
- {status === 'success' && `$${data.hmtPrice}`} - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
+
); -} +}; + +export default HMTPrice; diff --git a/packages/apps/dashboard/client/src/pages/Home/Holders.tsx b/packages/apps/dashboard/client/src/pages/Home/Holders.tsx index d72698569e..d25feb93b3 100644 --- a/packages/apps/dashboard/client/src/pages/Home/Holders.tsx +++ b/packages/apps/dashboard/client/src/pages/Home/Holders.tsx @@ -1,20 +1,22 @@ -import { FormatNumber } from '@components/Home/FormatNumber'; +import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; + +import { FormatNumber } from '@components/Home/FormatNumber'; import { useGeneralStats } from '@services/api/use-general-stats'; -export function Holders() { - const { data, status } = useGeneralStats(); +const Holders = () => { + const { data, isSuccess, isPending, isError } = useGeneralStats(); return ( -
- - Holders + + Holders + + {isSuccess && } + {isPending && '...'} + {isError && 'No data'} -
- {status === 'success' && } - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
+
); -} +}; + +export default Holders; diff --git a/packages/apps/dashboard/client/src/pages/Home/Home.tsx b/packages/apps/dashboard/client/src/pages/Home/Home.tsx index 8082578b9f..73e16c028a 100644 --- a/packages/apps/dashboard/client/src/pages/Home/Home.tsx +++ b/packages/apps/dashboard/client/src/pages/Home/Home.tsx @@ -1,124 +1,127 @@ -import PageWrapper from '@components/PageWrapper'; -import SearchBar from '@components/SearchBar/SearchBar'; -import ShadowIcon from '@components/ShadowIcon'; -import Typography from '@mui/material/Typography'; +import { FC } from 'react'; + +import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; -import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; import Divider from '@mui/material/Divider'; +import Grid from '@mui/material/Unstable_Grid2'; +import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; +import Typography from '@mui/material/Typography'; import { Link } from 'react-router-dom'; +import styled from '@mui/material/styles/styled'; + +import PageWrapper from '@components/PageWrapper'; +import SearchBar from '@components/SearchBar/SearchBar'; +import ShadowIcon from '@components/ShadowIcon'; import { Leaderboard } from './Leaderboard'; import GraphSwiper from '@components/Home/GraphSwiper'; -import { HMTPrice } from '@pages/Home/HMTPrice'; -import { TotalNumberOfTasks } from '@pages/Home/TotalNumberOfTasks'; -import { Holders } from '@pages/Home/Holders'; -import { TotalTransactions } from '@pages/Home/TotalTransactions'; +import HMTPrice from '@pages/Home/HMTPrice'; +import TotalNumberOfTasks from '@pages/Home/TotalNumberOfTasks'; +import Holders from '@pages/Home/Holders'; +import TotalTransactions from '@pages/Home/TotalTransactions'; import { LeaderboardIcon } from '@components/Icons/LeaderboardIcon'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; -import { colorPalette } from '@assets/styles/color-palette'; import CustomTooltip from '@components/CustomTooltip'; -const Home: React.FC = () => { - const { - mobile: { isMobile }, - } = useBreakPoints(); +import { useIsMobile } from '@utils/hooks/use-breakpoints'; + +const CardWrapper = styled(Grid)(({ theme }) => ({ + display: 'flex', + background: theme.palette.white.main, + borderRadius: '16px', + padding: '24px 32px', + [theme.breakpoints.up('md')]: { + height: 300, + }, + [theme.breakpoints.down('md')]: { + height: 'auto', + }, +})); + +const InfoTooltip = ({ title }: { title: string }) => ( + + + +); + +const renderViewChartsButton = (show: boolean) => { + if (show) { + return ( + + ); + } else { + return null; + } +}; + +const Home: FC = () => { + const isMobile = useIsMobile(); + return ( -
- - All HUMAN activity. In one place. - - -
-
-
-
Token
-
-
- - - -
- -
- -
-
- - - -
- -
-
-
-
- Data Overview - -
-
-
- - - -
- -
- -
-
- - - -
- -
-
-
- -
-
+ + Data Overview (All networks) + + {renderViewChartsButton(!isMobile)} +
+ + + + + + + + + + +
+ + + + {renderViewChartsButton(isMobile)} + + + { + const { data, isError, isPending, isSuccess } = useHcaptchaGeneralStats(); return ( -
- - Total Number of Tasks + + Total Number of Tasks + + {isSuccess && } + {isPending && '...'} + {isError && 'No data'} -
- {status === 'success' && } - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
+
); -} +}; + +export default TotalNumberOfTasks; diff --git a/packages/apps/dashboard/client/src/pages/Home/TotalTransactions.tsx b/packages/apps/dashboard/client/src/pages/Home/TotalTransactions.tsx index 82bf49cab7..6c4ada399a 100644 --- a/packages/apps/dashboard/client/src/pages/Home/TotalTransactions.tsx +++ b/packages/apps/dashboard/client/src/pages/Home/TotalTransactions.tsx @@ -1,22 +1,22 @@ -import { FormatNumber } from '@components/Home/FormatNumber'; +import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; + +import { FormatNumber } from '@components/Home/FormatNumber'; import { useGeneralStats } from '@services/api/use-general-stats'; -export function TotalTransactions() { - const { data, status } = useGeneralStats(); +const TotalTransactions = () => { + const { data, isError, isPending, isSuccess } = useGeneralStats(); return ( -
- - Total Transactions + + Total Transactions + + {isSuccess && } + {isPending && '...'} + {isError && 'No data'} -
- {status === 'success' && ( - - )} - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
+
); -} +}; + +export default TotalTransactions; diff --git a/packages/apps/dashboard/client/src/pages/Leaderboard/index.tsx b/packages/apps/dashboard/client/src/pages/Leaderboard/index.tsx index 1a2a7f2d48..60f93d1732 100644 --- a/packages/apps/dashboard/client/src/pages/Leaderboard/index.tsx +++ b/packages/apps/dashboard/client/src/pages/Leaderboard/index.tsx @@ -5,7 +5,7 @@ import { Leaderboard } from '../../features/Leaderboard/index'; import { useLeaderboardDetails } from '@services/api/use-leaderboard-details'; import { LeaderboardIcon } from '@components/Icons/LeaderboardIcon'; -export const LeaderBoard = () => { +const LeaderBoard = () => { const { data, status, error } = useLeaderboardDetails(); return ( @@ -20,3 +20,5 @@ export const LeaderBoard = () => { ); }; + +export default LeaderBoard; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx index 2a774f6b9c..f258eeb751 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx @@ -1,11 +1,12 @@ -import Typography from '@mui/material/Typography'; -import Card from '@mui/material/Card'; import Box from '@mui/material/Box'; import Stack from '@mui/material/Stack'; -import { colorPalette } from '@assets/styles/color-palette'; +import Typography from '@mui/material/Typography'; + import TitleSectionWrapper from '@components/SearchResults'; +import SectionWrapper from '@components/SectionWrapper'; +import HmtBalance from '../HmtBalance'; + import { AddressDetailsEscrowSchema } from '@services/api/use-address-details'; -import { HMTBalance } from '@pages/SearchResults/EscrowAddress/HMTBalance'; const EscrowAddress = ({ data: { @@ -24,57 +25,43 @@ const EscrowAddress = ({ data: AddressDetailsEscrowSchema; }) => { return ( - + {token} {balance !== undefined && balance !== null ? ( - - + + ) : null} {factoryAddress} - + {totalFundedAmount} HMT - + {amountPaid} HMT @@ -86,13 +73,11 @@ const EscrowAddress = ({ sx={{ padding: '3px 8px', borderRadius: '16px', - border: `1px solid ${colorPalette.secondary.light}`, + border: '1px solid', + borderColor: 'secondary.light', }} > - + {status} @@ -100,9 +85,7 @@ const EscrowAddress = ({ {launcher} @@ -111,38 +94,34 @@ const EscrowAddress = ({ {exchangeOracle} {recordingOracle} {reputationOracle} - + ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx deleted file mode 100644 index 839e28393a..0000000000 --- a/packages/apps/dashboard/client/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { colorPalette } from '@assets/styles/color-palette'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import { useHMTPrice } from '@services/api/use-hmt-price'; - -export const HMTBalance = ({ HMTBalance }: { HMTBalance: number }) => { - const { data, isError, isPending } = useHMTPrice(); - - if (isError) { - return N/A; - } - - if (isPending) { - return ...; - } - const HMTBalanceInDollars = HMTBalance * data.hmtPrice; - - return ( - - {HMTBalance} - - {`HMT($${HMTBalanceInDollars.toFixed(2)})`} - - - ); -}; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/HmtBalance/index.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/HmtBalance/index.tsx new file mode 100644 index 0000000000..b942cac755 --- /dev/null +++ b/packages/apps/dashboard/client/src/pages/SearchResults/HmtBalance/index.tsx @@ -0,0 +1,52 @@ +import { FC } from 'react'; + +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import { NumericFormat } from 'react-number-format'; + +import { useHMTPrice } from '@services/api/use-hmt-price'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; + +type Props = { + balance?: number | null; +}; + +const HmtBalance: FC = ({ balance }) => { + const { data, isError, isPending } = useHMTPrice(); + const isMobile = useIsMobile(); + + if (isError) { + return N/A; + } + + if (isPending) { + return ...; + } + + const _balance = + Number(balance) < 1 ? Number(balance) * 1e18 : Number(balance); + const balanceInDollars = balance ? (_balance * data).toFixed(2) : 0; + + return ( + + + + + + {`HMT($${balanceInDollars})`} + + + ); +}; + +export default HmtBalance; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/HmtPrice/index.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/HmtPrice/index.tsx new file mode 100644 index 0000000000..71c97576a8 --- /dev/null +++ b/packages/apps/dashboard/client/src/pages/SearchResults/HmtPrice/index.tsx @@ -0,0 +1,22 @@ +import { Typography, Stack } from '@mui/material'; + +import { useHMTPrice } from '@services/api/use-hmt-price'; + +const HmtPrice = () => { + const { data, isError, isPending, isSuccess } = useHMTPrice(); + + return ( + + + $ + + + {isError && 'N/A'} + {isPending && '...'} + {isSuccess && data} + + + ); +}; + +export default HmtPrice; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/KVStore/index.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/KVStore/index.tsx new file mode 100644 index 0000000000..3078b19642 --- /dev/null +++ b/packages/apps/dashboard/client/src/pages/SearchResults/KVStore/index.tsx @@ -0,0 +1,57 @@ +import Typography from '@mui/material/Typography'; + +import TableBody from '@mui/material/TableBody'; +import TableContainer from '@mui/material/TableContainer'; +import Table from '@mui/material/Table'; +import TableCell from '@mui/material/TableCell'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; + +import SectionWrapper from '@components/SectionWrapper'; +import useKvstoreData from '@services/api/use-kvstore-data'; + +const KVStore = () => { + const { data } = useKvstoreData(); + + if (data?.length === 0) { + return null; + } + + return ( + + + KV Store + + + + + + Key + Value + + + + {data?.map((row) => ( + + {row.key} + {row.value} + + ))} + +
+
+
+ ); +}; + +export default KVStore; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/ReputationScore/index.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/ReputationScore/index.tsx new file mode 100644 index 0000000000..7241d36ba9 --- /dev/null +++ b/packages/apps/dashboard/client/src/pages/SearchResults/ReputationScore/index.tsx @@ -0,0 +1,58 @@ +import { FC } from 'react'; + +import { Reputation } from '@services/api/use-leaderboard-details'; +import { colorPalette } from '@assets/styles/color-palette'; +import { Box, Typography } from '@mui/material'; + +type Props = { + reputation: Reputation; +}; + +type ReputationAttributes = { + title: string; + colors: { title: string; border: string }; +}; + +const reputationAttributes: Record = { + High: { + title: 'High', + colors: { + title: colorPalette.success.main, + border: colorPalette.success.light, + }, + }, + Medium: { + title: 'Medium', + colors: { + title: colorPalette.warning.main, + border: colorPalette.warning.light, + }, + }, + Low: { + title: 'Low', + colors: { + title: colorPalette.orange.main, + border: colorPalette.orange.light, + }, + }, + Unknown: { + title: 'Coming soon', + colors: { + title: colorPalette.ocean.main, + border: colorPalette.ocean.light, + }, + }, +}; + +const ReputationScore: FC = ({ reputation }) => { + const colors = reputationAttributes[reputation].colors; + return ( + + + {reputationAttributes[reputation].title} + + + ); +}; + +export default ReputationScore; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetails.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetails.tsx index 24f69c717a..e1215c99c4 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetails.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetails.tsx @@ -1,55 +1,74 @@ -import Card from '@mui/material/Card'; -import Typography from '@mui/material/Typography'; import Box from '@mui/material/Box'; -import { colorPalette } from '@assets/styles/color-palette'; +import Chip from '@mui/material/Chip'; +import Link from '@mui/material/Link'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; import Stack from '@mui/material/Stack'; -import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; +import { Role } from '@human-protocol/sdk'; + +import SectionWrapper from '@components/SectionWrapper'; +import TitleSectionWrapper from '@components/SearchResults/TitleSectionWrapper'; +import { RoleDetailsEscrowsTable } from '@pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable'; +import KVStore from '../KVStore'; +import ReputationScore from '../ReputationScore'; +import StakeInfo from '../StakeInfo'; +import HmtBalance from '../HmtBalance'; +import HmtPrice from '../HmtPrice'; + import ReputationOracleIcon from '@assets/icons/reputation-oracle.svg'; import ExchangeOracleIcon from '@assets/icons/exchange-oracle.svg'; import JobLauncherIcon from '@assets/icons/job-launcher.svg'; import RecordingOracleIcon from '@assets/icons/recording-oracle.svg'; -import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; + import { AddressDetailsOperator } from '@services/api/use-address-details'; -import { getNetwork } from '@utils/config/networks'; -import { useWalletSearch } from '@utils/hooks/use-wallet-search'; -import { RoleDetailsEscrowsTable } from '@pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable'; -import { Reputation } from '@services/api/use-leaderboard-details'; import { env } from '@helpers/env'; -import { FormatNumberWithDecimals } from '@components/Home/FormatNumber'; -import CustomTooltip from '@components/CustomTooltip'; -import { Role } from '@human-protocol/sdk'; +import { colorPalette } from '@assets/styles/color-palette'; interface RoleInfoProps { title: string; points: string[]; + role: string; } -const RoleInformation = ({ title, points }: RoleInfoProps) => { +const renderRoleIcon = (role: string | null) => { + if (!role) return null; + + const roleIcons = { + [Role.ReputationOracle]: , + [Role.ExchangeOracle]: , + [Role.JobLauncher]: , + [Role.RecordingOracle]: , + }; + + return roleIcons[role]; +}; + +const RoleInformation = ({ title, points, role }: RoleInfoProps) => { return ( - - {title} -
    + + {renderRoleIcon(role)} + + {title} + + {points.map((elem, idx) => ( -
  • + {elem} -
  • + ))} -
-
+ +
); }; -const RenderRoleDetailsInfo = ({ - role, -}: { - role: AddressDetailsOperator['role']; -}) => { +const renderRoleDetailsInfo = (role: string | null) => { if (!role) { return null; } @@ -94,297 +113,122 @@ const RenderRoleDetailsInfo = ({ return null; } - return ; -}; - -const renderReputationTitle = (reputation: Reputation) => { - const reputationAttributes: Record< - Reputation, - { title: string; colors: { title: string; border: string } } - > = { - High: { - title: 'High', - colors: { - title: colorPalette.success.main, - border: colorPalette.success.light, - }, - }, - Medium: { - title: 'Medium', - colors: { - title: colorPalette.warning.main, - border: colorPalette.warning.light, - }, - }, - - Low: { - title: 'Low', - colors: { - title: colorPalette.orange.main, - border: colorPalette.orange.light, - }, - }, - Unknown: { - title: 'Coming soon', - colors: { - title: colorPalette.ocean.main, - border: colorPalette.ocean.light, - }, - }, - }; - - const colors = reputationAttributes[reputation].colors; - return ( - - - {reputationAttributes[reputation].title} - - + ); }; -const renderRoleIcon = (role: AddressDetailsOperator['role']) => { - if (!role) return null; - const roleIcons = { - [Role.ReputationOracle]: , - [Role.ExchangeOracle]: , - [Role.JobLauncher]: , - [Role.RecordingOracle]: , - }; - - return roleIcons[role]; -}; - -const RoleDetails = ({ - data: { +const RoleDetails = ({ data }: { data: AddressDetailsOperator }) => { + const { + balance, role, - chainId, reputation, amountJobsProcessed, amountStaked, amountLocked, - }, -}: { - data: AddressDetailsOperator; -}) => { - const { filterParams } = useWalletSearch(); + amountWithdrawable, + url, + fee, + jobTypes, + } = data; return ( <> - - - - Overview - + + + Overview {env.VITE_HUMANPROTOCOL_CORE_ARCHITECTURE ? ( - + HUMAN Protocol core architecture ) : null} - + + + + + + - - Role - - - {renderRoleIcon(role)} - - - - - - Network - - - {getNetwork(chainId)?.name || ''} - - - + + - - - - - - - Reputation Score - - {renderReputationTitle(reputation)} - - - + {url && ( + + + {url} + + + )} + {jobTypes && jobTypes?.length > 0 && ( + - Jobs Launched - - {amountJobsProcessed} - - - - - - - + {jobTypes.map((jobType) => ( + + ))} + + + )} + {fee && ( + + {fee}% + + )} + - Stake Info - - - - {amountStaked !== undefined && amountStaked !== null ? ( - - - Tokens Staked - - - - - - - HMT - - - - ) : null} - {amountLocked !== undefined && amountLocked !== null ? ( - - - Tokens Locked - - - - - - - HMT - - - - ) : null} + {amountJobsProcessed} + - - - {filterParams.address && filterParams.chainId ? ( - - ) : null} + + + + + ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx index 9a01f47b1c..babb913b9f 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx @@ -1,22 +1,19 @@ -import Card from '@mui/material/Card'; +import { useEffect } from 'react'; + +import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; -import Box from '@mui/material/Box'; -import { AddressDetailsOperator } from '@services/api/use-address-details'; import TableContainer from '@mui/material/TableContainer'; import Table from '@mui/material/Table'; -import { EscrowsTableBody } from '@pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody'; import TablePagination from '@mui/material/TablePagination'; -import { useEscrowDetailsDto } from '@utils/hooks/use-escrows-details-dto'; -import { useEscrowDetails } from '@services/api/use-escrows-details'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; -import { Stack } from '@mui/material'; -export const RoleDetailsEscrowsTable = ({ - role, -}: { - role: AddressDetailsOperator['role']; -}) => { +import { EscrowsTableBody } from '@pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody'; +import SectionWrapper from '@components/SectionWrapper'; +import { useEscrowDetailsDto } from '@utils/hooks/use-escrows-details-dto'; +import { useEscrowDetails } from '@services/api/use-escrows-details'; + +export const RoleDetailsEscrowsTable = ({ role }: { role: string | null }) => { const { data } = useEscrowDetails({ role }); const { pagination: { page, pageSize, lastPageIndex }, @@ -25,84 +22,70 @@ export const RoleDetailsEscrowsTable = ({ setPrevPage, } = useEscrowDetailsDto(); + useEffect(() => { + return () => { + setPageSize(10); + }; + }, [setPageSize]); + return ( - - - + + Escrows + + + - Escrows - - -
- - - - -
-
- + + + + + + + {}} + page={page} + rowsPerPage={pageSize} + onRowsPerPageChange={(event) => { + setPageSize(Number(event.target.value)); }} - > - {}} - page={page} - rowsPerPage={pageSize} - onRowsPerPageChange={(event) => { - setPageSize(Number(event.target.value)); - }} - rowsPerPageOptions={[5, 10]} - labelDisplayedRows={({ from, to }) => { - const effectiveTo = data?.results - ? from + data.results.length - 1 - : to; - return `${from}–${effectiveTo}`; - }} - component="div" - slotProps={{ - actions: { - nextButton: { - onClick: () => { - setNextPage(); - }, - disabled: - lastPageIndex !== undefined && - (page === lastPageIndex || lastPageIndex - 1 === page), + rowsPerPageOptions={[5, 10]} + labelDisplayedRows={({ from, to }) => { + const effectiveTo = data?.results + ? from + data.results.length - 1 + : to; + return `${from}–${effectiveTo}`; + }} + component="div" + slotProps={{ + actions: { + nextButton: { + onClick: () => { + setNextPage(); }, - previousButton: { - onClick: () => { - setPrevPage(); - }, + disabled: + lastPageIndex !== undefined && + (page === lastPageIndex || lastPageIndex - 1 === page), + }, + previousButton: { + onClick: () => { + setPrevPage(); }, }, - }} - /> - -
-
+ }, + }} + /> + + ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/SearchResults.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/SearchResults.tsx index 9c3db5f7f4..ab9d49fdf2 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/SearchResults.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/SearchResults.tsx @@ -14,7 +14,6 @@ import Loader from '@components/Loader'; import { getNetwork } from '@utils/config/networks'; import { AddressDetails, - AddressDetailsWallet, useAddressDetails, } from '@services/api/use-address-details'; import { handleErrorMessage } from '@services/handle-error-message'; @@ -22,6 +21,7 @@ import RoleDetails from '@pages/SearchResults/RoleDetails/RoleDetails'; import { AxiosError } from 'axios'; import { WalletIcon } from '@components/Icons/WalletIcon'; import { EscrowAddressIcon } from '@components/Icons/EscrowAddressIcon'; +import { WalletAddressTransactionsTable } from './WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable'; const renderCurrentResultType = ( addressDetails: AddressDetails, @@ -84,16 +84,19 @@ const Results = () => { return ; } - const selectedWalletData: AddressDetailsWallet | undefined = + const showTransactions = !!data.wallet || !!data.operator; + + const walletData = data.wallet || (data.operator && data.operator.role === null ? data.operator : undefined); return ( <> {renderCurrentResultType(data, filterParams.address)} @@ -102,12 +105,19 @@ const Results = () => { {data.operator && data.operator.role ? ( ) : null} - {selectedWalletData ? : null} - {data.escrow ? : null} + {walletData ? : null} + {data.escrow && } + {showTransactions && } ); }; +enum ParamsStatus { + LOADING = 'loading', + ERROR = 'error', + SUCCESS = 'success', +} + const SearchResults = () => { const location = useLocation(); const { chainId: urlChainId, address: urlAddress } = useParams(); @@ -116,20 +126,21 @@ const SearchResults = () => { setChainId, filterParams: { chainId, address }, } = useWalletSearch(); - const [paramsStatus, setParamsStatus] = useState< - 'loading' | 'error' | 'success' - >('loading'); + + const [paramsStatus, setParamsStatus] = useState( + ParamsStatus.LOADING + ); useEffect(() => { - setParamsStatus('loading'); + setParamsStatus(ParamsStatus.LOADING); }, [location]); useEffect(() => { - if (paramsStatus === 'success') return; + if (paramsStatus === ParamsStatus.SUCCESS) return; if (urlAddress) { setAddress(urlAddress); } else { - setParamsStatus('error'); + setParamsStatus(ParamsStatus.ERROR); return; } const chainIdFromUrl = Number(urlChainId); @@ -140,7 +151,7 @@ const SearchResults = () => { ) { setChainId(chainIdFromUrl); } else { - setParamsStatus('error'); + setParamsStatus(ParamsStatus.ERROR); } }, [ address, @@ -153,8 +164,8 @@ const SearchResults = () => { ]); useEffect(() => { - if (address && chainId && paramsStatus !== 'success') { - setParamsStatus('success'); + if (address && chainId && paramsStatus !== ParamsStatus.SUCCESS) { + setParamsStatus(ParamsStatus.SUCCESS); } }, [address, chainId, paramsStatus]); @@ -162,11 +173,13 @@ const SearchResults = () => { - {paramsStatus === 'loading' && } - {paramsStatus === 'error' && ( - Something went wrong + {paramsStatus === ParamsStatus.LOADING && ( + + )} + {paramsStatus === ParamsStatus.ERROR && ( + Something went wrong )} - {paramsStatus === 'success' && } + {paramsStatus === ParamsStatus.SUCCESS && } ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/StakeInfo/index.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/StakeInfo/index.tsx new file mode 100644 index 0000000000..2d1d293b0b --- /dev/null +++ b/packages/apps/dashboard/client/src/pages/SearchResults/StakeInfo/index.tsx @@ -0,0 +1,83 @@ +import { FC } from 'react'; + +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import { NumericFormat } from 'react-number-format'; + +import SectionWrapper from '@components/SectionWrapper'; + +import { useIsMobile } from '@utils/hooks/use-breakpoints'; + +type Props = { + amountStaked?: number | null; + amountLocked?: number | null; + amountWithdrawable?: number | null; +}; + +const renderAmount = (amount: number | null | undefined, isMobile: boolean) => { + return ( + + + + + + HMT + + + ); +}; + +const StakeInfo: FC = ({ + amountStaked, + amountLocked, + amountWithdrawable, +}) => { + const isMobile = useIsMobile(); + if (!amountStaked && !amountLocked && !amountWithdrawable) return null; + + return ( + + + Stake Info + + + {Number.isFinite(amountStaked) && ( + + + Staked Tokens + + {renderAmount(amountStaked, isMobile)} + + )} + {Number.isFinite(amountLocked) && ( + + + Locked Tokens + + {renderAmount(amountLocked, isMobile)} + + )} + {Number.isFinite(amountWithdrawable) && ( + + + Withdrawable Tokens + + {renderAmount(amountWithdrawable, isMobile)} + + )} + + + ); +}; + +export default StakeInfo; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddress.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddress.tsx index c127024544..89ac4b736a 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddress.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddress.tsx @@ -1,100 +1,86 @@ -import Typography from '@mui/material/Typography'; -import Card from '@mui/material/Card'; +import { FC } from 'react'; + import Stack from '@mui/material/Stack'; -import TitleSectionWrapper from '@components/SearchResults'; -import { colorPalette } from '@assets/styles/color-palette'; -import { AddressDetailsWallet } from '@services/api/use-address-details'; -import { useHMTPrice } from '@services/api/use-hmt-price'; -import { WalletAddressTransactionsTable } from '@pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable'; -import { useWalletSearch } from '@utils/hooks/use-wallet-search'; +import Typography from '@mui/material/Typography'; import { NumericFormat } from 'react-number-format'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; -const HmtPrice = () => { - const { - data: hmtPrice, - isError: isHmtPriceError, - isPending: isHmtPricePending, - } = useHMTPrice(); - - if (isHmtPriceError) { - return N/A; - } +import TitleSectionWrapper from '@components/SearchResults'; +import SectionWrapper from '@components/SectionWrapper'; +import HmtBalance from '../HmtBalance'; +import HmtPrice from '../HmtPrice'; +import KVStore from '../KVStore'; +import ReputationScore from '../ReputationScore'; +import StakeInfo from '../StakeInfo'; - if (isHmtPricePending) { - return ...; - } +import { + AddressDetailsOperator, + AddressDetailsWallet, +} from '@services/api/use-address-details'; +import { useIsMobile } from '@utils/hooks/use-breakpoints'; - return ( - - - - <>{hmtPrice.hmtPrice} - - - $ - - - - ); +type Props = { + data: AddressDetailsWallet | AddressDetailsOperator; }; -const WalletAddress = ({ - data: { balance }, -}: { - data: AddressDetailsWallet; -}) => { - const { filterParams } = useWalletSearch(); - const { mobile } = useBreakPoints(); +const WalletAddress: FC = ({ data }) => { + const { + balance, + amountStaked, + amountLocked, + reputation, + amountWithdrawable, + } = data; + const isMobile = useIsMobile(); + const isWallet = 'totalAmountReceived' in data; return ( <> - + + Overview - + + + + + + + + + {isWallet && ( + HMT - - - + + )} - - - {filterParams.address && filterParams.chainId ? ( - - ) : null} + + + ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx index 62992706eb..10b3927722 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx @@ -1,13 +1,18 @@ -import Typography from '@mui/material/Typography'; -import Card from '@mui/material/Card'; -import TableContainer from '@mui/material/TableContainer'; -import Table from '@mui/material/Table'; +import { useEffect } from 'react'; + import SimpleBar from 'simplebar-react'; +import Table from '@mui/material/Table'; +import TableContainer from '@mui/material/TableContainer'; +import TableFooter from '@mui/material/TableFooter'; import TablePagination from '@mui/material/TablePagination'; +import TableRow from '@mui/material/TableRow'; +import Typography from '@mui/material/Typography'; + import { TransactionsTableHead } from '@pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead'; import { TransactionsTableBody } from '@pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody'; +import SectionWrapper from '@components/SectionWrapper'; + import { useTransactionDetailsDto } from '@utils/hooks/use-transactions-details-dto'; -import { TableFooter } from '@mui/material'; import { useTransactionDetails } from '@services/api/use-transaction-details'; export const WalletAddressTransactionsTable = () => { @@ -19,75 +24,82 @@ export const WalletAddressTransactionsTable = () => { setPrevPage, } = useTransactionDetailsDto(); + useEffect(() => { + return () => { + setPageSize(10); + }; + }, [setPageSize]); + return ( - - + + Transactions - - - {}} - page={page} - component="td" - rowsPerPage={pageSize} - onRowsPerPageChange={(event) => { - setPageSize(Number(event.target.value)); - }} - rowsPerPageOptions={[5, 10]} - labelDisplayedRows={({ from, to }) => { - const effectiveTo = data?.results - ? from + data.results.length - 1 - : to; - return `${from}–${effectiveTo}`; - }} - slotProps={{ - actions: { - nextButton: { - onClick: () => { - setNextPage(); - }, - disabled: - lastPageIndex !== undefined && - (page === lastPageIndex || - lastPageIndex - 1 === page), +
+
+ + + + {}} + page={page} + component="td" + rowsPerPage={pageSize} + onRowsPerPageChange={(event) => { + setPageSize(Number(event.target.value)); + }} + rowsPerPageOptions={[5, 10]} + labelDisplayedRows={({ from, to }) => { + const effectiveTo = data?.results + ? from + data.results.length - 1 + : to; + return `${from}–${effectiveTo}`; + }} + slotProps={{ + actions: { + nextButton: { + onClick: () => { + setNextPage(); }, - previousButton: { - onClick: () => { - setPrevPage(); - }, + disabled: + lastPageIndex !== undefined && + (page === lastPageIndex || lastPageIndex - 1 === page), + }, + previousButton: { + onClick: () => { + setPrevPage(); }, }, - }} - /> - - -
- + }, + }} + /> + + +
-
+ ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx index 9480c5cd7d..61b1a638b9 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx @@ -1,69 +1,69 @@ -import { colorPalette } from '@assets/styles/color-palette'; import Box from '@mui/material/Box/Box'; import Typography from '@mui/material/Typography'; -import { capitalize } from '@mui/material'; -export const TransactionTableCellMethod = ({ method }: { method: string }) => { - const methodAttributes: Record< - string, - { color: { text: string; border: string } } - > = { - withdraw: { - color: { - text: colorPalette.error.main, - border: colorPalette.error.light, - }, +import { colorPalette } from '@assets/styles/color-palette'; + +const methodAttributes: Record< + string, + { color: { text: string; border: string } } +> = { + withdraw: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, }, - cancel: { - color: { - text: colorPalette.error.main, - border: colorPalette.error.light, - }, + }, + cancel: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, }, - stake: { - color: { - text: colorPalette.success.main, - border: colorPalette.success.light, - }, + }, + stake: { + color: { + text: colorPalette.success.main, + border: colorPalette.success.light, }, - unstake: { - color: { - text: colorPalette.error.main, - border: colorPalette.error.light, - }, + }, + unstake: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, }, - slash: { - color: { - text: colorPalette.error.main, - border: colorPalette.error.light, - }, + }, + slash: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, }, - stakeWithdrawn: { - color: { - text: colorPalette.error.main, - border: colorPalette.error.light, - }, + }, + stakeWithdrawn: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, }, - withdrawFees: { - color: { - text: colorPalette.error.main, - border: colorPalette.error.light, - }, + }, + withdrawFees: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, }, - approve: { - color: { - text: colorPalette.warning.main, - border: colorPalette.warning.light, - }, + }, + approve: { + color: { + text: colorPalette.warning.main, + border: colorPalette.warning.light, }, - complete: { - color: { - text: colorPalette.success.main, - border: colorPalette.success.light, - }, + }, + complete: { + color: { + text: colorPalette.success.main, + border: colorPalette.success.light, }, - }; + }, +}; +export const TransactionTableCellMethod = ({ method }: { method: string }) => { const currentStatusColors = methodAttributes[method]?.color || { text: colorPalette.primary.main, border: colorPalette.primary.light, @@ -71,20 +71,14 @@ export const TransactionTableCellMethod = ({ method }: { method: string }) => { return ( - - {capitalize(method)} + + {method} ); diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx index 6e18d806de..e1f229a167 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx @@ -16,7 +16,7 @@ export const TransactionTableCellValue = ({ value }: { value: string }) => { return ( {formatHMTDecimals(value)} - HMT + HMT ); }; diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx index 1bc9c3a454..d5b7f153af 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx @@ -6,6 +6,7 @@ import Box from '@mui/material/Box'; import IconButton from '@mui/material/IconButton'; import CircularProgress from '@mui/material/CircularProgress'; import AddCircleIcon from '@mui/icons-material/AddCircle'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; import RemoveCircleIcon from '@mui/icons-material/RemoveCircle'; import AbbreviateClipboard from '@components/SearchResults/AbbreviateClipboard'; import { colorPalette } from '@assets/styles/color-palette'; @@ -85,7 +86,7 @@ export const TransactionsTableBody: React.FC = () => { > - + {elem.internalTransactions.length > 0 && ( toggleRow(idx)} size="small"> {expandedRows[idx] ? ( @@ -109,11 +110,13 @@ export const TransactionsTableBody: React.FC = () => { /> - {' '} - + + + + {elem.block} @@ -140,10 +143,13 @@ export const TransactionsTableBody: React.FC = () => { /> - + + + + diff --git a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx index 24d5723e1d..1e7c35be6d 100644 --- a/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx +++ b/packages/apps/dashboard/client/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx @@ -1,91 +1,61 @@ import Typography from '@mui/material/Typography'; import Stack from '@mui/material/Stack'; -import { colorPalette } from '@assets/styles/color-palette'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import TableCell from '@mui/material/TableCell'; -import IconButton from '@mui/material/IconButton'; import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; + import CustomTooltip from '@components/CustomTooltip'; +const InfoTooltip = ({ title }: { title: string }) => ( + + + +); + export const TransactionsTableHead = () => { return ( - + - - - - - - - Transaction Hash - + Transaction Hash + - - - - - - Method + Method + - From + From - To + To - - - - - - Block + Block + - - - - - - Value + Value + diff --git a/packages/apps/dashboard/client/src/services/api-paths.ts b/packages/apps/dashboard/client/src/services/api-paths.ts index 656a08c685..dfa16f9f30 100644 --- a/packages/apps/dashboard/client/src/services/api-paths.ts +++ b/packages/apps/dashboard/client/src/services/api-paths.ts @@ -29,4 +29,7 @@ export const apiPaths = { enabledChains: { path: '/networks/operating', }, + kvstore: { + path: '/details/kvstore', + }, } as const; diff --git a/packages/apps/dashboard/client/src/services/api/use-address-details.tsx b/packages/apps/dashboard/client/src/services/api/use-address-details.tsx index 258b3588cc..51a4487c6e 100644 --- a/packages/apps/dashboard/client/src/services/api/use-address-details.tsx +++ b/packages/apps/dashboard/client/src/services/api/use-address-details.tsx @@ -29,6 +29,12 @@ const walletSchema = z.object({ chainId: z.number(), address: z.string(), balance: z.string().transform(transformOptionalTokenAmount), + amountStaked: z.string().transform(transformOptionalTokenAmount), + amountLocked: z.string().transform(transformOptionalTokenAmount), + amountWithdrawable: z.string().transform(transformOptionalTokenAmount), + reputation: reputationSchema, + totalAmountReceived: z.string().transform(transformOptionalTokenAmount), + payoutCount: z.number().or(z.string()), }); export type AddressDetailsWallet = z.infer; @@ -78,6 +84,10 @@ const operatorSchema = z.object({ .nullable(), amountStaked: z.string().optional().transform(transformOptionalTokenAmount), amountLocked: z.string().optional().transform(transformOptionalTokenAmount), + amountWithdrawable: z + .string() + .optional() + .transform(transformOptionalTokenAmount), lockedUntilTimestamp: z.string().optional(), reputation: reputationSchema, fee: z.number(), diff --git a/packages/apps/dashboard/client/src/services/api/use-hmt-price.tsx b/packages/apps/dashboard/client/src/services/api/use-hmt-price.tsx index 78232607d3..4a1ae8629b 100644 --- a/packages/apps/dashboard/client/src/services/api/use-hmt-price.tsx +++ b/packages/apps/dashboard/client/src/services/api/use-hmt-price.tsx @@ -20,7 +20,7 @@ export function useHMTPrice() { successHMTPriceResponseSchema ); - return validResponse; + return validResponse.hmtPrice; }, queryKey: ['useHMTPrice'], }); diff --git a/packages/apps/dashboard/client/src/services/api/use-kvstore-data.tsx b/packages/apps/dashboard/client/src/services/api/use-kvstore-data.tsx new file mode 100644 index 0000000000..55ef3228a4 --- /dev/null +++ b/packages/apps/dashboard/client/src/services/api/use-kvstore-data.tsx @@ -0,0 +1,36 @@ +import { useQuery } from '@tanstack/react-query'; + +import { apiPaths } from '@services/api-paths'; +import { httpService } from '@services/http-service'; +import { validateResponse } from '@services/validate-response'; +import { z } from 'zod'; +import { useWalletSearch } from '@utils/hooks/use-wallet-search'; + +const kvstoreDataSchema = z.array( + z.object({ + key: z.string(), + value: z.string(), + }) +); + +export type KvstoreData = z.infer; + +const useKvstoreData = () => { + const { filterParams } = useWalletSearch(); + + return useQuery({ + queryKey: ['kvstoreData', filterParams.address], + queryFn: async () => { + const { data } = await httpService.get( + `${apiPaths.kvstore.path}/${filterParams.address}`, + { params: { chain_id: filterParams.chainId || -1 } } + ); + + const validResponse = validateResponse(data, kvstoreDataSchema); + + return validResponse; + }, + }); +}; + +export default useKvstoreData; diff --git a/packages/apps/dashboard/client/src/theme.tsx b/packages/apps/dashboard/client/src/theme.tsx index 955fb4009c..d961419f4a 100644 --- a/packages/apps/dashboard/client/src/theme.tsx +++ b/packages/apps/dashboard/client/src/theme.tsx @@ -3,16 +3,17 @@ import { PaletteColorOptions, PaletteColor, } from '@mui/material/styles/createPalette'; -import { ThemeOptions } from '@mui/material'; +import { Shadows, ThemeOptions } from '@mui/material'; import { colorPalette } from '@assets/styles/color-palette'; import { CSSProperties } from 'react'; declare module '@mui/material/Typography' { interface TypographyPropsVariantOverrides { - ['Components/Button Small']: true; - ['Components/Button Large']: true; - ['Components/Chip']: true; - ['Components/Table Header']: true; + ['Button Small']: true; + ['Button Large']: true; + ['Chip']: true; + ['Table Header']: true; + ['Tooltip']: true; ['H6-Mobile']: true; body3: true; } @@ -20,20 +21,22 @@ declare module '@mui/material/Typography' { declare module '@mui/material/styles' { interface TypographyVariants { - ['Components/Button Small']: CSSProperties; - ['Components/Button Large']: CSSProperties; - ['Components/Chip']: CSSProperties; - ['Components/Table Header']: CSSProperties; + ['Button Small']: CSSProperties; + ['Button Large']: CSSProperties; + ['Chip']: CSSProperties; + ['Table Header']: CSSProperties; + ['Tooltip']: CSSProperties; ['H6-Mobile']: CSSProperties; body3: CSSProperties; } // allow configuration using `createTheme` interface TypographyVariantsOptions { - ['Components/Button Small']?: CSSProperties; - ['Components/Button Large']?: CSSProperties; - ['Components/Chip']?: CSSProperties; - ['Components/Table Header']?: CSSProperties; + ['Button Small']?: CSSProperties; + ['Button Large']?: CSSProperties; + ['Chip']?: CSSProperties; + ['Table Header']?: CSSProperties; + ['Tooltip']?: CSSProperties; ['H6-Mobile']: CSSProperties; body3?: CSSProperties; } @@ -43,12 +46,10 @@ declare module '@mui/material/styles' { interface Palette { sky: PaletteColor; white: PaletteColor; - textSecondary: PaletteColor; } interface PaletteOptions { sky?: PaletteColorOptions; white?: PaletteColorOptions; - textSecondary?: PaletteColorOptions; } } @@ -56,7 +57,6 @@ declare module '@mui/material/Button' { interface ButtonPropsColorOverrides { sky: true; white: true; - textSecondary: true; } } @@ -64,7 +64,6 @@ declare module '@mui/material/IconButton' { interface IconButtonPropsColorOverrides { sky: true; white: true; - textSecondary: true; } } @@ -72,7 +71,6 @@ declare module '@mui/material/SvgIcon' { interface SvgIconPropsColorOverrides { sky: true; white: true; - textSecondary: true; } } @@ -102,12 +100,11 @@ const theme: ThemeOptions = createTheme({ contrastText: colorPalette.sky.contrastText, }, white: { - main: '#fff', - light: '#fff', - dark: '#fff', - contrastText: '#fff', + main: '#ffffff', + light: '#ffffff', + dark: '#f6f7fe', + contrastText: '#ffffff', }, - textSecondary: colorPalette.textSecondary, }, typography: { fontFamily: 'Inter, Arial, sans-serif', @@ -120,7 +117,7 @@ const theme: ThemeOptions = createTheme({ }, h3: { fontSize: 24, - fontWeight: 500, + fontWeight: 600, '@media (max-width:600px)': { fontSize: 20, }, @@ -159,28 +156,28 @@ const theme: ThemeOptions = createTheme({ letterSpacing: '0.4px', textAlign: 'left', }, - 'Components/Button Small': { + 'Button Small': { fontSize: '13px', fontWeight: 600, lineHeight: '22px', letterSpacing: '0.1px', textAlign: 'left', }, - 'Components/Button Large': { + 'Button Large': { fontSize: '15px', fontWeight: 600, lineHeight: '26px', letterSpacing: '0.1px', textAlign: 'left', }, - 'Components/Chip': { + Chip: { fontSize: '13px', fontWeight: 400, lineHeight: '18px', letterSpacing: '0.16px', textAlign: 'left', }, - 'Components/Table Header': { + 'Table Header': { fontFamily: 'Roboto', fontSize: '14px', fontWeight: 500, @@ -188,6 +185,11 @@ const theme: ThemeOptions = createTheme({ letterSpacing: '0.17px', textAlign: 'left', }, + Tooltip: { + fontSize: 10, + fontWeight: 500, + lineHeight: '14px', + }, subtitle1: { fontSize: 12, }, @@ -197,9 +199,20 @@ const theme: ThemeOptions = createTheme({ lineHeight: '21.9px', }, caption: { - fontSize: 10, + fontSize: 12, + fontWeight: 400, + lineHeight: 5 / 3, + letterSpacing: 0.4, }, }, + shadows: [ + ...createTheme({}).shadows.map((shadow, i) => { + if (i === 2) { + return '0px 3px 1px -2px #e9ebfa, 0px 2px 2px 0px rgba(233, 235, 250, 0.50), 0px 1px 5px 0px rgba(233, 235, 250, 0.20)'; + } + return shadow; + }), + ] as Shadows, components: { MuiButton: { styleOverrides: { diff --git a/packages/apps/dashboard/client/src/utils/hooks/use-breakpoints.tsx b/packages/apps/dashboard/client/src/utils/hooks/use-breakpoints.tsx new file mode 100644 index 0000000000..d024c42b44 --- /dev/null +++ b/packages/apps/dashboard/client/src/utils/hooks/use-breakpoints.tsx @@ -0,0 +1,54 @@ +import useMediaQuery from '@mui/material/useMediaQuery'; + +type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; + +export const breakpoints = { + xs: '(max-width: 600px)', + sm: '(min-width: 601px) and (max-width: 900px)', + md: '(min-width: 901px) and (max-width: 1200px)', + lg: '(min-width: 1201px) and (max-width: 1536px)', + xl: '(min-width: 1537px)', +} as const; + +export type BreakpointResult = { + [K in Breakpoint]: { + isActive: boolean; + mediaQuery: string; + }; +}; + +const useBreakpoints = (): BreakpointResult => { + const matchesXs = useMediaQuery(breakpoints.xs); + const matchesSm = useMediaQuery(breakpoints.sm); + const matchesMd = useMediaQuery(breakpoints.md); + const matchesLg = useMediaQuery(breakpoints.lg); + const matchesXl = useMediaQuery(breakpoints.xl); + + return { + xs: { + isActive: matchesXs, + mediaQuery: `@media ${breakpoints.xs}`, + }, + sm: { + isActive: matchesSm, + mediaQuery: `@media ${breakpoints.sm}`, + }, + md: { + isActive: matchesMd, + mediaQuery: `@media ${breakpoints.md}`, + }, + lg: { + isActive: matchesLg, + mediaQuery: `@media ${breakpoints.lg}`, + }, + xl: { + isActive: matchesXl, + mediaQuery: `@media ${breakpoints.xl}`, + }, + }; +}; + +export const useIsMobile = () => { + const { xs, sm } = useBreakpoints(); + return xs.isActive || sm.isActive; +}; diff --git a/packages/apps/dashboard/client/src/utils/hooks/use-graph-page-chart-params.tsx b/packages/apps/dashboard/client/src/utils/hooks/use-graph-page-chart-params.tsx index abe615113f..0869e4dc69 100644 --- a/packages/apps/dashboard/client/src/utils/hooks/use-graph-page-chart-params.tsx +++ b/packages/apps/dashboard/client/src/utils/hooks/use-graph-page-chart-params.tsx @@ -3,35 +3,35 @@ import { create } from 'zustand'; const MINIMAL_DATE_FOR_DATE_PICKER = '2021-04-06'; -export type GraphPageChartPeriodName = '1W' | '1M' | '6M' | '1Y' | 'ALL'; +export type GraphPageChartPeriodName = '24H' | '1W' | '2W' | '1M' | 'ALL'; export type TimePeriod = { value: Dayjs; name: GraphPageChartPeriodName; }; +const oneDayAgo = dayjs().subtract(1, 'day'); const oneWeekAgo = dayjs().subtract(1, 'week'); +const twoWeeksAgo = dayjs().subtract(2, 'weeks'); const oneMonthAgo = dayjs().subtract(1, 'month'); -const sixMonthsAgo = dayjs().subtract(6, 'months'); -const oneYearAgo = dayjs().subtract(1, 'year'); export const initialAllTime = dayjs(MINIMAL_DATE_FOR_DATE_PICKER); export const TIME_PERIOD_OPTIONS: TimePeriod[] = [ { - value: oneWeekAgo, - name: '1W', + value: oneDayAgo, + name: '24H', }, { - value: oneMonthAgo, - name: '1M', + value: oneWeekAgo, + name: '1W', }, { - value: sixMonthsAgo, - name: '6M', + value: twoWeeksAgo, + name: '2W', }, { - value: oneYearAgo, - name: '1Y', + value: oneMonthAgo, + name: '1M', }, { value: initialAllTime, @@ -95,6 +95,7 @@ export const useGraphPageChartParams = create((set) => ({ dateRangeParams: { ...state.dateRangeParams, from: timePeriod.value, + to: dayjs(), }, }; }); diff --git a/packages/apps/dashboard/client/src/utils/hooks/use-is-mobile.tsx b/packages/apps/dashboard/client/src/utils/hooks/use-is-mobile.tsx deleted file mode 100644 index b0c520f018..0000000000 --- a/packages/apps/dashboard/client/src/utils/hooks/use-is-mobile.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import useMediaQuery from '@mui/material/useMediaQuery'; - -const breakpoints = { - mobile: `(max-width: 1100px)`, -}; - -export function useBreakPoints() { - const matchesMobile = useMediaQuery(breakpoints.mobile); - return { - mobile: { - isMobile: matchesMobile, - mediaQuery: `@media ${breakpoints.mobile}`, - }, - }; -}