Skip to content

feat: jurors page #1840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ed63810
feat: initial jurors page setup, jurors explore navlink, small stylin…
kemuru Jan 20, 2025
1b22294
feat: filter by totalresolvedvotes bigger than 0, types fix
kemuru Jan 21, 2025
63c308b
fix: subgraph bug which has not counting missed votes
kemuru Jan 22, 2025
ac069a3
Merge branch 'dev' into feat(web)/jurors-page
kemuru Jan 22, 2025
118feb6
Merge branch 'dev' into feat(web)/jurors-page
kemuru Jan 22, 2025
af51757
Merge branch 'dev' into feat(web)/jurors-page
kemuru Jan 22, 2025
db29a3d
feat: myprofile links, subgraph changes, pagination, query optimizati…
kemuru Jan 25, 2025
c95ee8a
Merge branch 'dev' into feat(web)/jurors-page
kemuru Jan 25, 2025
f2867a2
feat: add subgraph field, ranking icon, fix extra stats bug, filters,…
kemuru Jan 27, 2025
c749b2d
fix: nitpick text change
kemuru Jan 27, 2025
132743a
chore: add arrow back into the accordiontitle
kemuru Jan 27, 2025
07f83fa
chore: layout improvement
kemuru Jan 27, 2025
94c7637
fix: search to lower case in query
kemuru Jan 28, 2025
22e54d7
chore: move coherence percent function to utils, change name for clarity
kemuru Jan 28, 2025
81a3412
fix: layout shift if there is no rank, hide pagination if searching
kemuru Jan 28, 2025
b5d969b
Merge branch 'dev' into feat(web)/jurors-page
kemuru Jan 28, 2025
535508a
fix: few code smells
kemuru Jan 28, 2025
d04f0e1
chore: change label in mobile if search is active
kemuru Jan 28, 2025
876e208
Merge branch 'dev' into feat(web)/jurors-page
alcercu Jan 29, 2025
e6875eb
chore: subgraphs redeploy, scripts tweaks
jaybuidl Jan 30, 2025
2bb0a19
chore: txt
kemuru Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import QueryClientProvider from "context/QueryClientProvider";
import StyledComponentsProvider from "context/StyledComponentsProvider";
const Home = lazy(() => import("./pages/Home"));
const Cases = lazy(() => import("./pages/Cases"));
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Profile = lazy(() => import("./pages/Profile"));
const Courts = lazy(() => import("./pages/Courts"));
const Jurors = lazy(() => import("./pages/Jurors"));
const DisputeResolver = lazy(() => import("./pages/Resolver"));
const GetPnk = lazy(() => import("./pages/GetPnk"));
const Settings = lazy(() => import("./pages/Settings"));
Expand Down Expand Up @@ -64,10 +65,18 @@ const App: React.FC = () => {
}
/>
<Route
path="dashboard/:page/:order/:filter"
path="jurors/*"
element={
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
<Dashboard />
<Jurors />
</Suspense>
}
/>
<Route
path="profile/:page/:order/:filter"
element={
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
<Profile />
</Suspense>
}
/>
Expand Down
5 changes: 2 additions & 3 deletions web/src/components/EvidenceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { Card } from "@kleros/ui-components-library";

import AttachmentIcon from "svgs/icons/attachment.svg";

import { DEFAULT_CHAIN, getChain } from "consts/chains";
import { formatDate } from "utils/date";
import { getIpfsUrl } from "utils/getIpfsUrl";
import { shortenAddress } from "utils/shortenAddress";
Expand Down Expand Up @@ -224,7 +223,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
description,
fileURI,
}) => {
const dashboardLink = `/dashboard/1/desc/all?address=${sender}`;
const profileLink = `/profile/1/desc/all?address=${sender}`;

const transactionExplorerLink = useMemo(() => {
return getTxnExplorerLink(transactionHash ?? "");
Expand All @@ -249,7 +248,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
<BottomLeftContent>
<AccountContainer>
<Identicon size="24" string={sender} />
<InternalLink to={dashboardLink}>
<InternalLink to={profileLink}>
<Address>{shortenAddress(sender)}</Address>
</InternalLink>
</AccountContainer>
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/Popup/MiniGuides/JurorLevels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { Card as _Card } from "@kleros/ui-components-library";

import { landscapeStyle } from "styles/landscapeStyle";

import Coherence from "pages/Dashboard/JurorInfo/Coherence";
import PixelArt from "pages/Dashboard/JurorInfo/PixelArt";
import Coherence from "pages/Profile/JurorInfo/Coherence";
import PixelArt from "pages/Profile/JurorInfo/PixelArt";

import Template from "./MainStructureTemplate";
import { Title, ParagraphsContainer, LeftContentContainer } from "./PageContentsTemplate";
Expand Down
2 changes: 1 addition & 1 deletion web/src/layout/Header/navbar/Explore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const links = [
{ to: "/", text: "Home" },
{ to: "/cases/display/1/desc/all", text: "Cases" },
{ to: "/courts", text: "Courts" },
{ to: "/dashboard/1/desc/all", text: "Dashboard" },
{ to: "/jurors", text: "Jurors" },
{ to: "/get-pnk", text: "Get PNK" },
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ const AccordionTitle: React.FC<{
commited: boolean;
hiddenVotes: boolean;
}> = ({ juror, choice, voteCount, period, answers, isActiveRound, commited, hiddenVotes }) => {
const dashboardLink = `/dashboard/1/desc/all?address=${juror}`;
const profileLink = `/profile/1/desc/all?address=${juror}`;

return (
<TitleContainer>
<AddressContainer>
<Identicon size="20" string={juror} />
<StyledInternalLink to={dashboardLink}>
<StyledInternalLink to={profileLink}>
<StyledLabel variant="secondaryText">{shortenAddress(juror)}</StyledLabel>
</StyledInternalLink>
</AddressContainer>
Expand Down
3 changes: 3 additions & 0 deletions web/src/pages/Courts/CourtDetails/TopSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ const SearchResultsContainer = styled(OverlayScrollbarsComponent)`
overflow-y: auto;
z-index: 1;
background-color: ${({ theme }) => theme.whiteBackground};
border-top-left-radius: 0;
border-top-right-radius: 0;
`;

const StyledCard = styled(Card)<{ selected: boolean }>`
Expand All @@ -79,6 +81,7 @@ const StyledCard = styled(Card)<{ selected: boolean }>`
border: none;
border-left: ${({ selected, theme }) => (selected ? `3px solid ${theme.primaryBlue}` : "none")};
background-color: ${({ selected, theme }) => (selected ? theme.mediumBlue : "transparent")};
border-radius: 0;

:hover {
background-color: ${({ theme }) => theme.mediumBlue};
Expand Down
2 changes: 1 addition & 1 deletion web/src/pages/Home/TopJurors/JurorCard/JurorLevel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getUserLevelData } from "utils/userLevelCalculation";

import { landscapeStyle } from "styles/landscapeStyle";

import PixelArt from "pages/Dashboard/JurorInfo/PixelArt";
import PixelArt from "pages/Profile/JurorInfo/PixelArt";

const Container = styled.div`
display: flex;
Expand Down
4 changes: 2 additions & 2 deletions web/src/pages/Home/TopJurors/JurorCard/JurorTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ interface IJurorTitle {
}

const JurorTitle: React.FC<IJurorTitle> = ({ address }) => {
const dashboardLink = `/dashboard/1/desc/all?address=${address}`;
const profileLink = `/profile/1/desc/all?address=${address}`;

return (
<Container>
<IdenticonOrAvatar address={address} />
<StyledInternalLink to={dashboardLink}>
<StyledInternalLink to={profileLink}>
<AddressOrName address={address} />
</StyledInternalLink>
</Container>
Expand Down
4 changes: 2 additions & 2 deletions web/src/pages/Home/TopJurors/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Title = styled.h1`
font-size: ${responsiveSize(20, 24)};
`;

const ListContainer = styled.div`
export const ListContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
Expand All @@ -35,7 +35,7 @@ const ListContainer = styled.div`
)}
`;

const StyledLabel = styled.label`
export const StyledLabel = styled.label`
font-size: 16px;
`;

Expand Down
76 changes: 76 additions & 0 deletions web/src/pages/Jurors/Search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useRef, useState } from "react";
import styled, { css } from "styled-components";

import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import { useDebounce } from "react-use";
import { Searchbar } from "@kleros/ui-components-library";

import { isEmpty } from "utils/index";
import { decodeURIFilter, encodeURIFilter, useRootPath } from "utils/uri";

import { landscapeStyle } from "styles/landscapeStyle";
import { responsiveSize } from "styles/responsiveSize";

const Container = styled.div`
display: flex;
flex-direction: column;
gap: ${responsiveSize(8, 16)};

${landscapeStyle(
() => css`
flex-direction: row;
`
)}
`;

const StyledSearchbar = styled(Searchbar)`
flex: 1;
flex-basis: 310px;

input {
font-size: 16px;
height: 45px;
padding-top: 0px;
padding-bottom: 0px;
}
`;

const Search: React.FC = () => {
const { page, order, filter } = useParams();
const location = useRootPath();
const decodedFilter = decodeURIFilter(filter ?? "all");
const { id: searchValue, ...filterObject } = decodedFilter;
const [search, setSearch] = useState(searchValue ?? "");
const initialRenderRef = useRef(true);
const navigate = useNavigate();
const [searchParams] = useSearchParams();

useDebounce(
() => {
if (initialRenderRef.current && isEmpty(search)) {
initialRenderRef.current = false;
return;
}
initialRenderRef.current = false;
const newFilters = isEmpty(search) ? { ...filterObject } : { ...filterObject, id: search };
const encodedFilter = encodeURIFilter(newFilters);
navigate(`${location}/${page}/${order}/${encodedFilter}?${searchParams.toString()}`);
},
500,
[search]
);

return (
<Container>
<StyledSearchbar
dir="auto"
type="text"
placeholder="Search"
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
</Container>
);
};

export default Search;
28 changes: 28 additions & 0 deletions web/src/pages/Jurors/Stats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import styled from "styled-components";

const FieldWrapper = styled.div`
display: inline-flex;
gap: 8px;
`;

const StyledLabel = styled.label`
color: ${({ theme }) => theme.primaryText};
`;

const Field: React.FC<{ label: string; value: string }> = ({ label, value }) => (
<FieldWrapper>
<StyledLabel>{label}</StyledLabel>
<small>{value}</small>
</FieldWrapper>
);

export interface IStats {
totalJurors: number;
}

const Stats: React.FC<IStats> = ({ totalJurors }) => {
return <Field label="Total" value={`${totalJurors} Jurors`} />;
};

export default Stats;
22 changes: 22 additions & 0 deletions web/src/pages/Jurors/StatsAndFilters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import styled from "styled-components";

import { responsiveSize } from "styles/responsiveSize";
import Stats, { IStats } from "./Stats";

const Container = styled.div`
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: ${responsiveSize(4, 8)};
margin-bottom: ${responsiveSize(16, 32)};
justify-content: space-between;
`;

const StatsAndFilters: React.FC<IStats> = ({ totalJurors }) => (
<Container>
<Stats {...{ totalJurors }} />
</Container>
);

export default StatsAndFilters;
65 changes: 65 additions & 0 deletions web/src/pages/Jurors/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "react";
import styled, { css } from "styled-components";

import { MAX_WIDTH_LANDSCAPE, landscapeStyle } from "styles/landscapeStyle";
import { responsiveSize } from "styles/responsiveSize";

import { isUndefined } from "utils/index";

import { useTopUsersByCoherenceScore } from "queries/useTopUsersByCoherenceScore";

import { SkeletonDisputeListItem } from "components/StyledSkeleton";
import Search from "./Search";
import StatsAndFilters from "./StatsAndFilters";
import JurorCard from "../Home/TopJurors/JurorCard";
import { ListContainer, StyledLabel } from "../Home/TopJurors";
import Header from "../Home/TopJurors/Header";

const Container = styled.div`
width: 100%;
background-color: ${({ theme }) => theme.lightBackground};
padding: 32px 16px 40px;
max-width: ${MAX_WIDTH_LANDSCAPE};
margin: 0 auto;

${landscapeStyle(
() => css`
padding: 48px ${responsiveSize(0, 132)} 60px;
`
)}
`;

const StyledTitle = styled.h1`
margin: 0px;
font-size: ${responsiveSize(20, 24)};
`;

const Jurors: React.FC = () => {
const { data: queryJurors } = useTopUsersByCoherenceScore(1000);

const topJurors = queryJurors?.users?.map((juror, index) => ({
...juror,
rank: index + 1,
}));

return (
<Container>
<StyledTitle>Jurors Leaderboard</StyledTitle>
<Search />
<StatsAndFilters totalJurors={0} />

{!isUndefined(topJurors) && topJurors.length === 0 ? (
<StyledLabel>There are no jurors staked yet.</StyledLabel>
) : (
<ListContainer>
<Header />
{!isUndefined(topJurors)
? topJurors.map((juror) => <JurorCard key={juror.rank} address={juror.id} {...juror} />)
: [...Array(5)].map((_, i) => <SkeletonDisputeListItem key={i} />)}
</ListContainer>
)}
</Container>
);
};

export default Jurors;
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const Header: React.FC<IHeader> = ({
return (
<Container>
<StyledTitle>
Juror Dashboard -
Juror Profile -
<Copiable copiableContent={addressToQuery} info="Copy Address">
<StyledExternalLink to={addressExplorerLink} target="_blank" rel="noopener noreferrer">
{shortenAddress(addressToQuery)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const ConnectWalletContainer = styled.div`
color: ${({ theme }) => theme.primaryText};
`;

const Dashboard: React.FC = () => {
const Profile: React.FC = () => {
const { isConnected, address: connectedAddress } = useAccount();
const { page, order, filter } = useParams();
const [searchParams] = useSearchParams();
Expand Down Expand Up @@ -97,7 +97,7 @@ const Dashboard: React.FC = () => {
</>
) : (
<ConnectWalletContainer>
To see your dashboard, connect first
To see your profile, connect first
<hr />
<ConnectWallet />
</ConnectWalletContainer>
Expand All @@ -108,4 +108,4 @@ const Dashboard: React.FC = () => {
);
};

export default Dashboard;
export default Profile;
Loading